mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-25 01:13:25 +01:00
missing json and jquery stuff for egw_tail
This commit is contained in:
parent
41e4581c30
commit
aeab9cc5aa
108
json.php
Normal file
108
json.php
Normal file
@ -0,0 +1,108 @@
|
||||
<?php
|
||||
/**
|
||||
* eGroupWare - general JSON handler for EGroupware
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage ajax
|
||||
* @author Andreas Stoeckel <as@stylite.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* callback if the session-check fails, redirects via xajax to login.php
|
||||
*
|
||||
* @param array &$anon_account anon account_info with keys 'login', 'passwd' and optional 'passwd_type'
|
||||
* @return boolean/string true if we allow anon access and anon_account is set, a sessionid or false otherwise
|
||||
*/
|
||||
function xajax_redirect(&$anon_account)
|
||||
{
|
||||
$response = new egw_json_response();
|
||||
$response->redirect($GLOBALS['egw_info']['server']['webserver_url'].'/login.php?cd=10', true);
|
||||
$response->printOutput();
|
||||
|
||||
common::egw_exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception handler for xajax, return the message (and trace, if enabled) as alert() to the user
|
||||
*
|
||||
* Does NOT return!
|
||||
*
|
||||
* @param Exception $e
|
||||
*/
|
||||
function ajax_exception_handler(Exception $e)
|
||||
{
|
||||
// logging all exceptions to the error_log
|
||||
if (function_exists('_egw_log_exception'))
|
||||
{
|
||||
_egw_log_exception($e,$message);
|
||||
}
|
||||
$response = new egw_json_response();
|
||||
$message .= ($message ? "\n\n" : '').$e->getMessage();
|
||||
|
||||
// only show trace (incl. function arguments) if explicitly enabled, eg. on a development system
|
||||
if ($GLOBALS['egw_info']['server']['exception_show_trace'])
|
||||
{
|
||||
$message .= "\n\n".$e->getTraceAsString();
|
||||
}
|
||||
$response->alert($message);
|
||||
$response->printOutput();
|
||||
|
||||
if (is_object($GLOBALS['egw']))
|
||||
{
|
||||
common::egw_exit();
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
// set our own exception handler, to not get the html from eGW's default one
|
||||
set_exception_handler('ajax_exception_handler');
|
||||
|
||||
if (isset($_GET['menuaction']))
|
||||
{
|
||||
if (strpos($_GET['menuaction'],'::') !== false && strpos($_GET['menuaction'],'.') === false) // static method name app_something::method
|
||||
{
|
||||
@list($className,$functionName,$handler) = explode('::',$_GET['menuaction']);
|
||||
list($appName) = explode('_',$className);
|
||||
}
|
||||
else
|
||||
{
|
||||
@list($appName, $className, $functionName, $handler) = explode('.',$_GET['menuaction']);
|
||||
}
|
||||
//error_log("json.php: appName=$appName, className=$className, functionName=$functionName, handler=$handler");
|
||||
|
||||
$GLOBALS['egw_info'] = array(
|
||||
'flags' => array(
|
||||
'currentapp' => $appName,
|
||||
'noheader' => True,
|
||||
'disable_Template_class' => True,
|
||||
'autocreate_session_callback' => 'xajax_redirect',
|
||||
'no_exception_handler' => true, // we already installed our own
|
||||
'no_dla_update' => $appName == 'notifications', // otherwise session never time out
|
||||
)
|
||||
);
|
||||
//if ($_GET['menuaction'] !='notifications.notifications_ajax.get_notifications') error_log(__METHOD__.__LINE__.' Appname:'.$appName.' Action:'.print_r($_GET['menuaction'],true));
|
||||
if ($_GET['menuaction']=='felamimail.ajaxfelamimail.refreshMessageList' ||
|
||||
$_GET['menuaction']=='felamimail.ajaxfelamimail.refreshFolderList')
|
||||
{
|
||||
$GLOBALS['egw_info']['flags']['no_dla_update']=true;
|
||||
}
|
||||
include('./header.inc.php');
|
||||
|
||||
|
||||
//Create a new json handler
|
||||
$json = new egw_json_request();
|
||||
|
||||
//Check whether the request data is set
|
||||
if (isset($GLOBALS['egw_unset_vars']['_POST[json_data]']))
|
||||
{
|
||||
throw new egw_exception_assertion_failed("JSON Data contains script tags. Aborting...");
|
||||
}
|
||||
$json->parseRequest($_GET['menuaction'], (array)$_POST['json_data']);
|
||||
egw_json_response::get();
|
||||
common::egw_exit();
|
||||
}
|
||||
|
||||
throw new Exception($_SERVER['PHP_SELF'] . ' Invalid AJAX JSON Request');
|
511
phpgwapi/inc/class.egw_json.inc.php
Normal file
511
phpgwapi/inc/class.egw_json.inc.php
Normal file
@ -0,0 +1,511 @@
|
||||
<?php
|
||||
/**
|
||||
* eGroupWare API: JSON - Contains functions and classes for doing JSON requests.
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage ajax
|
||||
* @author Andreas Stoeckel <as@stylite.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class handling JSON requests to the server
|
||||
*/
|
||||
class egw_json_request
|
||||
{
|
||||
|
||||
private static $_hadJSONRequest = false;
|
||||
|
||||
public static function isJSONRequest()
|
||||
{
|
||||
return self::$_hadJSONRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the raw input data supplied with the input_data parameter and calls the menuaction
|
||||
* passing all parameters supplied in the request to it.
|
||||
*
|
||||
* @param string menuaction to call
|
||||
* @param string $input_data is the RAW input data as it was received from the client
|
||||
*/
|
||||
public function parseRequest($menuaction, $input_data)
|
||||
{
|
||||
// Remember that we currently are in a JSON request - e.g. used in the redirect code
|
||||
self::$_hadJSONRequest = true;
|
||||
|
||||
if (empty($input_data))
|
||||
{
|
||||
$this->handleRequest($menuaction, array());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (get_magic_quotes_gpc())
|
||||
{
|
||||
$input_data[0] = stripslashes($input_data[0]);
|
||||
}
|
||||
|
||||
//Decode the JSON input data into associative arrays
|
||||
if (($json = json_decode($input_data[0], true)) !== false)
|
||||
{
|
||||
$parameters = array();
|
||||
|
||||
//Get the request array
|
||||
if (isset($json['request']))
|
||||
{
|
||||
$request = $json['request'];
|
||||
|
||||
//Check whether any parameters were supplied along with the request
|
||||
if (isset($request['parameters']))
|
||||
{
|
||||
$parameters = $request['parameters'];
|
||||
}
|
||||
}
|
||||
//Call the supplied callback function along with the menuaction and the passed parameters
|
||||
$this->handleRequest($menuaction, $parameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request handler
|
||||
*
|
||||
* @param string $menuaction
|
||||
* @param array $parameters
|
||||
*/
|
||||
public function handleRequest($menuaction, array $parameters)
|
||||
{
|
||||
if (strpos($menuaction,'::') !== false && strpos($menuaction,'.') === false) // static method name app_something::method
|
||||
{
|
||||
@list($className,$functionName,$handler) = explode('::',$menuaction);
|
||||
list($appName) = explode('_',$className);
|
||||
}
|
||||
else
|
||||
{
|
||||
@list($appName, $className, $functionName, $handler) = explode('.',$menuaction);
|
||||
}
|
||||
//error_log("json.php: appName=$appName, className=$className, functionName=$functionName, handler=$handler");
|
||||
|
||||
switch($handler)
|
||||
{
|
||||
case '/etemplate/process_exec':
|
||||
$_GET['menuaction'] = $appName.'.'.$className.'.'.$functionName;
|
||||
$appName = $className = 'etemplate';
|
||||
$functionName = 'process_exec';
|
||||
$menuaction = 'etemplate.etemplate.process_exec';
|
||||
|
||||
$parameters = array(
|
||||
$parameters[0]['etemplate_exec_id'],
|
||||
$parameters[0]['submit_button'],
|
||||
$parameters[0],
|
||||
'xajaxResponse',
|
||||
);
|
||||
//error_log("xajax_doXMLHTTP() /etemplate/process_exec handler: arg0='$menuaction', menuaction='$_GET[menuaction]'");
|
||||
break;
|
||||
case 'etemplate': // eg. ajax code in an eTemplate widget
|
||||
$menuaction = ($appName = 'etemplate').'.'.$className.'.'.$functionName;
|
||||
break;
|
||||
case 'template':
|
||||
$menuaction = $appName.'.'.$className.'.'.$functionName;
|
||||
list($template) = explode('_', $className);
|
||||
break;
|
||||
}
|
||||
|
||||
if(substr($className,0,4) != 'ajax' && substr($className,-4) != 'ajax' &&
|
||||
$menuaction != 'etemplate.etemplate.process_exec' && substr($functionName,0,4) != 'ajax' ||
|
||||
!preg_match('/^[A-Za-z0-9_-]+(\.[A-Za-z0-9_]+\.|::)[A-Za-z0-9_]+$/',$menuaction))
|
||||
{
|
||||
// stopped for security reasons
|
||||
error_log($_SERVER['PHP_SELF']. ' stopped for security reason. '.$menuaction.' is not valid. class- or function-name must start with ajax!!!');
|
||||
// send message also to the user
|
||||
throw new Exception($_SERVER['PHP_SELF']. ' stopped for security reason. '.$menuaction.' is not valid. class- or function-name must start with ajax!!!');
|
||||
exit;
|
||||
}
|
||||
|
||||
if (isset($template))
|
||||
{
|
||||
if (!class_exists($className)) require_once(EGW_SERVER_ROOT.'/phpgwapi/templates/'.$template.'/class.'.$className.'.inc.php');
|
||||
$ajaxClass = new $className;
|
||||
}
|
||||
else
|
||||
{
|
||||
$ajaxClass = CreateObject($appName.'.'.$className);
|
||||
}
|
||||
|
||||
// for Ajax: no need to load the "standard" javascript files,
|
||||
// they are already loaded, in fact jquery has a problem if loaded twice
|
||||
//egw_framework::js_files(array());
|
||||
|
||||
$parameters = translation::convert($parameters, 'utf-8');
|
||||
|
||||
call_user_func_array(array($ajaxClass, $functionName), $parameters);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class used to send ajax responses
|
||||
*/
|
||||
class egw_json_response
|
||||
{
|
||||
/**
|
||||
* A response can only contain one generic data part.
|
||||
* This variable is used to store, whether a data part had already been added to the response.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
private $hasData = false;
|
||||
|
||||
/**
|
||||
* Array containing all beforeSendData callbacks
|
||||
*/
|
||||
protected $beforeSendDataProcs = array();
|
||||
|
||||
/**
|
||||
* Holds the actual response data which is then encoded to JSON
|
||||
* once the "getJSON" function is called
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $responseArray = array();
|
||||
|
||||
/**
|
||||
* Holding instance of class for singelton egw_json_response::get()
|
||||
*
|
||||
* @var egw_json_response
|
||||
*/
|
||||
private static $response = null;
|
||||
|
||||
/**
|
||||
* Singelton for class
|
||||
*
|
||||
* @return egw_json_response
|
||||
*/
|
||||
public static function get()
|
||||
{
|
||||
if (!isset(self::$response))
|
||||
{
|
||||
self::$response = new egw_json_response();
|
||||
}
|
||||
return self::$response;
|
||||
}
|
||||
|
||||
public static function isJSONResponse()
|
||||
{
|
||||
return isset(self::$response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Private function used to send the HTTP header of the JSON response
|
||||
*/
|
||||
private function sendHeader()
|
||||
{
|
||||
//Send the character encoding header
|
||||
header('content-type: application/json; charset='.translation::charset());
|
||||
}
|
||||
|
||||
/**
|
||||
* Private function which is used to send the result via HTTP
|
||||
*/
|
||||
public function sendResult()
|
||||
{
|
||||
$inst = self::get();
|
||||
|
||||
//Call each attached before send data proc
|
||||
foreach ($inst->beforeSendDataProcs as $proc)
|
||||
call_user_func_array($proc['proc'], $proc['params']);
|
||||
|
||||
$inst->sendHeader();
|
||||
|
||||
echo $inst->getJSON();
|
||||
}
|
||||
|
||||
/**
|
||||
* xAjax compatibility function
|
||||
*/
|
||||
public function printOutput()
|
||||
{
|
||||
// do nothing, as output is triggered by destructor
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds any type of data to the response array
|
||||
*/
|
||||
protected function addGeneric($key, $data)
|
||||
{
|
||||
self::get()->responseArray[] = array(
|
||||
'type' => $key,
|
||||
'data' => $data,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a "data" response to the json response.
|
||||
*
|
||||
* This function may only be called once for a single JSON response object.
|
||||
*
|
||||
* @param object|array|string $data can be of any data type and will be added JSON Encoded to your response.
|
||||
*/
|
||||
public function data($data)
|
||||
{
|
||||
/* Only allow adding the data response once */
|
||||
$inst = self::get();
|
||||
if (!$inst->hasData)
|
||||
{
|
||||
$inst->addGeneric('data', $data);
|
||||
$inst->hasData = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Adding more than one data response to a JSON response is not allowed.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an "alert" to the response which can be handeled on the client side.
|
||||
*
|
||||
* The default implementation simply displays the text supplied here with the JavaScript function "alert".
|
||||
*
|
||||
* @param string $message contains the actual message being sent to the client.
|
||||
* @param string $details (optional) can be used to inform the user on the client side about additional details about the error. This might be information how the error can be resolved/why it was raised or simply some debug data.
|
||||
*/
|
||||
public function alert($message, $details = '')
|
||||
{
|
||||
if (is_string($message) && is_string($details))
|
||||
{
|
||||
$this->addGeneric('alert', array(
|
||||
"message" => $message,
|
||||
"details" => $details));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Invalid parameters supplied.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to add a generic java script to the response which will be executed upon the request gets received.
|
||||
*
|
||||
* @deprecated
|
||||
* @param string $script the script code which should be executed upon receiving
|
||||
*/
|
||||
public function script($script)
|
||||
{
|
||||
if (is_string($script))
|
||||
{
|
||||
$this->addGeneric('script', $script);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Invalid parameters supplied.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to add a global javascript function with giben parameters
|
||||
*
|
||||
* @param string $script the script code which should be executed upon receiving
|
||||
*/
|
||||
public function jquery($selector,$method,array $parameters=array())
|
||||
{
|
||||
if (is_string($selector) && is_string($method))
|
||||
{
|
||||
$this->addGeneric('jquery', array(
|
||||
'select' => $selector,
|
||||
'func' => $method,
|
||||
'parms' => $parameters,
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Invalid parameters supplied.");
|
||||
}
|
||||
}
|
||||
|
||||
public function generic($type, array $parameters = array())
|
||||
{
|
||||
if (is_string($type))
|
||||
{
|
||||
$this->addGeneric($type, $parameters);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Invalid parameters supplied.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an html assign to the response, which is excecuted upon the request is received.
|
||||
*
|
||||
* @param string $id id of dom element to modify
|
||||
* @param string $key attribute name of dom element which should be modified
|
||||
* @param string $value the value which should be assigned to the given attribute
|
||||
*/
|
||||
public function assign($id, $key, $value)
|
||||
{
|
||||
if (is_string($id) && is_string($key) && (is_string($value) || is_numeric($value) || is_null($value)))
|
||||
{
|
||||
$this->addGeneric('assign', array(
|
||||
'id' => $id,
|
||||
'key' => $key,
|
||||
'value' => $value,
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Invalid parameters supplied");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect to given url
|
||||
*
|
||||
* @param string $url
|
||||
* @param boolean $global specifies whether to redirect the whole framework
|
||||
* or only the current application
|
||||
*/
|
||||
public function redirect($url, $global = false)
|
||||
{
|
||||
if (is_string($url) && is_bool($global))
|
||||
{
|
||||
//self::script("location.href = '$url';");
|
||||
$this->addGeneric('redirect', array(
|
||||
'url' => $url,
|
||||
'global' => $global,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays an error message on the client
|
||||
*/
|
||||
public function error($msg)
|
||||
{
|
||||
if (is_string($msg))
|
||||
{
|
||||
$this->addGeneric('error', $msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Includes the given CSS file. Every url can only be included once.
|
||||
*
|
||||
* @param string $url specifies the url to the css file to include
|
||||
*/
|
||||
public function includeCSS($url)
|
||||
{
|
||||
if (is_string($url))
|
||||
{
|
||||
$this->addGeneric('css', $url);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Includes the given JS file. Every url can only be included once.
|
||||
*
|
||||
* @param string $url specifies the url to the css file to include
|
||||
*/
|
||||
public function includeScript($url)
|
||||
{
|
||||
if (is_string($url))
|
||||
{
|
||||
self::get()->addGeneric('js', $url);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the actual JSON code generated by calling the above "add" function.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getJSON()
|
||||
{
|
||||
$inst = self::get();
|
||||
|
||||
/* Wrap the result array into a parent "response" Object */
|
||||
$res = array('response' => $inst->responseArray);
|
||||
|
||||
return json_encode($res); //PHP5.3+, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function which can be used to add an event listener callback function to
|
||||
* the "beforeSendData" callback. This callback might be used to add a response
|
||||
* which always has to be added after all other responses.
|
||||
* @param callback Callback function or method which should be called before the response gets sent
|
||||
* @param mixed n Optional parameters which get passed to the callback function.
|
||||
*/
|
||||
public function addBeforeSendDataCallback($proc)
|
||||
{
|
||||
//Get the current instance
|
||||
$inst = self::get();
|
||||
|
||||
//Get all parameters passed to the function and delete the first one
|
||||
$params = func_get_args();
|
||||
array_shift($params);
|
||||
|
||||
$inst->beforeSendDataProcs[] = array(
|
||||
'proc' => $proc,
|
||||
'params' => $params
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
//Only send the response if this instance is the singleton instance
|
||||
if ($this == self::get())
|
||||
$this->sendResult();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated legacy xajax wrapper functions for the new egw_json interface
|
||||
*/
|
||||
class xajaxResponse extends egw_json_response
|
||||
{
|
||||
public function addScript($script)
|
||||
{
|
||||
$this->script($script);
|
||||
}
|
||||
|
||||
public function addAlert($message)
|
||||
{
|
||||
$this->alert($message, '');
|
||||
}
|
||||
|
||||
public function addAssign($id, $key, $value)
|
||||
{
|
||||
$this->assign($id, $key, $value);
|
||||
}
|
||||
|
||||
public function addRedirect($url)
|
||||
{
|
||||
$this->redirect($url);
|
||||
}
|
||||
|
||||
public function addScriptCall($func)
|
||||
{
|
||||
$args = func_get_args();
|
||||
$func = array_shift($args);
|
||||
|
||||
$this->script("try{window['".$func."'].apply(window, ".json_encode($args).");} catch(e) {_egw_json_debug_log(e);}");
|
||||
}
|
||||
|
||||
public function addIncludeCSS($url)
|
||||
{
|
||||
$this->includeCSS($url);
|
||||
}
|
||||
|
||||
public function addIncludeScript($url)
|
||||
{
|
||||
$this->includeScript($url);
|
||||
}
|
||||
|
||||
public function getXML()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
}
|
@ -162,6 +162,7 @@ class egw_tail
|
||||
|
||||
return '
|
||||
<script type="text/javascript">
|
||||
var egw_webserverUrl = "'.$GLOBALS['egw_info']['server']['webserver_url'].'";
|
||||
var '.$id.'_tail_start = 0;
|
||||
function button_'.$id.'(button)
|
||||
{
|
||||
|
@ -155,6 +155,8 @@ pre.tail { background-color: white; padding-left: 5px; margin-left: 5px; }
|
||||
';
|
||||
$header = str_replace('!','/',substr($filename,10+strlen($GLOBALS['egw_info']['user']['account_lid']),-4));
|
||||
$tail = new egw_tail($filename);
|
||||
$GLOBALS['egw']->js->validate_file('jquery','jquery');
|
||||
$GLOBALS['egw']->js->validate_file('.','egw_json');
|
||||
$GLOBALS['egw']->framework->render($tail->show($header),false,false);
|
||||
}
|
||||
}
|
746
phpgwapi/js/egw_json.js
Normal file
746
phpgwapi/js/egw_json.js
Normal file
@ -0,0 +1,746 @@
|
||||
/**
|
||||
* eGroupWare API: JSON - Contains the client side javascript implementation of class.egw_json.inc.php
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
* @package api
|
||||
* @subpackage ajax
|
||||
* @author Andreas Stoeckel <as@stylite.de>
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/* The egw_json_request is the javaScript side implementation of class.egw_json.inc.php.*/
|
||||
|
||||
function _egw_json_escape_string(input)
|
||||
{
|
||||
var len = input.length;
|
||||
var res = "";
|
||||
|
||||
for (var i = 0; i < len; i++)
|
||||
{
|
||||
switch (input.charAt(i))
|
||||
{
|
||||
case '"':
|
||||
res += '\\"';
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
res += '\\n';
|
||||
break;
|
||||
|
||||
case '\r':
|
||||
res += '\\r';
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
res += '\\\\';
|
||||
break;
|
||||
|
||||
case '\/':
|
||||
res += '\\/';
|
||||
break;
|
||||
|
||||
case '\b':
|
||||
res += '\\b';
|
||||
break;
|
||||
|
||||
case '\f':
|
||||
res += '\\f';
|
||||
break;
|
||||
|
||||
case '\t':
|
||||
res += '\\t';
|
||||
break;
|
||||
|
||||
default:
|
||||
res += input.charAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
function _egw_json_encode_simple(input)
|
||||
{
|
||||
switch (input.constructor)
|
||||
{
|
||||
case String:
|
||||
return '"' + _egw_json_escape_string(input) + '"';
|
||||
|
||||
case Number:
|
||||
return input.toString();
|
||||
|
||||
case Boolean:
|
||||
return input ? 'true' : 'false';
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function egw_json_encode(input)
|
||||
{
|
||||
if (input == null || !input && input.length == 0) return 'null';
|
||||
|
||||
var simple_res = _egw_json_encode_simple(input);
|
||||
if (simple_res == null)
|
||||
{
|
||||
switch (input.constructor)
|
||||
{
|
||||
case Array:
|
||||
var buf = [];
|
||||
for (var k in input)
|
||||
{
|
||||
//Filter non numeric entries
|
||||
if (!isNaN(k))
|
||||
buf.push(egw_json_encode(input[k]));
|
||||
}
|
||||
return '[' + buf.join(',') + ']';
|
||||
|
||||
case Object:
|
||||
var buf = [];
|
||||
for (var k in input)
|
||||
{
|
||||
buf.push(_egw_json_encode_simple(k) + ':' + egw_json_encode(input[k]));
|
||||
}
|
||||
return '{' + buf.join(',') + '}';
|
||||
|
||||
default:
|
||||
return 'null';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return simple_res;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Some variables needed to store which JS and CSS files have already be included
|
||||
*/
|
||||
var egw_json_files = {};
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the egw_json_files object with all files which are already bound in
|
||||
*/
|
||||
$j(document).ready(function() {
|
||||
$j("script, link").each(function() {
|
||||
var file = false;
|
||||
if ($j(this).attr("src")) {
|
||||
file = $j(this).attr("src");
|
||||
} else if ($j(this).attr("href")) {
|
||||
file = $j(this).attr("href");
|
||||
}
|
||||
if (file) {
|
||||
egw_json_files[file] = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Variable which stores all currently registered plugins
|
||||
*/
|
||||
var _egw_json_plugins = [];
|
||||
|
||||
/**
|
||||
* Register a plugin for the egw_json handler
|
||||
*/
|
||||
function egw_json_register_plugin(_callback, _context)
|
||||
{
|
||||
//Default the context parameter to "window"
|
||||
if (typeof _context == 'undefined') {
|
||||
_context = window;
|
||||
}
|
||||
|
||||
//Add a plugin object to the plugins array
|
||||
_egw_json_plugins[_egw_json_plugins.length] = {
|
||||
'callback': _callback,
|
||||
'context': _context
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used internally to pass a response to all registered plugins
|
||||
*/
|
||||
function _egw_json_plugin_handle(_type, _response) {
|
||||
for (var i = 0; i < _egw_json_plugins.length; i++)
|
||||
{
|
||||
try {
|
||||
var plugin = _egw_json_plugins[i];
|
||||
if (plugin.callback.call(plugin.context, _type, _response)) {
|
||||
return true;
|
||||
}
|
||||
} catch (e) {
|
||||
if (typeof console != 'undefined')
|
||||
{
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** The constructor of the egw_json_request class.
|
||||
*
|
||||
* @param string _menuaction the menuaction function which should be called and
|
||||
* which handles the actual request. If the menuaction is a full featured
|
||||
* url, this one will be used instead.
|
||||
* @param array _parameters which should be passed to the menuaction function.
|
||||
* @param object _context is the context which will be used for the callback function
|
||||
*/
|
||||
function egw_json_request(_menuaction, _parameters, _context)
|
||||
{
|
||||
this.context = window.document;
|
||||
if (typeof _context != 'undefined')
|
||||
this.context = _context;
|
||||
|
||||
if (typeof _parameters != 'undefined')
|
||||
{
|
||||
this.parameters = _parameters;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.parameters = new Array;
|
||||
}
|
||||
|
||||
// Check whether the supplied menuaction parameter is a full featured url
|
||||
// or just a menuaction
|
||||
if (_menuaction.match(/json.php\?menuaction=[a-z_0-9]*\.[a-z_0-9]*\.[a-z_0-9]*/i))
|
||||
{
|
||||
// Menuaction is a full featured url
|
||||
this.url = _menuaction
|
||||
}
|
||||
else
|
||||
{
|
||||
// We only got a menu action, assemble the url manually.
|
||||
this.url = this._assembleAjaxUrl(_menuaction);
|
||||
}
|
||||
|
||||
this.request = null;
|
||||
this.sender = null;
|
||||
this.callback = null;
|
||||
this.alertHandler = this.alertFunc;
|
||||
this.onLoadFinish = null;
|
||||
this.loadedJSFiles = {};
|
||||
this.handleResponseDone = false;
|
||||
this.app = null;
|
||||
if (window.egw_alertHandler)
|
||||
{
|
||||
this.alertHandler = window.egw_alertHandler;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the "application" object which is passed to egw_appWindowOpen when a redirect is done
|
||||
*/
|
||||
egw_json_request.prototype.setAppObject = function(_app)
|
||||
{
|
||||
this.app = _app;
|
||||
}
|
||||
|
||||
egw_json_request.prototype._assembleAjaxUrl = function(_menuaction)
|
||||
{
|
||||
// Retrieve the webserver url
|
||||
var webserver_url = window.egw_webserverUrl;
|
||||
|
||||
// Check whether the webserver_url is really set
|
||||
// Don't check for !webserver_url as it might be empty.
|
||||
// Thank you to Ingo Ratsdorf for reporting this.
|
||||
if (typeof webserver_url == "undefined")
|
||||
{
|
||||
throw "Internal JS error, top window not found, webserver url could not be retrieved.";
|
||||
}
|
||||
|
||||
// Add the ajax relevant parts
|
||||
return webserver_url + '/json.php?menuaction=' + _menuaction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the AJAX JSON request.
|
||||
*
|
||||
* @param boolean _async specifies whether the request should be handeled asynchronously (true, the sendRequest function immediately returns to the caller) or asynchronously (false, the sendRequest function waits until the request is received)
|
||||
* @param _callback is an additional callback function which should be called upon a "data" response is received
|
||||
* @param _sender is the reference object the callback function should get
|
||||
*/
|
||||
egw_json_request.prototype.sendRequest = function(_async, _callback, _sender)
|
||||
{
|
||||
//Store the sender and callback parameter inside this class
|
||||
this.sender = _sender;
|
||||
if (typeof _callback != "undefined")
|
||||
this.callback = _callback;
|
||||
|
||||
//Copy the async parameter which defaults to "true"
|
||||
var is_async = true;
|
||||
if (typeof _async != "undefined")
|
||||
is_async = _async;
|
||||
|
||||
//Assemble the actual request object containing the json data string
|
||||
var request_obj = {
|
||||
"json_data": egw_json_encode(
|
||||
{
|
||||
"request": {
|
||||
"parameters": this.parameters
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
//Send the request via the jquery AJAX interface to the server
|
||||
this.request = $j.ajax({url: this.url,
|
||||
async: is_async,
|
||||
context: this,
|
||||
data: request_obj,
|
||||
dataType: 'json',
|
||||
type: 'POST',
|
||||
success: this.handleResponse,
|
||||
error: function(_xmlhttp,_err) { window.console.error('Ajax request to ' + this.url + ' failed: ' + _err); }
|
||||
});
|
||||
}
|
||||
|
||||
egw_json_request.prototype.abort = function()
|
||||
{
|
||||
this.request.abort();
|
||||
}
|
||||
|
||||
egw_json_request.prototype.alertFunc = function(_message, _details)
|
||||
{
|
||||
alert(_message);
|
||||
if(_details) _egw_json_debug_log(_message, _details);
|
||||
}
|
||||
|
||||
function _egw_json_debug_log(_msg, _e)
|
||||
{
|
||||
if (typeof console != "undefined" && typeof console.log != "undefined")
|
||||
{
|
||||
console.log(_msg, _e);
|
||||
}
|
||||
}
|
||||
|
||||
/* Displays an json error message */
|
||||
egw_json_request.prototype.jsonError = function(_msg, _e)
|
||||
{
|
||||
var msg = 'EGW JSON Error: '._msg;
|
||||
|
||||
//Log and show the error message
|
||||
_egw_json_debug_log(msg, _e);
|
||||
this.alertHandler(msg);
|
||||
}
|
||||
|
||||
/* Internal function which handles the response from the server */
|
||||
egw_json_request.prototype.handleResponse = function(data, textStatus, XMLHttpRequest)
|
||||
{
|
||||
this.handleResponseDone = false;
|
||||
if (data && data.response)
|
||||
{
|
||||
var hasResponse = false;
|
||||
for (var i = 0; i < data.response.length; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
var res = data.response[i];
|
||||
|
||||
switch (data.response[i].type)
|
||||
{
|
||||
case 'alert':
|
||||
//Check whether all needed parameters have been passed and call the alertHandler function
|
||||
if ((typeof res.data.message != 'undefined') &&
|
||||
(typeof res.data.details != 'undefined'))
|
||||
{
|
||||
this.alertHandler(
|
||||
res.data.message,
|
||||
res.data.details)
|
||||
hasResponse = true;
|
||||
} else
|
||||
throw 'Invalid parameters';
|
||||
break;
|
||||
case 'assign':
|
||||
//Check whether all needed parameters have been passed and call the alertHandler function
|
||||
if ((typeof res.data.id != 'undefined') &&
|
||||
(typeof res.data.key != 'undefined') &&
|
||||
(typeof res.data.value != 'undefined'))
|
||||
{
|
||||
var obj = document.getElementById(res.data.id);
|
||||
if (obj)
|
||||
{
|
||||
obj[res.data.key] = res.data.value;
|
||||
|
||||
if (res.data.key == "innerHTML")
|
||||
{
|
||||
egw_insertJS(res.data.value);
|
||||
}
|
||||
|
||||
hasResponse = true;
|
||||
}
|
||||
} else
|
||||
throw 'Invalid parameters';
|
||||
break;
|
||||
case 'data':
|
||||
//Callback the caller in order to allow him to handle the data
|
||||
if (this.callback)
|
||||
{
|
||||
this.callback.call(this.sender, res.data);
|
||||
hasResponse = true;
|
||||
}
|
||||
break;
|
||||
case 'script':
|
||||
if (typeof res.data == 'string')
|
||||
{
|
||||
try
|
||||
{
|
||||
var func = function() {eval(res.data);};
|
||||
func.call(window);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
e.code = res.data;
|
||||
_egw_json_debug_log(e);
|
||||
}
|
||||
hasResponse = true;
|
||||
} else
|
||||
throw 'Invalid parameters';
|
||||
break;
|
||||
case 'jquery':
|
||||
if (typeof res.data.select == 'string' &&
|
||||
typeof res.data.func == 'string')
|
||||
{
|
||||
try
|
||||
{
|
||||
var jQueryObject = $j(res.data.select, this.context);
|
||||
jQueryObject[res.data.func].apply(jQueryObject, res.data.parms);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
_egw_json_debug_log(e, {'Function': res.data.func, 'Parameters': res.data.params});
|
||||
}
|
||||
hasResponse = true;
|
||||
} else
|
||||
throw 'Invalid parameters';
|
||||
break;
|
||||
case 'redirect':
|
||||
//console.log(res.data.url);
|
||||
if (typeof res.data.url == 'string' &&
|
||||
typeof res.data.global == 'boolean')
|
||||
{
|
||||
//Special handling for framework reload
|
||||
res.data.global |= (res.data.url.indexOf("?cd=10") > 0);
|
||||
|
||||
if (res.data.global)
|
||||
{
|
||||
egw_topWindow().location.href = res.data.url;
|
||||
}
|
||||
else
|
||||
{
|
||||
egw_appWindowOpen(this.app, res.data.url);
|
||||
}
|
||||
|
||||
hasResponse = true;
|
||||
} else
|
||||
throw 'Invalid parameters';
|
||||
break;
|
||||
case 'css':
|
||||
if (typeof res.data == 'string')
|
||||
{
|
||||
//Check whether the requested file had already be included
|
||||
if (!egw_json_files[res.data])
|
||||
{
|
||||
egw_json_files[res.data] = true;
|
||||
|
||||
//Get the head node and append a new link node with the stylesheet url to it
|
||||
var headID = document.getElementsByTagName('head')[0];
|
||||
var cssnode = document.createElement('link');
|
||||
cssnode.type = "text/css";
|
||||
cssnode.rel = "stylesheet";
|
||||
cssnode.href = res.data;
|
||||
headID.appendChild(cssnode);
|
||||
}
|
||||
hasResponse = true;
|
||||
} else
|
||||
throw 'Invalid parameters';
|
||||
break;
|
||||
case 'js':
|
||||
if (typeof res.data == 'string')
|
||||
{
|
||||
//Check whether the requested file had already be included
|
||||
if (!egw_json_files[res.data])
|
||||
{
|
||||
egw_json_files[res.data] = true;
|
||||
|
||||
//Get the head node and append a new script node with the js file to it
|
||||
var headID = document.getElementsByTagName('head')[0];
|
||||
var scriptnode = document.createElement('script');
|
||||
scriptnode.type = "text/javascript";
|
||||
scriptnode.src = res.data;
|
||||
scriptnode._originalSrc = res.data;
|
||||
headID.appendChild(scriptnode);
|
||||
|
||||
//Increment the includedJSFiles count
|
||||
this.loadedJSFiles[res.data] = false;
|
||||
|
||||
if (typeof console != 'undefined' && typeof console.log != 'undefined')
|
||||
console.log("Requested JS file '%s' from server", res.data);
|
||||
|
||||
var self = this;
|
||||
|
||||
//FF, Opera, Chrome
|
||||
scriptnode.onload = function(e) {
|
||||
var file = e.target._originalSrc;
|
||||
if (typeof console != 'undefined' && typeof console.log != 'undefined')
|
||||
console.log("Retrieved JS file '%s' from server", file);
|
||||
|
||||
self.loadedJSFiles[file] = true;
|
||||
self.checkLoadFinish();
|
||||
};
|
||||
|
||||
//IE
|
||||
if (typeof scriptnode.readyState != 'undefined')
|
||||
{
|
||||
if (scriptnode.readyState != 'complete' &&
|
||||
scriptnode.readyState != 'loaded')
|
||||
{
|
||||
scriptnode.onreadystatechange = function() {
|
||||
var node = window.event.srcElement;
|
||||
if (node.readyState == 'complete' || node.readyState == 'loaded') {
|
||||
var file = node._originalSrc;
|
||||
if (typeof console != 'undefined' && typeof console.log != 'undefined')
|
||||
console.log("Retrieved JS file '%s' from server", [file]);
|
||||
|
||||
self.loadedJSFiles[file] = true;
|
||||
self.checkLoadFinish();
|
||||
}
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
this.loadedJSFiles[res.data] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
hasResponse = true;
|
||||
} else
|
||||
throw 'Invalid parameters';
|
||||
break;
|
||||
case 'error':
|
||||
if (typeof res.data == 'string')
|
||||
{
|
||||
this.jsonError(res.data);
|
||||
hasResponse = true;
|
||||
} else
|
||||
throw 'Invalid parameters';
|
||||
break;
|
||||
}
|
||||
|
||||
//Try to handle the json response with all registered plugins
|
||||
hasResponse |= _egw_json_plugin_handle(data.response[i].type, res);
|
||||
} catch(e) {
|
||||
this.jsonError('Internal JSON handler error', e);
|
||||
}
|
||||
}
|
||||
|
||||
/* If no explicit response has been specified, call the callback (if one was set) */
|
||||
if (!hasResponse && this.callback && data.response[i])
|
||||
{
|
||||
this.callback.call(this.sender, data.response[i].data);
|
||||
}
|
||||
|
||||
this.handleResponseDone = true;
|
||||
|
||||
this.checkLoadFinish();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The "onLoadFinish" handler gets called after all JS-files have been loaded
|
||||
* successfully
|
||||
*/
|
||||
egw_json_request.prototype.checkLoadFinish = function()
|
||||
{
|
||||
var complete = true;
|
||||
for (var key in this.loadedJSFiles) {
|
||||
complete = complete && this.loadedJSFiles[key];
|
||||
}
|
||||
|
||||
if (complete && this.onLoadFinish && this.handleResponseDone)
|
||||
{
|
||||
this.onLoadFinish.call(this.sender);
|
||||
}
|
||||
}
|
||||
|
||||
function egw_json_getFormValues(_form, _filterClass)
|
||||
{
|
||||
var elem = null;
|
||||
if (typeof _form == 'object')
|
||||
{
|
||||
elem = _form;
|
||||
}
|
||||
else
|
||||
{
|
||||
elem = document.getElementsByName(_form)[0];
|
||||
}
|
||||
|
||||
var serialized = new Object;
|
||||
if (typeof elem != "undefined" && elem && elem.childNodes)
|
||||
{
|
||||
if (typeof _filterClass == 'undefined')
|
||||
_filterClass = null;
|
||||
|
||||
_egw_json_getFormValues(serialized, elem.childNodes, _filterClass)
|
||||
}
|
||||
|
||||
return serialized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated legacy xajax wrapper functions for the new egw_json interface
|
||||
*/
|
||||
/*_xajax_doXMLHTTP = function(_async, _menuaction, _arguments)
|
||||
{
|
||||
// Assemble the parameter array
|
||||
var paramarray = new Array();
|
||||
for (var i = 1; i < _arguments.length; i++)
|
||||
{
|
||||
paramarray[paramarray.length] = _arguments[i];
|
||||
}
|
||||
|
||||
// Create a new request, passing the menuaction and the parameter array
|
||||
var request = new egw_json_request(_menuaction, paramarray);
|
||||
|
||||
// Send the request
|
||||
request.sendRequest(_async);
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
xajax_doXMLHTTP = function(_menuaction)
|
||||
{
|
||||
return _xajax_doXMLHTTP(true, _menuaction, arguments);
|
||||
}
|
||||
|
||||
xajax_doXMLHTTPsync = function(_menuaction)
|
||||
{
|
||||
return _xajax_doXMLHTTP(false, _menuaction, arguments);
|
||||
};
|
||||
|
||||
window.xajax = {
|
||||
"getFormValues": function(_form)
|
||||
{
|
||||
return egw_json_getFormValues(_form);
|
||||
}
|
||||
};
|
||||
*/
|
||||
/*
|
||||
The following code is adapted from the xajax project which is licensed under
|
||||
the following license
|
||||
@copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson
|
||||
@copyright Copyright (c) 2008-2009 by Joseph Woolley, Steffen Konerow, Jared White & J. Max Wilson
|
||||
@license http://www.xajaxproject.org/bsd_license.txt BSD License
|
||||
*/
|
||||
|
||||
/**
|
||||
* used internally by the legacy "egw_json_response.getFormValues" to recursively
|
||||
* run over all form elements
|
||||
* @param serialized is the object which will contain the form data
|
||||
* @param children is the children node of the form we're runing over
|
||||
* @param string _filterClass if given only return
|
||||
*/
|
||||
function _egw_json_getFormValues(serialized, children, _filterClass)
|
||||
{
|
||||
//alert('_egw_json_getFormValues(,,'+_filterClass+')');
|
||||
for (var i = 0; i < children.length; ++i) {
|
||||
var child = children[i];
|
||||
|
||||
if (typeof child.childNodes != "undefined")
|
||||
_egw_json_getFormValues(serialized, child.childNodes, _filterClass);
|
||||
|
||||
if ((!_filterClass || $j(child).hasClass(_filterClass)) && typeof child.name != "undefined")
|
||||
{
|
||||
//alert('_egw_json_getFormValues(,,'+_filterClass+') calling _egw_json_getFormValue for name='+child.name+', class='+child.class+', value='+child.value);
|
||||
_egw_json_getFormValue(serialized, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _egw_json_getObjectLength(_obj)
|
||||
{
|
||||
var res = 0;
|
||||
for (key in _obj)
|
||||
{
|
||||
if (_obj.hasOwnProperty(key))
|
||||
res++;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* used internally to serialize
|
||||
*/
|
||||
function _egw_json_getFormValue(serialized, child)
|
||||
{
|
||||
//Return if the child doesn't have a name, is disabled, or is a radio-/checkbox and not checked
|
||||
if ((typeof child.name == "undefined") || (child.disabled && child.disabled == true) ||
|
||||
(child.type && (child.type == 'radio' || child.type == 'checkbox' || child.type == 'button' || child.type == 'submit') && (!child.checked)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var name = child.name;
|
||||
var values = null;
|
||||
|
||||
if ('select-multiple' == child.type)
|
||||
{
|
||||
values = new Array;
|
||||
for (var j = 0; j < child.length; ++j)
|
||||
{
|
||||
var option = child.options[j];
|
||||
if (option.selected == true)
|
||||
values.push(option.value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
values = child.value;
|
||||
}
|
||||
|
||||
//Special treatment if the name of the child contains a [] - then all theese
|
||||
//values are added to an array.
|
||||
var keyBegin = name.indexOf('[');
|
||||
if (0 <= keyBegin) {
|
||||
var n = name;
|
||||
var k = n.substr(0, n.indexOf('['));
|
||||
var a = n.substr(n.indexOf('['));
|
||||
if (typeof serialized[k] == 'undefined')
|
||||
serialized[k] = new Object;
|
||||
|
||||
var p = serialized; // pointer reset
|
||||
while (a.length != 0) {
|
||||
var sa = a.substr(0, a.indexOf(']')+1);
|
||||
|
||||
var lk = k; //save last key
|
||||
var lp = p; //save last pointer
|
||||
|
||||
a = a.substr(a.indexOf(']')+1);
|
||||
p = p[k];
|
||||
k = sa.substr(1, sa.length-2);
|
||||
if (k == '') {
|
||||
if ('select-multiple' == child.type) {
|
||||
k = lk; //restore last key
|
||||
p = lp;
|
||||
} else {
|
||||
k = _egw_json_getObjectLength(p);
|
||||
}
|
||||
}
|
||||
if (typeof p[k] == 'undefined')
|
||||
{
|
||||
p[k] = new Object;
|
||||
}
|
||||
}
|
||||
p[k] = values;
|
||||
} else {
|
||||
//Add the value to the result object with the given name
|
||||
if (typeof values != "undefined")
|
||||
{
|
||||
serialized[name] = values;
|
||||
}
|
||||
}
|
||||
}
|
16
phpgwapi/js/jquery/jquery.js
vendored
Normal file
16
phpgwapi/js/jquery/jquery.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user