From f21d3433721308f5d0693f44bbfed56f7b2ecc2d Mon Sep 17 00:00:00 2001 From: wei <> Date: Fri, 5 May 2006 00:45:35 +0000 Subject: Adding TActiveLabel --- .gitattributes | 1 + framework/Web/Javascripts/js/ajax.js | 29 +++++--- framework/Web/Javascripts/js/prado.js | 2 +- framework/Web/Javascripts/prado/ajax3.js | 84 +++++++++++++++++++--- framework/Web/Javascripts/prado/element.js | 2 +- framework/Web/UI/ActiveControls/TActiveLabel.php | 70 ++++++++++++++++++ .../Web/UI/ActiveControls/TActivePageAdapter.php | 2 +- framework/Web/UI/ActiveControls/TCallback.php | 19 +---- .../UI/ActiveControls/TCallbackClientScript.php | 14 ++-- .../ActiveControls/TCallbackClientSideOptions.php | 16 +++++ framework/Web/UI/TPage.php | 33 ++++++++- .../pages/ActiveControls/ActiveControl.page | 10 +-- .../pages/ActiveControls/ActiveControl.php | 4 +- 13 files changed, 228 insertions(+), 58 deletions(-) create mode 100644 framework/Web/UI/ActiveControls/TActiveLabel.php diff --git a/.gitattributes b/.gitattributes index 88be958c..1567ada7 100644 --- a/.gitattributes +++ b/.gitattributes @@ -928,6 +928,7 @@ framework/Web/THttpResponse.php -text framework/Web/THttpSession.php -text framework/Web/THttpUtility.php -text framework/Web/UI/ActiveControls/TActiveControlAdapter.php -text +framework/Web/UI/ActiveControls/TActiveLabel.php -text framework/Web/UI/ActiveControls/TActivePageAdapter.php -text framework/Web/UI/ActiveControls/TCallback.php -text framework/Web/UI/ActiveControls/TCallbackClientScript.php -text 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)([\\s\\S\\w\\W]*)()',"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 @@ + + * @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 + * @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); /* @@ -323,6 +330,28 @@ class TPage extends TTemplateControl $this->unloadRecursive(); } + /** + * 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. diff --git a/tests/FunctionalTests/features/protected/pages/ActiveControls/ActiveControl.page b/tests/FunctionalTests/features/protected/pages/ActiveControls/ActiveControl.page index 87522f72..2d43bb82 100644 --- a/tests/FunctionalTests/features/protected/pages/ActiveControls/ActiveControl.page +++ b/tests/FunctionalTests/features/protected/pages/ActiveControls/ActiveControl.page @@ -2,9 +2,9 @@

TCallback Demo

- - + OnCallback="control1onCallback" /> + + @@ -12,10 +12,6 @@ - - asdad - - diff --git a/tests/FunctionalTests/features/protected/pages/ActiveControls/ActiveControl.php b/tests/FunctionalTests/features/protected/pages/ActiveControls/ActiveControl.php index 43d93d30..8323667a 100644 --- a/tests/FunctionalTests/features/protected/pages/ActiveControls/ActiveControl.php +++ b/tests/FunctionalTests/features/protected/pages/ActiveControls/ActiveControl.php @@ -7,9 +7,7 @@ class ActiveControl extends TPage { public function control1onCallback($sender, $param) { - $this->button2->setVisible(true); - $this->button2->setText("Time is ".time()); - $this->control1->render($param->getOutput()); + $this->label1->setText("The time is ".time()); } } ?> -- cgit v1.2.3