diff options
Diffstat (limited to 'framework/Web')
| -rw-r--r-- | framework/Web/Javascripts/js/ajax.js | 29 | ||||
| -rw-r--r-- | framework/Web/Javascripts/js/prado.js | 2 | ||||
| -rw-r--r-- | framework/Web/Javascripts/prado/ajax3.js | 84 | ||||
| -rw-r--r-- | framework/Web/Javascripts/prado/element.js | 2 | ||||
| -rw-r--r-- | framework/Web/UI/ActiveControls/TActiveLabel.php | 70 | ||||
| -rw-r--r-- | framework/Web/UI/ActiveControls/TActivePageAdapter.php | 2 | ||||
| -rw-r--r-- | framework/Web/UI/ActiveControls/TCallback.php | 19 | ||||
| -rw-r--r-- | framework/Web/UI/ActiveControls/TCallbackClientScript.php | 14 | ||||
| -rw-r--r-- | framework/Web/UI/ActiveControls/TCallbackClientSideOptions.php | 16 | ||||
| -rw-r--r-- | framework/Web/UI/TPage.php | 33 | 
10 files changed, 223 insertions, 48 deletions
| diff --git a/framework/Web/Javascripts/js/ajax.js b/framework/Web/Javascripts/js/ajax.js index 375d90e9..6ab3d18d 100644 --- a/framework/Web/Javascripts/js/ajax.js +++ b/framework/Web/Javascripts/js/ajax.js @@ -34,14 +34,14 @@ this.transport.onreadystatechange=Prototype.emptyFunction;},getHeaderData:functi  catch(e)  {if(typeof(json)=="string")  {Logger.info("using json") -return Prado.CallbackRequest.decode(json);}}}});Prado.CallbackRequest=Class.create();Object.extend(Prado.CallbackRequest,{FIELD_CALLBACK_TARGET:'PRADO_CALLBACK_TARGET',FIELD_CALLBACK_PARAMETER:'PRADO_CALLBACK_PARAMETER',FIELD_CALLBACK_PAGESTATE:'PRADO_PAGESTATE',PostDataLoaders:[],DATA_HEADER:'X-PRADO-DATA',ACTION_HEADER:'X-PRADO-ACTIONS',ERROR_HEADER:'X-PRADO-ERROR',dispatchActions:function(transport,actions) +return Prado.CallbackRequest.decode(json);}}}});Prado.CallbackRequest=Class.create();Object.extend(Prado.CallbackRequest,{FIELD_CALLBACK_TARGET:'PRADO_CALLBACK_TARGET',FIELD_CALLBACK_PARAMETER:'PRADO_CALLBACK_PARAMETER',FIELD_CALLBACK_PAGESTATE:'PRADO_PAGESTATE',PostDataLoaders:[],DATA_HEADER:'X-PRADO-DATA',ACTION_HEADER:'X-PRADO-ACTIONS',ERROR_HEADER:'X-PRADO-ERROR',Queque:[],InProgress:[],dispatchActions:function(transport,actions)  {if(actions&&actions.length>0)  actions.each(this.__run.bind(this,transport));},__run:function(transport,command)  {for(var method in command)  {if(command[method][0])  {var id=command[method][0];if($(id)||id.indexOf("[]")>-1)  method.toFunction().apply(this,command[method].concat(transport));else if(typeof(Logger)!="undefined") -{Logger.error("Error in executing callback response:","Unable to find HTML element with ID '"+id+"' before executing "+method+"().");}}}},Exception:{"on505":function(request,transport,data) +{Logger.error("Error in executing callback response:","Unable to find HTML element with ID '"+id+"' before executing "+method+"().");}}}},Exception:{"on500":function(request,transport,data)  {var e=request.getHeaderData(Prado.CallbackRequest.ERROR_HEADER);Logger.error("Callback Server Error "+e.code,this.formatException(e));},'on200':function(request,transport,data)  {if(transport.status<500)  {var msg='HTTP '+transport.status+" with response : \n";msg+=transport.responseText+"\n";msg+="Data : \n"+inspect(data)+"\n";msg+="Actions : \n";request.getHeaderData(Prado.CallbackRequest.ACTION_HEADER).each(function(action) @@ -52,15 +52,28 @@ Logger.warn(msg);}},onException:function(e)  {msg+="  #"+i+" "+trace[i].file;msg+="("+trace[i].line+"): ";msg+=trace[i]["class"]+"->"+trace[i]["function"]+"()"+"\n";}  msg+=e.version+" "+e.time+"\n";return msg;}},encode:function(data)  {return Prado.JSON.stringify(data);},decode:function(data) -{return Prado.JSON.parse(data);}}) -Event.OnLoad(function() +{if(typeof(data)=="string"&&data.trim().length>0) +return Prado.JSON.parse(data);else +return null;},dispatchQuequedRequest:function() +{requests=Prado.CallbackRequest;if(requests.InProgress.length==0&&requests.Queque.length>0) +{var item=requests.Queque.pop();item.callback=new Ajax.Request(item.url,item.options);item.callback.callbackID=item.id;item.timeout=setTimeout(function() +{requests.removeInProgress(item.callback);},item.options.TimeOut);requests.InProgress.push(item);}},removeInProgress:function(request) +{if(request&&request.callbackID) +{var stillInProgress=[];requests=Prado.CallbackRequest;requests.InProgress.each(function(item) +{if(item.callback.callbackID==request.callbackID) +{item.callback.transport.abort();request.transport.abort();clearTimeout(item.timeout);} +else +{stillInProgress.push(item);}}) +requests.InProgress=stillInProgress;} +requests.dispatchQuequedRequest();}}) +Ajax.Responders.register({onComplete:Prado.CallbackRequest.removeInProgress});Event.OnLoad(function()  {if(typeof Logger!="undefined") -Ajax.Responders.register(Prado.CallbackRequest.Exception);});Prado.CallbackRequest.prototype={url:window.location.href,options:{},id:null,request:null,initialize:function(id,options) -{this.options=options||{};this.id=id;var request={postBody:this._getPostData(),parameters:''} -Object.extend(this.options||{},request);if(this.options.CausesValidation!=false&&typeof(Prado.Validation)!="undefined") +Ajax.Responders.register(Prado.CallbackRequest.Exception);});Prado.CallbackRequest.prototype={url:window.location.href,options:{TimeOut:30000},id:null,callback:null,initialize:function(id,options) +{Object.extend(this.options,options||{});this.id=id;var request={postBody:this._getPostData(),parameters:''} +Object.extend(this.options,request);if(this.options.CausesValidation!=false&&typeof(Prado.Validation)!="undefined")  {var form=this.options.Form||Prado.Validation.getForm();if(Prado.Validation.validate(form,this.options.ValidationGroup,this)==false)  return;} -this.request=new Ajax.Request(this.url,this.options);},_getPostData:function() +Prado.CallbackRequest.Queque.push(this);Prado.CallbackRequest.dispatchQuequedRequest();},_getPostData:function()  {var data={};var callback=Prado.CallbackRequest;if(this.options.PostState!=false)  {callback.PostDataLoaders.each(function(name)  {$A(document.getElementsByName(name)).each(function(element) diff --git a/framework/Web/Javascripts/js/prado.js b/framework/Web/Javascripts/js/prado.js index f6c52983..f545ee74 100644 --- a/framework/Web/Javascripts/js/prado.js +++ b/framework/Web/Javascripts/js/prado.js @@ -266,7 +266,7 @@ el.setAttribute(attribute,value);},setOptions:function(element,options)  el.remove(0);for(var i=0;i<options.length;i++)  el.options[el.options.length]=new Option(options[i][0],options[i][1]);}},focus:function(element)  {var obj=$(element);if(typeof(obj)!="undefined"&&typeof(obj.focus)!="undefined") -setTimeout(function(){obj.focus();},100);return false;},replaceContent:function(element,method,content,boundary,transport) +setTimeout(function(){obj.focus();},100);return false;},replace:function(element,method,content,boundary,transport)  {if(boundary)  {var f=RegExp('(<!--'+boundary+'-->)([\\s\\S\\w\\W]*)(<!--//'+boundary+'-->)',"m");var result=transport.responseText.match(f);if(result&&result.length>=2)  content=result[2];} diff --git a/framework/Web/Javascripts/prado/ajax3.js b/framework/Web/Javascripts/prado/ajax3.js index 63add490..8ea76e10 100644 --- a/framework/Web/Javascripts/prado/ajax3.js +++ b/framework/Web/Javascripts/prado/ajax3.js @@ -103,6 +103,14 @@ Object.extend(Prado.CallbackRequest,  	 * Response errors/exceptions header name.
  	 */
  	ERROR_HEADER : 'X-PRADO-ERROR',
 +	/**
 +	 * Callback request queque.
 +	 */
 +	Queque : [],
 +	/**
 +	 * Requests In progress.
 +	 */
 +	InProgress : [],
  	/**
  	 * Dispatch callback response actions.
 @@ -140,9 +148,9 @@ Object.extend(Prado.CallbackRequest,  	Exception :
  	{
  		/**
 -		 * Server returns 505 exception. Just log it.
 +		 * Server returns 500 exception. Just log it.
  		 */
 -		"on505" : function(request, transport, data)
 +		"on500" : function(request, transport, data)
  		{	
  			var e = request.getHeaderData(Prado.CallbackRequest.ERROR_HEADER);
  			Logger.error("Callback Server Error "+e.code, this.formatException(e));
 @@ -163,7 +171,6 @@ Object.extend(Prado.CallbackRequest,  				{
  					msg += inspect(action)+"\n";
  				})
 -				
  				Logger.warn(msg);
  			}
  		},
 @@ -209,10 +216,61 @@ Object.extend(Prado.CallbackRequest,  	 */
  	decode : function(data)
  	{
 -		return Prado.JSON.parse(data);
 +		if(typeof(data) == "string" && data.trim().length > 0)
 +			return Prado.JSON.parse(data);
 +		else
 +			return null;
 +	},
 +	
 +	/**
 +	 * Dispatch quequed requests, and set a timeout.
 +	 */
 +	dispatchQuequedRequest : function()
 +	{
 +		requests = Prado.CallbackRequest;
 +		if(requests.InProgress.length == 0 && requests.Queque.length > 0)
 +		{
 +			var item = requests.Queque.pop();
 +			item.callback = new Ajax.Request(item.url, item.options);
 +			item.callback.callbackID = item.id;
 +			item.timeout = setTimeout(function()
 +			{
 +				requests.removeInProgress(item.callback);
 +			}, item.options.TimeOut);
 +			requests.InProgress.push(item);
 +		}
 +	},
 +	
 +	/**
 +	 * Remove a request currently in progress and call dispatchQuequedRequest.
 +	 */
 +	removeInProgress : function(request)
 +	{
 +		if(request && request.callbackID)
 +		{
 +			var stillInProgress = [];
 +			requests = Prado.CallbackRequest;
 +			requests.InProgress.each(function(item)
 +			{
 +				if(item.callback.callbackID == request.callbackID)
 +				{
 +					item.callback.transport.abort();
 +					request.transport.abort();
 +					clearTimeout(item.timeout);	
 +				}
 +				else
 +				{
 +					stillInProgress.push(item);
 +				}
 +			})
 +			requests.InProgress = stillInProgress;
 +		}
 +		requests.dispatchQuequedRequest();
  	}
  })
 +Ajax.Responders.register({onComplete : Prado.CallbackRequest.removeInProgress});
 +
  //Add HTTP exception respones when logger is enabled.
  Event.OnLoad(function()
  { 
 @@ -233,7 +291,10 @@ Prado.CallbackRequest.prototype =  	/**
  	 * Callback options, including onXXX events.
  	 */
 -	options : {},
 +	options : 
 +	{
 +		TimeOut : 30000 // 30 second timeout.
 +	},
  	/**
  	 * Callback target ID. E.g. $control->getUniqueID();
 @@ -243,14 +304,15 @@ Prado.CallbackRequest.prototype =  	/**
  	 * Current callback request.
  	 */
 -	request : null,
 +	callback : null,
  	/**
  	 * Prepare and inititate a callback request.
  	 */
  	initialize : function(id, options)
  	{
 -		this.options = options || {};	
 +		Object.extend(this.options, options || {});
 +		
  		this.id = id;
  		var request = 
 @@ -258,14 +320,18 @@ Prado.CallbackRequest.prototype =  			postBody : this._getPostData(),
  			parameters : ''
  		}
 -		Object.extend(this.options || {},request);
 +		
 +		Object.extend(this.options, request);		
 +		
  		if(this.options.CausesValidation != false && typeof(Prado.Validation) != "undefined")
  		{
  			var form =  this.options.Form || Prado.Validation.getForm();
  			if(Prado.Validation.validate(form,this.options.ValidationGroup,this) == false)
  				return;
  		}
 -		this.request = new Ajax.Request(this.url, this.options);
 +		
 +		Prado.CallbackRequest.Queque.push(this);
 +		Prado.CallbackRequest.dispatchQuequedRequest();
  	},
  	/**
 diff --git a/framework/Web/Javascripts/prado/element.js b/framework/Web/Javascripts/prado/element.js index 88fb9ec5..cf02095b 100644 --- a/framework/Web/Javascripts/prado/element.js +++ b/framework/Web/Javascripts/prado/element.js @@ -76,7 +76,7 @@ Prado.Element =  		return false;
  	},
 -	replaceContent : function(element, method, content, boundary, transport)
 +	replace : function(element, method, content, boundary, transport)
  	{
  		if(boundary)
  		{
 diff --git a/framework/Web/UI/ActiveControls/TActiveLabel.php b/framework/Web/UI/ActiveControls/TActiveLabel.php new file mode 100644 index 00000000..d71d8b7a --- /dev/null +++ b/framework/Web/UI/ActiveControls/TActiveLabel.php @@ -0,0 +1,70 @@ +<?php
 +/**
 + * TActiveLabel class file.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @link http://www.pradosoft.com/
 + * @copyright Copyright © 2005 PradoSoft
 + * @license http://www.pradosoft.com/license/
 + * @version $Revision: $  $Date: $
 + * @package System.Web.UI.ActiveControls
 + */
 +
 +/**
 + * TActiveLabel class
 + *
 + * The active control counterpart of TLabel component. During a callback
 + * request, setting {@link setText Text} property will also set the text of the
 + * label on the client upon callback completion. Similarly, setting {@link
 + * setForControl ForControl} will set the client-side for attribute on the
 + * label.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @version $Revision: $  $Date: $
 + * @package System.Web.UI.ActiveControls
 + * @since 3.0
 + */
 +class TActiveLabel extends TLabel
 +{
 +	/**
 +	 * Creates a new callback control, sets the adapter to
 +	 * TActiveControlAdapter. If you override this class, be sure to set the
 +	 * adapter appropriately by, for example, call this constructor.
 +	 */
 +	public function __construct()
 +	{
 +		parent::__construct();
 +		$this->setAdapter(new TActiveControlAdapter($this));
 +	}
 +
 +	/**
 +	 * On callback response, the inner HTMl of the label is updated.
 +	 * @param string the text value of the label
 +	 */
 +	public function setText($value)
 +	{
 +		parent::setText($value);
 +		if($this->getPage()->getAllowCallbackUpdate())
 +		{
 +			$this->getPage()->getCallbackClient()->update($this, $value);
 +		}
 +	}
 +	
 +	/**
 +	 * Sets the ID of the control that the label is associated with.
 +	 * The control must be locatable via {@link TControl::findControl} using the ID.
 +	 * On callback response, the For attribute of the label is updated.
 +	 * @param string the associated control ID
 +	 */
 +	public function setForControl($value)
 +	{
 +		parent::setForControl($value);
 +		if($this->getPage()->getAllowCallbackUpdate())
 +		{
 +			$id=$this->findControl($value)->getClientID();
 +			$this->getPage()->getCallbackClient()->setAttribute($this, 'for', $id);
 +		}
 +	}
 +} 
 +
 +?>
 diff --git a/framework/Web/UI/ActiveControls/TActivePageAdapter.php b/framework/Web/UI/ActiveControls/TActivePageAdapter.php index 4cb785dd..db783a12 100644 --- a/framework/Web/UI/ActiveControls/TActivePageAdapter.php +++ b/framework/Web/UI/ActiveControls/TActivePageAdapter.php @@ -285,7 +285,7 @@ class TCallbackErrorHandler extends TErrorHandler  		{
  			$response = $this->getApplication()->getResponse();
  			$data = TJavascript::jsonEncode($this->getExceptionData($exception));			
 -			$response->appendHeader('HTTP/1.0 505 Internal Error');
 +			$response->appendHeader('HTTP/1.0 500 Internal Error');
  			$response->appendHeader(TActivePageAdapter::CALLBACK_ERROR_HEADER.': '.$data);
  		}
  		else
 diff --git a/framework/Web/UI/ActiveControls/TCallback.php b/framework/Web/UI/ActiveControls/TCallback.php index d3b1f54d..9c3234fd 100644 --- a/framework/Web/UI/ActiveControls/TCallback.php +++ b/framework/Web/UI/ActiveControls/TCallback.php @@ -4,7 +4,7 @@   * Created on 25/04/2006
   */
 -class TCallback extends TWebControl implements ICallbackEventHandler
 +class TCallback extends TControl implements ICallbackEventHandler
  {	
  	/**
  	 * @var TCallbackClientSideOptions client-side options.
 @@ -21,15 +21,7 @@ class TCallback extends TWebControl implements ICallbackEventHandler  		parent::__construct();
  		$this->setAdapter(new TActiveControlAdapter($this));
  	}
 -	
 -	/**
 -	 * @return string tag name of the panel
 -	 */
 -	protected function getTagName()
 -	{
 -		return 'div';
 -	}	
 -	
 +
  	/**
  	 * @return boolean whether callback event trigger by this button will cause
  	 * input validation, default is true
 @@ -153,13 +145,6 @@ class TCallback extends TWebControl implements ICallbackEventHandler  		$client = $this->getPage()->getClientScript(); 
  		return $client->getCallbackReference($this, $this->getCallbackOptions());
  	}
 -	
 -	public function render($writer)
 -	{
 -		parent::render($writer);
 -		if($this->getPage()->getIsCallback())
 -			$this->getPage()->getCallbackClient()->replace($this, $writer);
 -	}	
  } 
  ?>
 diff --git a/framework/Web/UI/ActiveControls/TCallbackClientScript.php b/framework/Web/UI/ActiveControls/TCallbackClientScript.php index aaf81380..5f8851db 100644 --- a/framework/Web/UI/ActiveControls/TCallbackClientScript.php +++ b/framework/Web/UI/ActiveControls/TCallbackClientScript.php @@ -318,20 +318,16 @@ class TCallbackClientScript extends TApplicationComponent  		if($content instanceof TControl)
  		{
  			$boundary = $this->getRenderedContentBoundary($content);
 -			$this->callClientFunction('Prado.Element.replaceContent', 
 -					array($element, $method, null, $boundary));		
 +			$content = null;
  		}
  		else if($content instanceof THtmlWriter)
  		{
  			$boundary = $this->getResponseContentBoundary($content);
 -			$this->callClientFunction('Prado.Element.replaceContent', 
 -					array($element, $method, null, $boundary));		
 -		}
 -		else
 -		{
 -			$this->callClientFunction('Prado.Element.replaceContent', 
 -				array($element, $method, $content, $boundary));		
 +			$content = null;
  		}
 +
 +		$this->callClientFunction('Prado.Element.replace', 
 +					array($element, $method, $content, $boundary));		
  	}
  	/**
 diff --git a/framework/Web/UI/ActiveControls/TCallbackClientSideOptions.php b/framework/Web/UI/ActiveControls/TCallbackClientSideOptions.php index 1e1bd52f..6a4731f7 100644 --- a/framework/Web/UI/ActiveControls/TCallbackClientSideOptions.php +++ b/framework/Web/UI/ActiveControls/TCallbackClientSideOptions.php @@ -216,6 +216,22 @@ class TCallbackClientSideOptions extends TClientSideOptions  	{
  		$this->getOptions()->add('PostState', TPropertyValue::ensureBoolean($value));
  	}
 +	
 +	/**
 +	 * @return integer callback request timeout.
 +	 */
 +	public function getRequestTimeOut()
 +	{
 +		return $this->getOption('TimeOut');
 +	}
 +	
 +	/**
 +	 * @param integer callback request timeout 
 +	 */
 +	public function setRequestTimeOut($value)
 +	{
 +		$this->getOptions()->add('TimeOut', TPropertyValue::ensureInteger($value));
 +	}
  } 
  ?>
 diff --git a/framework/Web/UI/TPage.php b/framework/Web/UI/TPage.php index 94f1f475..11ebc1dd 100644 --- a/framework/Web/UI/TPage.php +++ b/framework/Web/UI/TPage.php @@ -37,7 +37,7 @@ class TPage extends TTemplateControl  	const FIELD_PAGESTATE='PRADO_PAGESTATE';
  	const FIELD_CALLBACK_TARGET='PRADO_CALLBACK_TARGET';
  	const FIELD_CALLBACK_PARAMETER='PRADO_CALLBACK_PARAMETER';
 -//	const FIELD_CALLBACK_ID='PRADO_CALLBACK_ID';
 +
  	/**
  	 * @var array system post fields
  	 */
 @@ -48,7 +48,6 @@ class TPage extends TTemplateControl  		'PRADO_PAGESTATE'=>true,
  		'PRADO_CALLBACK_TARGET'=>true,
  		'PRADO_CALLBACK_PARAMETER'=>true
 -		//'PRADO_CALLBACK_ID'=>true
  	);
  	/**
  	 * @var TForm form instance
 @@ -154,6 +153,11 @@ class TPage extends TTemplateControl  	 * @var array post data loader IDs.
  	 */
  	private $_postDataLoaders=array();
 +	/**
 +	 * @var boolean true if callback request is allowed to update the client-
 +	 * side contents during callback response.
 +	 */
 +	private $_allowCallbackUpdate=false;
  	/**
  	 * Constructor.
 @@ -278,6 +282,8 @@ class TPage extends TTemplateControl  		Prado::trace("Page initRecursive()",'System.Web.UI.TPage');
  		$this->initRecursive();
 +		$this->setAllowCallbackUpdate(true);
 +
  		Prado::trace("Page onInitComplete()",'System.Web.UI.TPage');
  		$this->onInitComplete(null);
 @@ -295,6 +301,7 @@ class TPage extends TTemplateControl  		Prado::trace("Page raiseChangedEvents()",'System.Web.UI.TPage');
  		$this->raiseChangedEvents();
 +
  		$this->getAdapter()->processCallbackEvent($writer); 
  /*		
 @@ -324,6 +331,28 @@ class TPage extends TTemplateControl  	}
  	/**
 +	 * Returns true if callback request is allowed to update the client- side
 +	 * contents during callback response. Default is true if {@link
 +	 * getIsCallback IsCallback} is true and onInit stage has been completed.
 +	 * @return boolean true to allow client-side update.
 +	 */
 +	public function getAllowCallbackUpdate()
 +	{
 +		return $this->_allowCallbackUpdate;
 +	}
 +	
 +	/**
 +	 * Set to true to allow callback request to update client-side content
 +	 * during callback response. Default is true if {@link getIsCallback
 +	 * IsCallback} is true and onInit stage has been completed.
 +	 * @param boolean true to allow callback to update client-side content.
 +	 */
 +	public function setAllowCallbackUpdate($value)
 +	{
 +		$this->_allowCallbackUpdate = TPropertyValue::ensureBoolean($value);
 +	}
 +	
 +	/**
  	 * Gets the callback client script handler that allows javascript functions
  	 * to be executed during the callback response. 
  	 * @return TCallbackClientScript interface to client-side javascript code.
 | 
