summaryrefslogtreecommitdiff
path: root/framework/Web
diff options
context:
space:
mode:
authorwei <>2006-05-14 00:30:53 +0000
committerwei <>2006-05-14 00:30:53 +0000
commitae43fa72cdae13bace16a5b8250170e472bb2b87 (patch)
tree6efea16ae0773f5c739bff2cf643f54ba499e5c0 /framework/Web
parentddc3ea15bbfd0235fe90f3b2211bf4cc605e25d6 (diff)
refactor active controls.
Diffstat (limited to 'framework/Web')
-rw-r--r--framework/Web/Javascripts/js/ajax.js20
-rw-r--r--framework/Web/Javascripts/prado/ajax3.js30
-rw-r--r--framework/Web/UI/ActiveControls/TActiveButton.php106
-rw-r--r--framework/Web/UI/ActiveControls/TActiveControlAdapter.php171
-rw-r--r--framework/Web/UI/ActiveControls/TActiveLabel.php31
-rw-r--r--framework/Web/UI/ActiveControls/TActivePageAdapter.php2
-rw-r--r--framework/Web/UI/ActiveControls/TActivePanel.php5
-rw-r--r--framework/Web/UI/ActiveControls/TActiveTextBox.php111
-rw-r--r--framework/Web/UI/ActiveControls/TAutoComplete.php176
-rw-r--r--framework/Web/UI/ActiveControls/TBaseActiveControl.php205
-rw-r--r--framework/Web/UI/ActiveControls/TCallback.php131
-rw-r--r--framework/Web/UI/ActiveControls/TCallbackClientSideOptions.php24
-rw-r--r--framework/Web/UI/TClientScriptManager.php2
-rw-r--r--framework/Web/UI/TControl.php2
14 files changed, 543 insertions, 473 deletions
diff --git a/framework/Web/Javascripts/js/ajax.js b/framework/Web/Javascripts/js/ajax.js
index ba4bdbaf..6e6d0afb 100644
--- a/framework/Web/Javascripts/js/ajax.js
+++ b/framework/Web/Javascripts/js/ajax.js
@@ -34,13 +34,18 @@ 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',PAGESTATE_HEADER:'X-PRADO-PAGESTATE',requestInProgress:null,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',FIELD_POSTBACK_TARGET:'PRADO_POSTBACK_TARGET',FIELD_POSTBACK_PARAMETER:'PRADO_POSTBACK_PARAMETER',PostDataLoaders:[],DATA_HEADER:'X-PRADO-DATA',ACTION_HEADER:'X-PRADO-ACTIONS',ERROR_HEADER:'X-PRADO-ERROR',PAGESTATE_HEADER:'X-PRADO-PAGESTATE',requestInProgress:null,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")
+{try
+{method.toFunction().apply(this,command[method].concat(transport));}
+catch(e)
+{if(typeof(Logger)!="undefined")
+Prado.CallbackRequest.Exception.onException(null,e);}}
+else if(typeof(Logger)!="undefined")
{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)
@@ -48,10 +53,9 @@ method.toFunction().apply(this,command[method].concat(transport));else if(typeof
{data.each(function(action)
{msg+=inspect(action)+"\n";});}
Logger.warn(msg);}},onException:function(request,e)
-{msg="";for(var v in e)
-{if(typeof(v[e])!="object"&&typeof(v[e])!="function")
-msg+=v+":"+e[v]+"\n";}
-Logger.error('Uncaught Callback Client Exception:',e);},formatException:function(e)
+{msg="";$H(e).each(function(item)
+{msg+=item.key+": "+item.value+"\n";})
+Logger.error('Uncaught Callback Client Exception:',msg);},formatException:function(e)
{var msg=e.type+" with message \""+e.message+"\"";msg+=" in "+e.file+"("+e.line+")\n";msg+="Stack trace:\n";var trace=e.trace;for(var i=0;i<trace.length;i++)
{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)
@@ -91,7 +95,9 @@ Prado.CallbackRequest.dispatchNormalRequest(this);},_getPostData:function()
data[name]=value;})})}
if(typeof(this.options.params)!="undefined")
data[callback.FIELD_CALLBACK_PARAMETER]=callback.encode(this.options.params);var pageState=$F(callback.FIELD_CALLBACK_PAGESTATE);if(typeof(pageState)!="undefined")
-data[callback.FIELD_CALLBACK_PAGESTATE]=pageState;data[callback.FIELD_CALLBACK_TARGET]=this.id;return $H(data).toQueryString();}}
+data[callback.FIELD_CALLBACK_PAGESTATE]=pageState;data[callback.FIELD_CALLBACK_TARGET]=this.id;if(this.options.EventTarget)
+data[callback.FIELD_POSTBACK_TARGET]=this.options.EventTarget;if(this.options.EventParameter)
+data[callback.FIELD_POSTBACK_PARAMETER]=this.options.EventParameter;return $H(data).toQueryString();}}
Prado.Callback=function(UniqueID,parameter,onSuccess,options)
{var callback={'params':parameter||'','onSuccess':onSuccess||Prototype.emptyFunction};Object.extend(callback,options||{});new Prado.CallbackRequest(UniqueID,callback);return false;}
Array.prototype.______array='______array';Prado.JSON={org:'http://www.JSON.org',copyright:'(c)2005 JSON.org',license:'http://www.crockford.com/JSON/license.html',stringify:function(arg){var c,i,l,s='',v;switch(typeof arg){case'object':if(arg){if(arg.______array=='______array'){for(i=0;i<arg.length;++i){v=this.stringify(arg[i]);if(s){s+=',';}
diff --git a/framework/Web/Javascripts/prado/ajax3.js b/framework/Web/Javascripts/prado/ajax3.js
index b21e9429..1e832889 100644
--- a/framework/Web/Javascripts/prado/ajax3.js
+++ b/framework/Web/Javascripts/prado/ajax3.js
@@ -87,6 +87,11 @@ Object.extend(Prado.CallbackRequest,
* Callback request page state field name,
*/
FIELD_CALLBACK_PAGESTATE : 'PRADO_PAGESTATE',
+
+ FIELD_POSTBACK_TARGET : 'PRADO_POSTBACK_TARGET',
+
+ FIELD_POSTBACK_PARAMETER : 'PRADO_POSTBACK_PARAMETER',
+
/**
* List of form fields that will be collected during callback.
*/
@@ -132,7 +137,17 @@ Object.extend(Prado.CallbackRequest,
{
var id = command[method][0];
if($(id) || id.indexOf("[]") > -1)
- method.toFunction().apply(this,command[method].concat(transport));
+ {
+ try
+ {
+ method.toFunction().apply(this,command[method].concat(transport));
+ }
+ catch(e)
+ {
+ if(typeof(Logger) != "undefined")
+ Prado.CallbackRequest.Exception.onException(null,e);
+ }
+ }
else if(typeof(Logger) != "undefined")
{
Logger.error("Error in executing callback response:",
@@ -185,12 +200,11 @@ Object.extend(Prado.CallbackRequest,
onException : function(request,e)
{
msg = "";
- for(var v in e)
+ $H(e).each(function(item)
{
- if(typeof(v[e]) != "object" && typeof(v[e]) != "function")
- msg += v+":"+e[v]+"\n";
- }
- Logger.error('Uncaught Callback Client Exception:', e);
+ msg += item.key+": "+item.value+"\n";
+ })
+ Logger.error('Uncaught Callback Client Exception:', msg);
},
/**
@@ -407,6 +421,10 @@ Prado.CallbackRequest.prototype =
if(typeof(pageState) != "undefined")
data[callback.FIELD_CALLBACK_PAGESTATE] = pageState;
data[callback.FIELD_CALLBACK_TARGET] = this.id;
+ if(this.options.EventTarget)
+ data[callback.FIELD_POSTBACK_TARGET] = this.options.EventTarget;
+ if(this.options.EventParameter)
+ data[callback.FIELD_POSTBACK_PARAMETER] = this.options.EventParameter;
return $H(data).toQueryString();
}
}
diff --git a/framework/Web/UI/ActiveControls/TActiveButton.php b/framework/Web/UI/ActiveControls/TActiveButton.php
index da5ec5ad..3343d7fe 100644
--- a/framework/Web/UI/ActiveControls/TActiveButton.php
+++ b/framework/Web/UI/ActiveControls/TActiveButton.php
@@ -6,11 +6,6 @@
class TActiveButton extends TButton implements ICallbackEventHandler
{
/**
- * @var TCallbackClientSideOptions client-side options.
- */
- private $_clientSide;
-
- /**
* 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, by calling this constructor.
@@ -22,29 +17,13 @@ class TActiveButton extends TButton implements ICallbackEventHandler
}
/**
- * @param boolean true to allow fine grain callback updates.
+ * @return TBaseActiveCallbackControl base callback options.
*/
- public function setAllowCallbackUpdate($value)
+ public function getActiveControl()
{
- $this->setViewState('CallbackUpdate', TPropertyValue::ensureBoolean($value), true);
+ return $this->getAdapter()->getActiveControl();
}
-
- /**
- * @return true to allow fine grain callback updates.
- */
- public function getAllowCallbackUpdate()
- {
- return $this->getViewState('CallbackUpdate', true);
- }
-
- /**
- * @return true if can update changes on the client-side during callback.
- */
- protected function canUpdateClientSide()
- {
- return $this->getIsInitialized() && $this->getAllowCallbackUpdate();
- }
-
+
/**
* Raises the callback event. This method is required by {@link
* ICallbackEventHandler} interface. If {@link getCausesValidation
@@ -78,89 +57,22 @@ class TActiveButton extends TButton implements ICallbackEventHandler
public function setText($value)
{
parent::setText($value);
- if($this->canUpdateClientSide())
+ if($this->getActiveControl()->canUpdateClientSide())
$this->getPage()->getCallbackClient()->setAttribute($this, 'value', $value);
}
-
- /**
- * Callback client-side options can be set by setting the properties of
- * the ClientSide property. E.g. <com:TCallback ClientSide.OnSuccess="..." />
- * See {@link TCallbackClientSideOptions} for details on the properties of
- * ClientSide.
- * @return TCallbackClientSideOptions client-side callback options.
- */
- public function getClientSide()
- {
- if(is_null($this->_clientSide))
- $this->_clientSide = $this->createClientSideOptions();
- return $this->_clientSide;
- }
-
- /**
- * @return TCallbackClientSideOptions callback client-side options.
- */
- protected function createClientSideOptions()
- {
- if(($id=$this->getCallbackOptions())!=='' && ($control=$this->findControl($id))!==null)
- {
- if($control instanceof TCallbackOptions)
- return clone($control->getClientSide());
- }
- return new TCallbackClientSideOptions;
- }
-
- /**
- * Sets the ID of a TCallbackOptions component to duplicate the client-side
- * options for this control. The {@link getClientSide ClientSide}
- * subproperties has precendent over the CallbackOptions property.
- * @param string ID of a TCallbackOptions control from which ClientSide
- * options are cloned.
- */
- public function setCallbackOptions($value)
- {
- $this->setViewState('CallbackOptions', $value,'');
- }
-
- /**
- * @return string ID of a TCallbackOptions control from which ClientSide
- * options are cloned.
- */
- public function getCallbackOptions()
- {
- return $this->getViewState('CallbackOptions','');
- }
/**
* Renders the callback control javascript statement.
*/
protected function renderClientControlScript($writer)
{
- $writer->addAttribute('id',$this->getClientID());
- $cs = $this->getPage()->getClientScript();
- $cs->registerCallbackControl(get_class($this),$this->getCallbackOptions());
}
- /**
- * @return array list of callback options.
- */
- protected function getCallbackClientSideOptions()
- {
- return array_merge($this->getPostBackOptions(),
- $this->getClientSide()->getOptions()->toArray());
- }
-
- /**
- * Returns the javascript statement to invoke a callback request for this
- * control. Additional options for callback can be set via subproperties of
- * {@link getClientSide ClientSide} property. E.g. ClientSide.OnSuccess="..."
- * @param TControl callback handler control, use current object if null.
- * @return string javascript statement to invoke a callback.
- */
- public function getCallbackReference($control=null)
+ protected function addAttributesToRender($writer)
{
- $client = $this->getPage()->getClientScript();
- $object = is_null($control) ? $this : $control;
- return $client->getCallbackReference($object, $this->getCallbackClientSideOptions());
+ parent::addAttributesToRender($writer);
+ $writer->addAttribute('id',$this->getClientID());
+ $this->getActiveControl()->registerCallbackClientScript($this->getPostBackOptions());
}
}
diff --git a/framework/Web/UI/ActiveControls/TActiveControlAdapter.php b/framework/Web/UI/ActiveControls/TActiveControlAdapter.php
index 1cdd5d73..af4131ea 100644
--- a/framework/Web/UI/ActiveControls/TActiveControlAdapter.php
+++ b/framework/Web/UI/ActiveControls/TActiveControlAdapter.php
@@ -2,28 +2,187 @@
/*
* Created on 29/04/2006
*/
+Prado::using('System.Web.UI.ActiveControls.TBaseActiveControl');
class TActiveControlAdapter extends TControlAdapter
{
private static $_renderedPosts = false;
+ private $_activeControlType;
+
+ private $_baseActiveControl;
+
+ private $_stateTracker;
+
+ public function __construct($control, $baseCallbackClass=null)
+ {
+ parent::__construct($control);
+ $this->setBaseControlType($baseCallbackClass);
+ }
+
+ private function setBaseControlType($type)
+ {
+ if(is_null($type))
+ {
+ if($this->getControl() instanceof ICallbackEventHandler)
+ $this->_activeControlType = 'TBaseActiveCallbackControl';
+ else
+ $this->_activeControlType = 'TBaseActiveControl';
+ }
+ else
+ {
+ $this->_activeControlType = $type;
+ }
+ }
+
/**
* Render the callback request post data loaders once only.
*/
public function render($writer)
{
- if(!self::$_renderedPosts)
+ $this->renderCallbackClientScripts();
+ parent::render($writer);
+ if($this->getPage()->getIsCallback())
+ $this->getPage()->getCallbackClient()->replace($this->getControl(), $writer);
+ }
+
+ protected function renderCallbackClientScripts()
+ {
+ $cs = $this->getPage()->getClientScript();
+ $key = get_class($this);
+ if(!$cs->isEndScriptRegistered($key))
{
- $cs = $this->getPage()->getClientScript();
$cs->registerPradoScript('ajax');
$options = TJavascript::encode($this->getPage()->getPostDataLoaders(),false);
$script = "Prado.CallbackRequest.PostDataLoaders = {$options};";
- $cs->registerEndScript(get_class($this), $script);
- self::$_renderedPosts = true;
+ $cs->registerEndScript($key, $script);
}
- parent::render($writer);
+ }
+
+ public function getActiveControl()
+ {
+ if(is_null($this->_baseActiveControl))
+ {
+ $type = $this->_activeControlType;
+ $this->_baseActiveControl = new $type($this->getControl());
+ }
+ return $this->_baseActiveControl;
+ }
+
+ protected function getIsTrackingPageState()
+ {
if($this->getPage()->getIsCallback())
- $this->getPage()->getCallbackClient()->replace($this->getControl(), $writer);
+ {
+ $target = $this->getPage()->getCallbackEventTarget();
+ if($target instanceof ICallbackEventHandler)
+ {
+ $client = $target->getActiveControl()->getClientSide();
+ return $client->getEnablePageStateUpdate();
+ }
+ }
+ return false;
+ }
+
+ public function loadState()
+ {
+ if($this->getIsTrackingPageState())
+ {
+ $this->_stateTracker = new TCallbackPageStateTracker($this->getControl());
+ $this->_stateTracker->trackChanges();
+ }
+ parent::loadState();
+ }
+
+ public function saveState()
+ {
+ if(!is_null($this->_stateTracker)
+ && $this->getControl()->getActiveControl()->canUpdateClientSide())
+ {
+ $this->_stateTracker->respondToChanges();
+ }
+ parent::saveState();
}
}
+
+class TCallbackPageStateTracker
+{
+ private $_states = array('Visible', 'Enabled', 'Attributes', 'Style', 'TabIndex', 'ToolTip', 'AccessKey');
+ private $_existingState;
+ private $_control;
+ private $_nullObject;
+
+ public function __construct($control)
+ {
+ $this->_control = $control;
+ $this->_existingState = new TMap;
+ $this->_nullObject = new stdClass;
+ }
+
+ public function trackChanges()
+ {
+ foreach($this->_states as $name)
+ $this->_existingState[$name] = $this->_control->getViewState($name);
+ }
+
+ protected function getChanges()
+ {
+ $diff = array();
+ foreach($this->_states as $name)
+ {
+ $state = $this->_control->getViewState($name);
+ // echo " $name ";
+ $changes = $this->difference($state, $this->_existingState[$name]);
+ // echo " \n ";
+ if($changes !== $this->_nullObject)
+ $diff[$name] = $changes;
+ }
+ return $diff;
+ }
+
+ protected function difference($value1, $value2)
+ {
+// var_dump($value1, $value2);
+ if(gettype($value1) === gettype($value2)
+ && $value1 === $value2) return $this->_nullObject;
+ return $value1;
+ }
+
+ public function respondToChanges()
+ {
+ foreach($this->getChanges() as $property => $value)
+ {
+ $this->{'update'.$property}($value);
+ }
+ }
+
+ protected function client()
+ {
+ return $this->_control->getPage()->getCallbackClient();
+ }
+
+ protected function updateToolTip($value)
+ {
+ $this->client()->setAttribute($this->_control, 'title', $value);
+ }
+
+ protected function updateVisible($visible)
+ {
+ var_dump($visible);
+ if($visible === false)
+ $this->client()->hide($this->_control);
+ else
+ $this->client()->show($this->_control);
+ }
+
+ protected function updateEnabled($enable)
+ {
+ $this->client()->setAttribute($this->_control, 'disabled', $enable===false);
+ }
+
+ protected function updateStyle($style)
+ {
+ var_dump($style);
+ }
+}
+
?> \ No newline at end of file
diff --git a/framework/Web/UI/ActiveControls/TActiveLabel.php b/framework/Web/UI/ActiveControls/TActiveLabel.php
index 13a88b4f..fd2d49b8 100644
--- a/framework/Web/UI/ActiveControls/TActiveLabel.php
+++ b/framework/Web/UI/ActiveControls/TActiveLabel.php
@@ -37,32 +37,11 @@ class TActiveLabel extends TLabel
$this->setAdapter(new TActiveControlAdapter($this));
}
- /**
- * @param boolean true to allow fine grain callback updates.
- */
- public function setAllowCallbackUpdate($value)
- {
- $this->setViewState('CallbackUpdate', TPropertyValue::ensureBoolean($value), true);
- }
-
- /**
- * @return true to allow fine grain callback updates.
- */
- public function getAllowCallbackUpdate()
+ public function getActiveControl()
{
- return $this->getViewState('CallbackUpdate', true);
+ return $this->getAdapter()->getActiveControl();
}
-
- /**
- * @return true if can update changes on the client-side during callback.
- */
- protected function canUpdateClientSide()
- {
- return $this->getIsInitialized()
- && $this->getPage()->getIsCallback()
- && $this->getAllowCallbackUpdate();
- }
-
+
/**
* On callback response, the inner HTMl of the label is updated.
* @param string the text value of the label
@@ -70,7 +49,7 @@ class TActiveLabel extends TLabel
public function setText($value)
{
parent::setText($value);
- if($this->canUpdateClientSide())
+ if($this->getActiveControl()->canUpdateClientSide())
$this->getPage()->getCallbackClient()->update($this, $value);
}
@@ -83,7 +62,7 @@ class TActiveLabel extends TLabel
public function setForControl($value)
{
parent::setForControl($value);
- if($this->canUpdateClientSide())
+ if($this->getActiveControl()->canUpdateClientSide())
{
$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 e92c9cdc..9148a27f 100644
--- a/framework/Web/UI/ActiveControls/TActivePageAdapter.php
+++ b/framework/Web/UI/ActiveControls/TActivePageAdapter.php
@@ -95,7 +95,7 @@ class TActivePageAdapter extends TControlAdapter
}
if(($handler = $this->getCallbackEventTarget()) !== null)
{
- if($handler->getClientSide()->getEnablePageStateUpdate())
+ if($handler->getActiveControl()->getClientSide()->getEnablePageStateUpdate())
{
$pagestate = $this->getPage()->getClientState();
$response->appendHeader(self::CALLBACK_PAGESTATE_HEADER.': '.$pagestate);
diff --git a/framework/Web/UI/ActiveControls/TActivePanel.php b/framework/Web/UI/ActiveControls/TActivePanel.php
index b3568279..bd7b2200 100644
--- a/framework/Web/UI/ActiveControls/TActivePanel.php
+++ b/framework/Web/UI/ActiveControls/TActivePanel.php
@@ -15,6 +15,11 @@ class TActivePanel extends TPanel
parent::__construct();
$this->setAdapter(new TActiveControlAdapter($this));
}
+
+ public function getActiveControl()
+ {
+ return $this->getAdapter()->getActiveControl();
+ }
}
?> \ No newline at end of file
diff --git a/framework/Web/UI/ActiveControls/TActiveTextBox.php b/framework/Web/UI/ActiveControls/TActiveTextBox.php
index ad28b291..fba36a14 100644
--- a/framework/Web/UI/ActiveControls/TActiveTextBox.php
+++ b/framework/Web/UI/ActiveControls/TActiveTextBox.php
@@ -3,14 +3,9 @@
* Created on 6/05/2006
*/
-class TActiveTextBox extends TTextBox implements ICallbackEventHandler
+class TActiveTextBox extends TTextBox
{
/**
- * @var TCallbackClientSideOptions client-side options.
- */
- private $_clientSide;
-
- /**
* 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, by calling this constructor.
@@ -21,119 +16,21 @@ class TActiveTextBox extends TTextBox implements ICallbackEventHandler
$this->setAdapter(new TActiveControlAdapter($this));
}
- /**
- * @param boolean true to allow fine grain callback updates.
- */
- public function setAllowCallbackUpdate($value)
- {
- $this->setViewState('CallbackUpdate', TPropertyValue::ensureBoolean($value), true);
- }
-
- /**
- * @return true to allow fine grain callback updates.
- */
- public function getAllowCallbackUpdate()
- {
- return $this->getViewState('CallbackUpdate', true);
- }
-
- /**
- * @return true if can update changes on the client-side during callback.
- */
- protected function canUpdateClientSide()
- {
- return $this->getIsInitialized()
- && $this->getPage()->getIsCallback()
- && $this->getAllowCallbackUpdate();
- }
-
- /**
- * Callback client-side options can be set by setting the properties of
- * the ClientSide property. E.g. <com:TCallback ClientSide.OnSuccess="..." />
- * See {@link TCallbackClientSideOptions} for details on the properties of
- * ClientSide.
- * @return TCallbackClientSideOptions client-side callback options.
- */
- public function getClientSide()
+ public function getActiveControl()
{
- if(is_null($this->_clientSide))
- $this->_clientSide = $this->createClientSideOptions();
- return $this->_clientSide;
+ return $this->getAdapter()->getActiveControl();
}
/**
- * @return TCallbackClientSideOptions callback client-side options.
- */
- protected function createClientSideOptions()
- {
- return new TCallbackClientSideOptions;
- }
-
- /**
- * Raises the callback event. This method is required by {@link
- * ICallbackEventHandler} interface. It class raisePostDataChangedEvent
- * first then raises {@link onCallback OnCallback} event. This method is
- * mainly used by framework and control developers.
- * @param TCallbackEventParameter the event parameter
- */
- public function raiseCallbackEvent($param)
- {
- $this->raisePostDataChangedEvent();
- $this->onCallback($param);
- }
-
- /**
- * This method is invoked when a callback is requested. The method raises
- * 'OnCallback' event to fire up the event handlers. If you override this
- * method, be sure to call the parent implementation so that the event
- * handler can be invoked.
- * @param TCallbackEventParameter event parameter to be passed to the event handlers
- */
- public function onCallback($param)
- {
- $this->raiseEvent('OnCallback', $this, $param);
- }
-
- /**
* Client-side Text property can only be updated after the OnLoad stage.
* @param string text content for the textbox
*/
public function setText($value)
{
parent::setText($value);
- if($this->canUpdateClientSide() && $this->getHasLoadedPostData())
+ if($this->getActiveControl()->canUpdateClientSide() && $this->getHasLoadedPostData())
$this->getPage()->getCallbackClient()->setValue($this, $value);
}
-
- protected function renderClientControlScript($writer)
- {
- $writer->addAttribute('id',$this->getClientID());
- $cs = $this->getPage()->getClientScript();
- $cs->registerCallbackControl(get_class($this),$this->getCallbackOptions());
- }
-
- /**
- * @return array list of callback options.
- */
- protected function getCallbackOptions()
- {
- return array_merge($this->getPostBackOptions(),
- $this->getClientSide()->getOptions()->toArray());
- }
-
- /**
- * Returns the javascript statement to invoke a callback request for this
- * control. Additional options for callback can be set via subproperties of
- * {@link getClientSide ClientSide} property. E.g. ClientSide.OnSuccess="..."
- * @param TControl callback handler control, use current object if null.
- * @return string javascript statement to invoke a callback.
- */
- public function getCallbackReference($control=null)
- {
- $client = $this->getPage()->getClientScript();
- $object = is_null($control) ? $this : $control;
- return $client->getCallbackReference($object, $this->getPostBackOptions());
- }
}
?> \ No newline at end of file
diff --git a/framework/Web/UI/ActiveControls/TAutoComplete.php b/framework/Web/UI/ActiveControls/TAutoComplete.php
index 025a7977..5a76847d 100644
--- a/framework/Web/UI/ActiveControls/TAutoComplete.php
+++ b/framework/Web/UI/ActiveControls/TAutoComplete.php
@@ -11,6 +11,62 @@ class TAutoComplete extends TActiveTextBox implements ICallbackEventHandler, INa
private $_repeater=null;
private $_resultPanel=null;
+ public function getSeparator()
+ {
+ return $this->getViewState('tokens', '');
+ }
+
+ public function setSeparator($value)
+ {
+ $this->setViewState('tokens', TPropertyValue::ensureString($value), '');
+ }
+
+ public function getFrequency()
+ {
+ return $this->getViewState('frequency', '');
+ }
+
+ public function setFrequency($value)
+ {
+ $this->setViewState('frequency', TPropertyValue::ensureFloat($value),'');
+ }
+
+ public function getMinChars()
+ {
+ return $this->getViewState('minChars','');
+ }
+
+ public function setMinChars($value)
+ {
+ $this->setViewState('minChars', TPropertyValue::ensureInteger($value), '');
+ }
+
+ /**
+ * Raises the callback event. This method is required by {@link
+ * ICallbackEventHandler} interface. If {@link getCausesValidation
+ * CausesValidation} is true, it will invoke the page's {@link TPage::
+ * validate validate} method first. It will raise {@link onCallback
+ * OnCallback} event and then the {@link onClick OnClick} event. This method
+ * is mainly used by framework and control developers.
+ * @param TCallbackEventParameter the event parameter
+ */
+ public function raiseCallbackEvent($param)
+ {
+ $this->onCallback($param);
+ }
+
+ /**
+ * This method is invoked when a callback is requested. The method raises
+ * 'OnCallback' event to fire up the event handlers. If you override this
+ * method, be sure to call the parent implementation so that the event
+ * handler can be invoked.
+ * @param TCallbackEventParameter event parameter to be passed to the event handlers
+ */
+ public function onCallback($param)
+ {
+ $this->raiseEvent('OnCallback', $this, $param);
+ }
+
public function setDataSource($data)
{
$this->getSuggestions()->setDataSource($data);
@@ -54,47 +110,6 @@ class TAutoComplete extends TActiveTextBox implements ICallbackEventHandler, INa
return $repeater;
}
- /**
- * @return TCallbackClientSideOptions callback client-side options.
- */
- protected function createClientSideOptions()
- {
- if(($id=$this->getCallbackOptions())!=='' && ($control=$this->findControl($id))!==null)
- {
- if($control instanceof TCallbackOptions)
- {
- $options = clone($control->getClientSide());
- $options->setEnablePageStateUpdate(false);
- return $options;
- }
- }
- $options = new TAutoCompleteClientSideOptions;
- $options->setEnablePageStateUpdate(false);
- return $options;
- }
-
- /**
- * Sets the ID of a TCallbackOptions component to duplicate the client-side
- * options for this control. The {@link getClientSide ClientSide}
- * subproperties has precendent over the CallbackOptions property.
- * @param string ID of a TCallbackOptions control from which ClientSide
- * options are cloned.
- */
- public function setCallbackOptions($value)
- {
- $this->setViewState('CallbackOptions', $value,'');
- }
-
- /**
- * @return string ID of a TCallbackOptions control from which ClientSide
- * options are cloned.
- */
- public function getCallbackOptions()
- {
- return $this->getViewState('CallbackOptions','');
- }
-
-
public function renderEndTag($writer)
{
$this->getPage()->getClientScript()->registerPradoScript('effects');
@@ -109,24 +124,36 @@ class TAutoComplete extends TActiveTextBox implements ICallbackEventHandler, INa
public function render($writer)
{
- if($this->canUpdateClientSide())
+ if($this->getPage()->getIsCallback())
{
- $this->getSuggestions()->render($writer);
- $boundary = $writer->getWriter()->getBoundary();
- $writer->getWriter()->getResponse()->setData($boundary);
+ if($this->getActiveControl()->canUpdateClientSide())
+ $this->renderSuggestions($writer);
}
else
parent::render($writer);
}
+
+ protected function renderSuggestions($writer)
+ {
+ if($this->getSuggestions()->getItems()->getCount() > 0)
+ {
+ $this->getSuggestions()->render($writer);
+ $boundary = $writer->getWriter()->getBoundary();
+ $writer->getWriter()->getResponse()->setData($boundary);
+ }
+ }
/**
* @return array list of callback options.
*/
- protected function getCallbackClientSideOptions()
+ protected function getAutoCompleteOptions()
{
- $options = $this->getClientSide()->getOptions()->toArray();
- if(isset($options['tokens']))
- $options['tokens'] = TJavascript::encode($options['tokens'],false);
+ $this->getActiveControl()->getClientSide()->setEnablePageStateUpdate(false);
+ if(strlen($string = $this->getSeparator()))
+ {
+ $token = preg_split('//', $string, -1, PREG_SPLIT_NO_EMPTY);
+ $options['tokens'] = TJavascript::encode($token,false);
+ }
if($this->getAutoPostBack())
$options = array_merge($options,$this->getPostBackOptions());
$options['ResultPanel'] = $this->getResultPanel()->getClientID();
@@ -135,57 +162,16 @@ class TAutoComplete extends TActiveTextBox implements ICallbackEventHandler, INa
return $options;
}
- /**
- * Adds attribute name-value pairs to renderer.
- * This method overrides the parent implementation with additional textbox specific attributes.
- * @param THtmlWriter the writer used for the rendering purpose
- */
- protected function addAttributesToRender($writer)
+ public function addAttributesToRender($writer)
{
parent::addAttributesToRender($writer);
- $this->renderClientControlScript($writer);
+ $writer->addAttribute('id',$this->getClientID());
+ $this->getActiveControl()->registerCallbackClientScript($this->getAutoCompleteOptions());
}
-}
-
-/**
- * Client-side options for TAutoComplete.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @version $Revision: $ $Date: $
- * @package System.Web.UI.ActiveControls
- * @since 3.0
- */
-class TAutoCompleteClientSideOptions extends TCallbackClientSideOptions
-{
- public function getSeparator()
- {
- return $this->getOption('tokens');
- }
-
- public function setSeparator($value)
- {
- $this->setOption('tokens', preg_split('//', $value, -1, PREG_SPLIT_NO_EMPTY));
- }
-
- public function getFrequency()
- {
- return $this->getOption('frequency');
- }
-
- public function setFrequency($value)
- {
- $this->setOption('frequency', TPropertyValue::ensureFloat($value));
- }
-
- public function getMinChars()
- {
- return $this->getOption('minChars');
- }
-
- public function setMinChars($value)
+ protected function renderClientControlScript($writer)
{
- $this->setOption('minChars', TPropertyValue::ensureInteger($value));
+
}
}
diff --git a/framework/Web/UI/ActiveControls/TBaseActiveControl.php b/framework/Web/UI/ActiveControls/TBaseActiveControl.php
new file mode 100644
index 00000000..c5a62ade
--- /dev/null
+++ b/framework/Web/UI/ActiveControls/TBaseActiveControl.php
@@ -0,0 +1,205 @@
+<?php
+/*
+ * Created on 13/05/2006
+ */
+class TBaseActiveControl extends TComponent
+{
+ private $_options;
+ private $_control;
+
+ public function __construct($control)
+ {
+ $this->_control = $control;
+ $this->_options = new TMap;
+ }
+
+ protected function setOption($name,$value,$default=null)
+ {
+ $value = is_null($value) ? $default : $value;
+ if(!is_null($value))
+ $this->_options->add($name,$value);
+ }
+
+ protected function getOption($name,$default=null)
+ {
+ $item = $this->_options->itemAt($name);
+ return is_null($item) ? $default : $item;
+ }
+
+ protected function getPage()
+ {
+ return $this->_control->getPage();
+ }
+
+ protected function getControl()
+ {
+ return $this->_control;
+ }
+
+ /**
+ * @param boolean true to allow fine grain callback updates.
+ */
+ public function setEnableUpdate($value)
+ {
+ $this->setOption('EnableUpdate', TPropertyValue::ensureBoolean($value), true);
+ }
+
+ /**
+ * @return true to allow fine grain callback updates.
+ */
+ public function getEnableUpdate()
+ {
+ return $this->getOption('EnableUpdate', true);
+ }
+
+ public function canUpdateClientSide()
+ {
+ return $this->getControl()->getIsInitialized()
+ && $this->getPage()->getIsCallback()
+ && $this->getEnableUpdate();
+ }
+}
+
+
+class TBaseActiveCallbackControl extends TBaseActiveControl
+{
+ /**
+ * Callback client-side options can be set by setting the properties of
+ * the ClientSide property. E.g. <com:TCallback ClientSide.OnSuccess="..." />
+ * See {@link TCallbackClientSideOptions} for details on the properties of
+ * ClientSide.
+ * @return TCallbackClientSideOptions client-side callback options.
+ */
+ public function getClientSide()
+ {
+ if(is_null($client = $this->getOption('ClientSide')))
+ {
+ $client = $this->createClientSide();
+ $this->setOption('ClientSide', $client);
+ }
+ return $client;
+ }
+
+ /**
+ * @return TCallbackClientSideOptions callback client-side options.
+ */
+ protected function createClientSide()
+ {
+ if(($id=$this->getCallbackOptions())!==''
+ && ($control=$this->getControl()->findControl($id))!==null)
+ {
+ if($control instanceof TCallbackOptions)
+ return $control->getClientSide();
+ }
+ return new TCallbackClientSideOptions;
+ }
+
+ /**
+ * Sets the ID of a TCallbackOptions component to duplicate the client-side
+ * options for this control. The {@link getClientSide ClientSide}
+ * subproperties has precendent over the CallbackOptions property.
+ * @param string ID of a TCallbackOptions control from which ClientSide
+ * options are cloned.
+ */
+ public function setCallbackOptions($value)
+ {
+ $this->setOption('CallbackOptions', $value, '');
+ }
+
+ /**
+ * @return string ID of a TCallbackOptions control from which ClientSide
+ * options are cloned.
+ */
+ public function getCallbackOptions()
+ {
+ return $this->getOption('CallbackOptions', '');
+ }
+
+ /**
+ * @return boolean whether callback event trigger by this button will cause
+ * input validation, default is true
+ */
+ public function getCausesValidation()
+ {
+ return $this->getOption('CausesValidation',true);
+ }
+
+ /**
+ * @param boolean whether callback event trigger by this button will cause
+ * input validation
+ */
+ public function setCausesValidation($value)
+ {
+ $this->setOption('CausesValidation',TPropertyValue::ensureBoolean($value),true);
+ }
+
+ /**
+ * @return string the group of validators which the button causes validation
+ * upon callback
+ */
+ public function getValidationGroup()
+ {
+ return $this->getOption('ValidationGroup','');
+ }
+
+ /**
+ * @param string the group of validators which the button causes validation
+ * upon callback
+ */
+ public function setValidationGroup($value)
+ {
+ $this->getOption('ValidationGroup',$value,'');
+ }
+
+ /**
+ * @return boolean whether to perform validation if the callback is
+ * requested.
+ */
+ public function canCauseValidation()
+ {
+ if($this->getCausesValidation())
+ {
+ $group=$this->getValidationGroup();
+ return $this->getPage()->getValidators($group)->getCount()>0;
+ }
+ else
+ return false;
+ }
+
+ /**
+ * @return array list of callback javascript options.
+ */
+ protected function getClientSideOptions()
+ {
+ $options = $this->getClientSide()->getOptions()->toArray();
+ $validate = $this->getCausesValidation();
+ $options['CausesValidation']= $validate ? '' : false;
+ $options['ValidationGroup']=$this->getValidationGroup();
+ return $options;
+ }
+
+ public function registerCallbackClientScript($options=null)
+ {
+ $cs = $this->getPage()->getClientScript();
+ if(is_array($options))
+ $options = array_merge($this->getClientSideOptions(),$options);
+ else
+ $options = $this->getClientSideOptions();
+ $cs->registerCallbackControl(get_class($this->getControl()), $options);
+ }
+
+ /**
+ * Returns the javascript statement to invoke a callback request for this
+ * control. Additional options for callback can be set via subproperties of
+ * {@link getClientSide ClientSide} property. E.g. ClientSide.
+ * OnSuccess="..."
+ * @return string javascript statement to invoke a callback.
+ */
+ public function getJavascript()
+ {
+ $client = $this->getPage()->getClientScript();
+ return $client->getCallbackReference($this->getControl(),$this->getClientSideOptions());
+ }
+}
+
+?> \ No newline at end of file
diff --git a/framework/Web/UI/ActiveControls/TCallback.php b/framework/Web/UI/ActiveControls/TCallback.php
index 7bb4ee21..681093ee 100644
--- a/framework/Web/UI/ActiveControls/TCallback.php
+++ b/framework/Web/UI/ActiveControls/TCallback.php
@@ -27,11 +27,6 @@
class TCallback extends TControl implements ICallbackEventHandler
{
/**
- * @var TCallbackClientSideOptions client-side options.
- */
- private $_clientSide;
-
- /**
* 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.
@@ -43,105 +38,14 @@ class TCallback extends TControl implements ICallbackEventHandler
}
/**
- * @return boolean whether callback event trigger by this button will cause
- * input validation, default is true
- */
- public function getCausesValidation()
- {
- return $this->getViewState('CausesValidation',true);
- }
-
- /**
- * @param boolean whether callback event trigger by this button will cause
- * input validation
- */
- public function setCausesValidation($value)
- {
- $this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true);
- }
-
- /**
- * @return string the group of validators which the button causes validation
- * upon callback
- */
- public function getValidationGroup()
- {
- return $this->getViewState('ValidationGroup','');
- }
-
- /**
- * @param string the group of validators which the button causes validation
- * upon callback
+ * @return TBaseActiveCallbackControl base callback options.
*/
- public function setValidationGroup($value)
+ public function getActiveControl()
{
- $this->setViewState('ValidationGroup',$value,'');
+ return $this->getAdapter()->getActiveControl();
}
/**
- * Callback client-side options can be set by setting the properties of
- * the ClientSide property. E.g. <com:TCallback ClientSide.OnSuccess="..." />
- * See {@link TCallbackClientSideOptions} for details on the properties of
- * ClientSide.
- * @return TCallbackClientSideOptions client-side callback options.
- */
- public function getClientSide()
- {
- if(is_null($this->_clientSide))
- $this->_clientSide = $this->createClientSideOptions();
- return $this->_clientSide;
- }
-
- /**
- * @return TCallbackClientSideOptions callback client-side options.
- */
- protected function createClientSideOptions()
- {
- if(($id=$this->getCallbackOptions())!=='' && ($control=$this->findControl($id))!==null)
- {
- if($control instanceof TCallbackOptions)
- return clone($control->getClientSide());
- }
- return new TCallbackClientSideOptions;
- }
-
- /**
- * Sets the ID of a TCallbackOptions component to duplicate the client-side
- * options for this control. The {@link getClientSide ClientSide}
- * subproperties has precendent over the CallbackOptions property.
- * @param string ID of a TCallbackOptions control from which ClientSide
- * options are cloned.
- */
- public function setCallbackOptions($value)
- {
- $this->setViewState('CallbackOptions', $value,'');
- }
-
- /**
- * @return string ID of a TCallbackOptions control from which ClientSide
- * options are cloned.
- */
- public function getCallbackOptions()
- {
- return $this->getViewState('CallbackOptions','');
- }
-
- /**
- * @return boolean whether to perform validation if the callback is
- * requested.
- */
- protected function canCauseValidation()
- {
- if($this->getCausesValidation())
- {
- $group=$this->getValidationGroup();
- return $this->getPage()->getValidators($group)->getCount()>0;
- }
- else
- return false;
- }
-
- /**
* Raises the callback event. This method is required by {@link
* ICallbackEventHandler} interface. If {@link getCausesValidation
* CausesValidation} is true, it will invoke the page's {@link TPage::
@@ -152,8 +56,8 @@ class TCallback extends TControl implements ICallbackEventHandler
*/
public function raiseCallbackEvent($param)
{
- if($this->getCausesValidation())
- $this->getPage()->validate($this->getValidationGroup());
+ if($this->getActiveControl()->canCauseValidation())
+ $this->getPage()->validate($this->getActiveControl()->getValidationGroup());
$this->onCallback($param);
}
@@ -168,31 +72,6 @@ class TCallback extends TControl implements ICallbackEventHandler
{
$this->raiseEvent('OnCallback', $this, $param);
}
-
- /**
- * @return array list of callback javascript options.
- */
- protected function getCallbackClientSideOptions()
- {
- $validate = $this->getCausesValidation();
- $options['CausesValidation']= $validate ? '' : false;
- $options['ValidationGroup']=$this->getValidationGroup();
- return $options;
- }
-
- /**
- * Returns the javascript statement to invoke a callback request for this
- * control. Additional options for callback can be set via subproperties of
- * {@link getClientSide ClientSide} property. E.g. ClientSide.OnSuccess="..."
- * @param TControl callback handler control, use current object if null.
- * @return string javascript statement to invoke a callback.
- */
- public function getCallbackReference($control=null)
- {
- $client = $this->getPage()->getClientScript();
- $object = is_null($control) ? $this : $control;
- return $client->getCallbackReference($object, $this->getCallbackClientSideOptions());
- }
}
?> \ No newline at end of file
diff --git a/framework/Web/UI/ActiveControls/TCallbackClientSideOptions.php b/framework/Web/UI/ActiveControls/TCallbackClientSideOptions.php
index 3eadcd29..3f54e013 100644
--- a/framework/Web/UI/ActiveControls/TCallbackClientSideOptions.php
+++ b/framework/Web/UI/ActiveControls/TCallbackClientSideOptions.php
@@ -265,6 +265,30 @@ class TCallbackClientSideOptions extends TClientSideOptions
$option = $this->getOption('EnablePageStateUpdate');
return is_null($option) ? true : $option;
}
+
+ public function getPostBackTarget()
+ {
+ return $this->getOption('EventTarget');
+ }
+
+ public function setPostBackTarget($value)
+ {
+ if($value instanceof TControl)
+ $value = $value->getUniqueID();
+ $this->setOption('EventTarget', $value);
+ }
+
+ public function getPostBackParameter()
+ {
+ return $this->getOption('EventParameter');
+ }
+
+ public function setPostBackParameter($value)
+ {
+ $this->setOption('EventParameter', $value);
+ }
+
+
}
?> \ No newline at end of file
diff --git a/framework/Web/UI/TClientScriptManager.php b/framework/Web/UI/TClientScriptManager.php
index cad317ef..160ed055 100644
--- a/framework/Web/UI/TClientScriptManager.php
+++ b/framework/Web/UI/TClientScriptManager.php
@@ -168,7 +168,7 @@ class TClientScriptManager extends TApplicationComponent
{
$options = !is_array($options) ? array() : $options;
$class = new TReflectionClass($callbackHandler);
- $clientSide = $callbackHandler->getClientSide();
+ $clientSide = $callbackHandler->getActiveControl()->getClientSide();
$options = array_merge($options, $clientSide->getOptions()->toArray());
$optionString = TJavascript::encode($options);
$this->registerPradoScriptInternal('ajax');
diff --git a/framework/Web/UI/TControl.php b/framework/Web/UI/TControl.php
index 7121e5ed..7ca37a00 100644
--- a/framework/Web/UI/TControl.php
+++ b/framework/Web/UI/TControl.php
@@ -1250,7 +1250,7 @@ class TControl extends TApplicationComponent implements IRenderable, IBindable
}
}
- if($this->getEnabled() && $this instanceof IPostBackDataHandler)
+ if($this instanceof IPostBackDataHandler)
$this->getPage()->registerPostDataLoader($this);
}
$this->_stage=self::CS_PRERENDERED;