mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-24 17:04:14 +01:00
ability to queue ajax requests on the client and send them as a single ajax request every N ms to the server
a) instead of a single request like: new egw_json_request(menuaction, params).sendRequest(true, callback, context); b) you call: egw.jsonq(menuaction,params,callback,context) The server callback is identical for both kinds of requests. All egw_json_response methods can be used and the callback is optional.
This commit is contained in:
parent
077acb3fb0
commit
516b977472
2
json.php
2
json.php
@ -100,7 +100,7 @@ if (isset($_GET['menuaction']))
|
||||
{
|
||||
throw new egw_exception_assertion_failed("JSON Data contains script tags. Aborting...");
|
||||
}
|
||||
$json->parseRequest($_GET['menuaction'], (array)$_POST['json_data']);
|
||||
$json->parseRequest($_GET['menuaction'], $_POST['json_data']);
|
||||
egw_json_response::get();
|
||||
common::egw_exit();
|
||||
}
|
||||
|
@ -27,6 +27,8 @@ class egw_json_request
|
||||
* Parses the raw input data supplied with the input_data parameter and calls the menuaction
|
||||
* passing all parameters supplied in the request to it.
|
||||
*
|
||||
* Also handle queued requests (menuaction == 'home.queue') containing multiple requests
|
||||
*
|
||||
* @param string menuaction to call
|
||||
* @param string $input_data is the RAW input data as it was received from the client
|
||||
*/
|
||||
@ -35,38 +37,36 @@ class egw_json_request
|
||||
// Remember that we currently are in a JSON request - e.g. used in the redirect code
|
||||
self::$_hadJSONRequest = true;
|
||||
|
||||
if (empty($input_data))
|
||||
if (get_magic_quotes_gpc()) $input_data = stripslashes($input_data);
|
||||
|
||||
$json_data = json_decode($input_data,true);
|
||||
if (is_array($json_data) && isset($json_data['request']) && isset($json_data['request']['parameters']))
|
||||
{
|
||||
$this->handleRequest($menuaction, array());
|
||||
$parameters =& $json_data['request']['parameters'];
|
||||
}
|
||||
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'];
|
||||
}
|
||||
// do we have a single request or an array of queued requests
|
||||
if ($menuaction == 'home.queue')
|
||||
{
|
||||
$responses = array();
|
||||
$response = egw_json_response::get();
|
||||
foreach($parameters as $uid => $data)
|
||||
{
|
||||
//error_log("$uid: menuaction=$data[menuaction], parameters=".array2string($data['parameters']));
|
||||
$this->handleRequest($data['menuaction'], $data['parameters']);
|
||||
$responses[$uid] = $response->initResponseArray();
|
||||
//error_log("responses[$uid]=".array2string($responses[$uid]));
|
||||
}
|
||||
//Call the supplied callback function along with the menuaction and the passed parameters
|
||||
$response->data($responses); // send all responses as data
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->handleRequest($menuaction, $parameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request handler
|
||||
@ -246,6 +246,20 @@ class egw_json_response
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Init responseArray
|
||||
*
|
||||
* @param array $arr
|
||||
* @return array previous content
|
||||
*/
|
||||
public function initResponseArray()
|
||||
{
|
||||
$return = $this->responseArray;
|
||||
$this->responseArray = array();
|
||||
$this->hasData = false;
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a "data" response to the json response.
|
||||
*
|
||||
@ -309,9 +323,56 @@ class egw_json_response
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to add a global javascript function with giben parameters
|
||||
* Allows to call a global javascript function with given parameters: window[$func].apply(window, $parameters)
|
||||
*
|
||||
* @param string $script the script code which should be executed upon receiving
|
||||
* @param string $func name of the global (window) javascript function to call
|
||||
* @param array $parameters=array()
|
||||
*/
|
||||
public function apply($function,array $parameters=array())
|
||||
{
|
||||
if (is_string($function))
|
||||
{
|
||||
$this->addGeneric('apply', array(
|
||||
'func' => $function,
|
||||
'parms' => $parameters,
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Invalid parameters supplied.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to call a global javascript function with given parameters: window[$func].call(window[, $param1[, ...]])
|
||||
*
|
||||
* @param string $func name of the global (window) javascript function to call
|
||||
* @param mixed $parameters variable number of parameters
|
||||
*/
|
||||
public function call($function)
|
||||
{
|
||||
$parameters = func_get_args();
|
||||
array_shift($parameters); // shift off $function
|
||||
|
||||
if (is_string($function))
|
||||
{
|
||||
$this->addGeneric('apply', array(
|
||||
'func' => $function,
|
||||
'parms' => $parameters,
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Invalid parameters supplied.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to call a jquery function on a selector with given parameters: $j($selector).$func($parmeters)
|
||||
*
|
||||
* @param string $selector jquery selector
|
||||
* @param string $method name of the jquery to call
|
||||
* @param array $parameters=array()
|
||||
*/
|
||||
public function jquery($selector,$method,array $parameters=array())
|
||||
{
|
||||
@ -498,7 +559,7 @@ class xajaxResponse extends egw_json_response
|
||||
$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);}");
|
||||
$this->apply($func, $args);
|
||||
}
|
||||
|
||||
public function addIncludeCSS($url)
|
||||
|
@ -223,7 +223,7 @@ function egw_json_request(_menuaction, _parameters, _context)
|
||||
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
|
||||
this.url = _menuaction;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -401,7 +401,7 @@ egw_json_request.prototype.handleResponse = function(data, textStatus, XMLHttpRe
|
||||
{
|
||||
try
|
||||
{
|
||||
var func = function() {eval(res.data);};
|
||||
var func = new Function(res.data);
|
||||
func.call(window);
|
||||
}
|
||||
catch (e)
|
||||
@ -413,6 +413,22 @@ egw_json_request.prototype.handleResponse = function(data, textStatus, XMLHttpRe
|
||||
} else
|
||||
throw 'Invalid parameters';
|
||||
break;
|
||||
case 'apply':
|
||||
if (typeof res.data.func == 'string' && typeof window[res.data.func] == 'function')
|
||||
{
|
||||
try
|
||||
{
|
||||
window[res.data.func].apply(window, res.data.parameters);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
e.code = res.data.func;
|
||||
_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')
|
||||
|
@ -639,6 +639,117 @@ else
|
||||
}
|
||||
}
|
||||
return query.length ? _url+'?'+query.join('&') : _url;
|
||||
},
|
||||
|
||||
/**
|
||||
* Queued json requests (objects with attributes menuaction, parameters, context, callback, sender and callbeforesend)
|
||||
*
|
||||
* @access private, use jsonq method to queue requests
|
||||
*/
|
||||
jsonq_queue: {},
|
||||
|
||||
/**
|
||||
* Next uid (index) in queue
|
||||
*/
|
||||
jsonq_uid: 0,
|
||||
|
||||
/**
|
||||
* Running timer for next send of queued items
|
||||
*/
|
||||
jsonq_timer: null,
|
||||
|
||||
/**
|
||||
* Send a queued JSON call to the server
|
||||
*
|
||||
* @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 _callback callback function which should be called upon a "data" response is received
|
||||
* @param _sender is the reference object the callback function should get
|
||||
* @param _callbeforesend optional callback function which can modify the parameters, eg. to do some own queuing
|
||||
*/
|
||||
jsonq: function(_menuaction, _parameters, _callback, _sender, _callbeforesend)
|
||||
{
|
||||
this.jsonq_queue['u'+(this.jsonq_uid++)] = {
|
||||
menuaction: _menuaction,
|
||||
parameters: _parameters,
|
||||
callback: _callback,
|
||||
sender: _sender,
|
||||
callbeforesend: _callbeforesend
|
||||
};
|
||||
|
||||
if (this.jsonq_time == null)
|
||||
{
|
||||
// check / send queue every N ms
|
||||
var self = this;
|
||||
this.jsonq_timer = window.setInterval(function(){ self.jsonq_send();}, 100);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Send the whole job-queue to the server in a single json request with menuaction=queue
|
||||
*/
|
||||
jsonq_send: function()
|
||||
{
|
||||
if (this.jsonq_uid > 0 && typeof this.jsonq_queue['u'+(this.jsonq_uid-1)] == 'object')
|
||||
{
|
||||
var jobs_to_send = {};
|
||||
var something_to_send = false;
|
||||
for(var uid in this.jsonq_queue)
|
||||
{
|
||||
var job = this.jsonq_queue[uid];
|
||||
|
||||
if (job.menuaction == 'send') continue; // already send to server
|
||||
|
||||
// if job has a callbeforesend callback, call it to allow it to modify pararmeters
|
||||
if (typeof job.callbeforesend == 'function')
|
||||
{
|
||||
job.callbeforesend.apply(job.context, job.parameters);
|
||||
}
|
||||
jobs_to_send[uid] = {
|
||||
menuaction: job.menuaction,
|
||||
parameters: job.parameters
|
||||
};
|
||||
job.menuaction = 'send';
|
||||
job.parameters = null;
|
||||
something_to_send = true;
|
||||
}
|
||||
if (something_to_send)
|
||||
{
|
||||
new egw_json_request('home.queue', jobs_to_send, this).sendRequest(true, this.jsonq_callback, this);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Dispatch responses received
|
||||
*
|
||||
* @param object _data uid => response pairs
|
||||
*/
|
||||
jsonq_callback: function(_data)
|
||||
{
|
||||
if (typeof _data != 'object') throw "jsonq_callback called with NO object as parameter!";
|
||||
|
||||
var json = new egw_json_request('none');
|
||||
for(var uid in _data)
|
||||
{
|
||||
if (typeof this.jsonq_queue[uid] == 'undefined')
|
||||
{
|
||||
console.log("jsonq_callback received response for not existing queue uid="+uid+"!");
|
||||
console.log(_data[uid]);
|
||||
continue;
|
||||
}
|
||||
var job = this.jsonq_queue[uid];
|
||||
var response = _data[uid];
|
||||
|
||||
// fake egw_json_request object, to call it with the current response
|
||||
json.callback = job.callback;
|
||||
json.sender = job.sender;
|
||||
json.handleResponse({response: response});
|
||||
|
||||
delete this.jsonq_queue[uid];
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user