diff options
Diffstat (limited to 'framework/Web/UI')
29 files changed, 1393 insertions, 1315 deletions
diff --git a/framework/Web/UI/ActiveControls/TActiveCheckBox.php b/framework/Web/UI/ActiveControls/TActiveCheckBox.php index 55244372..3e078876 100644 --- a/framework/Web/UI/ActiveControls/TActiveCheckBox.php +++ b/framework/Web/UI/ActiveControls/TActiveCheckBox.php @@ -121,6 +121,9 @@ class TActiveCheckBox extends TCheckBox implements ICallbackEventHandler, IActiv /** * Ensure that the ID attribute is rendered and registers the javascript code * for initializing the active control. + * + * Since 3.1.4, the javascript code is not rendered if {@link setAutoPostBack AutoPostBack} is false + * * @param THtmlWriter the writer for the rendering purpose * @param string checkbox id * @param string onclick js @@ -128,8 +131,9 @@ class TActiveCheckBox extends TCheckBox implements ICallbackEventHandler, IActiv protected function renderInputTag($writer,$clientID,$onclick) { parent::renderInputTag($writer,$clientID,$onclick); - $this->getActiveControl()->registerCallbackClientScript( - $this->getClientClassName(), $this->getPostBackOptions()); + if ($this->getAutoPostBack()) + $this->getActiveControl()->registerCallbackClientScript( + $this->getClientClassName(), $this->getPostBackOptions()); } /** diff --git a/framework/Web/UI/ActiveControls/TActiveControlAdapter.php b/framework/Web/UI/ActiveControls/TActiveControlAdapter.php index 34872f98..8c6ba430 100644 --- a/framework/Web/UI/ActiveControls/TActiveControlAdapter.php +++ b/framework/Web/UI/ActiveControls/TActiveControlAdapter.php @@ -64,7 +64,7 @@ class TActiveControlAdapter extends TControlAdapter */
protected function setBaseControlClass($type)
{
- if(is_null($type))
+ if($type===null)
{
if($this->getControl() instanceof ICallbackEventHandler)
$this->_activeControlType = 'TBaseActiveCallbackControl';
@@ -117,7 +117,7 @@ class TActiveControlAdapter extends TControlAdapter */
public function getBaseActiveControl()
{
- if(is_null($this->_baseActiveControl))
+ if($this->_baseActiveControl===null)
{
$type = $this->_activeControlType;
$this->_baseActiveControl = new $type($this->getControl());
@@ -161,7 +161,7 @@ class TActiveControlAdapter extends TControlAdapter */
public function saveState()
{
- if(!is_null($this->_stateTracker)
+ if(($this->_stateTracker!==null)
&& $this->getControl()->getActiveControl()->canUpdateClientSide())
{
$this->_stateTracker->respondToChanges();
@@ -353,7 +353,7 @@ class TCallbackPageStateTracker */
protected function updateStyle($style)
{
- if(!is_null($style['CssClass']))
+ if($style['CssClass']!==null)
$this->client()->setAttribute($this->_control, 'class', $style['CssClass']);
if(count($style['Style']) > 0)
$this->client()->setStyle($this->_control, $style['Style']);
@@ -487,9 +487,9 @@ class TStyleDiff extends TViewStateDiff */
protected function getCssClassDiff()
{
- if(is_null($this->_old))
+ if($this->_old===null)
{
- return !is_null($this->_new) && $this->_new->hasCssClass()
+ return ($this->_new!==null) && $this->_new->hasCssClass()
? $this->_new->getCssClass() : null;
}
else
@@ -515,13 +515,13 @@ class TStyleDiff extends TViewStateDiff */
public function getDifference()
{
- if(is_null($this->_new))
+ if($this->_new===null)
return $this->_null;
else
{
$css = $this->getCssClassDiff();
$style = $this->getStyleDiff();
- if(!is_null($css) || !is_null($style))
+ if(($css!==null) || ($style!==null))
return array('CssClass' => $css, 'Style' => $style);
else
$this->_null;
@@ -546,9 +546,9 @@ class TMapCollectionDiff extends TViewStateDiff */
public function getDifference()
{
- if(is_null($this->_old))
+ if($this->_old===null)
{
- return !is_null($this->_new) ? $this->_new->toArray() : $this->_null;
+ return ($this->_new!==null) ? $this->_new->toArray() : $this->_null;
}
else
{
diff --git a/framework/Web/UI/ActiveControls/TActiveCustomValidator.php b/framework/Web/UI/ActiveControls/TActiveCustomValidator.php index 6c74aa7d..1f719bf6 100644 --- a/framework/Web/UI/ActiveControls/TActiveCustomValidator.php +++ b/framework/Web/UI/ActiveControls/TActiveCustomValidator.php @@ -4,7 +4,7 @@ *
* @author Wei Zhuo <weizhuo[at]gamil[dot]com>
* @link http://www.pradosoft.com/
- * @copyright Copyright © 2005-2008 PradoSoft + * @copyright Copyright © 2005-2008 PradoSoft
* @license http://www.pradosoft.com/license/
* @version $Id$
* @package System.Web.UI.ActiveControls
@@ -236,6 +236,6 @@ class TActiveCustomValidatorClientSide extends TCallbackClientSide public function getObserveChanges()
{
$changes = $this->getOption('ObserveChanges');
- return is_null($changes) ? true : $changes;
+ return ($changes===null) ? true : $changes;
}
}
diff --git a/framework/Web/UI/ActiveControls/TActiveDatePicker.php b/framework/Web/UI/ActiveControls/TActiveDatePicker.php index 052ed199..fafd21e5 100755 --- a/framework/Web/UI/ActiveControls/TActiveDatePicker.php +++ b/framework/Web/UI/ActiveControls/TActiveDatePicker.php @@ -39,6 +39,7 @@ class TActiveDatePicker extends TDatePicker implements ICallbackEventHandler, I protected function getDatePickerOptions(){ $options = parent::getDatePickerOptions(); $options['EventTarget'] = $this->getUniqueID(); + $options['ShowCalendar'] = $this->getShowCalendar(); return $options; } @@ -108,22 +109,20 @@ class TActiveDatePicker extends TDatePicker implements ICallbackEventHandler, I */ protected function registerCalendarClientScript() { - if($this->getShowCalendar()) - { - $cs = $this->getPage()->getClientScript(); - $cs->registerPradoScript("activedatepicker"); - - if(!$cs->isEndScriptRegistered('TDatePicker.spacer')) - { - $spacer = $this->getAssetUrl('spacer.gif'); - $code = "Prado.WebUI.TDatePicker.spacer = '$spacer';"; - $cs->registerEndScript('TDatePicker.spacer', $code); - } + + $cs = $this->getPage()->getClientScript(); + $cs->registerPradoScript("activedatepicker"); - $options = TJavaScript::encode($this->getDatePickerOptions()); - $code = "new Prado.WebUI.TActiveDatePicker($options);"; - $cs->registerEndScript("prado:".$this->getClientID(), $code); + if(!$cs->isEndScriptRegistered('TDatePicker.spacer')) + { + $spacer = $this->getAssetUrl('spacer.gif'); + $code = "Prado.WebUI.TDatePicker.spacer = '$spacer';"; + $cs->registerEndScript('TDatePicker.spacer', $code); } + + $options = TJavaScript::encode($this->getDatePickerOptions()); + $code = "new Prado.WebUI.TActiveDatePicker($options);"; + $cs->registerEndScript("prado:".$this->getClientID(), $code); } } ?> diff --git a/framework/Web/UI/ActiveControls/TActiveDropDownList.php b/framework/Web/UI/ActiveControls/TActiveDropDownList.php index e66b4cbd..c9458494 100644 --- a/framework/Web/UI/ActiveControls/TActiveDropDownList.php +++ b/framework/Web/UI/ActiveControls/TActiveDropDownList.php @@ -105,8 +105,9 @@ class TActiveDropDownList extends TDropDownList implements ICallbackEventHandler { parent::addAttributesToRender($writer); $writer->addAttribute('id',$this->getClientID()); - $this->getActiveControl()->registerCallbackClientScript( - $this->getClientClassName(), $this->getPostBackOptions()); + if ($this->getAutoPostBack()) + $this->getActiveControl()->registerCallbackClientScript( + $this->getClientClassName(), $this->getPostBackOptions()); } /** diff --git a/framework/Web/UI/ActiveControls/TActiveFileUpload.php b/framework/Web/UI/ActiveControls/TActiveFileUpload.php index e1b85f0d..b935936b 100755 --- a/framework/Web/UI/ActiveControls/TActiveFileUpload.php +++ b/framework/Web/UI/ActiveControls/TActiveFileUpload.php @@ -133,7 +133,30 @@ EOS; * default "Application.runtime.*" */ public function setTempPath($value){ - $this->setViewState('TempNamespace',$value,'Application.runtime.*'); + $this->setViewState('TempPath',$value,'Application.runtime.*'); + } + + /** + * @return boolean a value indicating whether an automatic callback to the server will occur whenever the user modifies the text in the TTextBox control and then tabs out of the component. Defaults to true. + * Note: When set to false, you will need to trigger the callback yourself. + */ + public function getAutoPostBack(){ + return $this->getViewState('AutoPostBack', true); + } + + /** + * @param boolean a value indicating whether an automatic callback to the server will occur whenever the user modifies the text in the TTextBox control and then tabs out of the component. Defaults to true. + * Note: When set to false, you will need to trigger the callback yourself. + */ + public function setAutoPostBack($value){ + $this->setViewState('AutoPostBack',TPropertyValue::ensureBoolean($value),true); + } + + /** + * @return string A chuck of javascript that will need to be called if {{@link getAutoPostBack AutoPostBack} is set to false} + */ + public function getCallbackJavascript(){ + return "Prado.WebUI.TActiveFileUpload.fileChanged(\"{$this->getClientID()}\")"; } /** @@ -172,6 +195,7 @@ EOS; */ public function onPreRender($param){ parent::onPreRender($param); + $this->getPage()->getClientScript()->registerPradoScript('effects'); $this->getPage()->getClientScript()->registerPradoScript('activefileupload'); } @@ -266,6 +290,7 @@ EOS; $options['indicatorID'] = $this->_busy->getClientID(); $options['completeID'] = $this->_success->getClientID(); $options['errorID'] = $this->_error->getClientID(); + $options['autoPostBack'] = $this->getAutoPostBack(); return $options; } @@ -312,4 +337,4 @@ EOS; $this->ensureChildControls(); return $this->_busy; } -}
\ No newline at end of file +} diff --git a/framework/Web/UI/ActiveControls/TActiveListBox.php b/framework/Web/UI/ActiveControls/TActiveListBox.php index 3deb9a0f..29857ee5 100644 --- a/framework/Web/UI/ActiveControls/TActiveListBox.php +++ b/framework/Web/UI/ActiveControls/TActiveListBox.php @@ -149,8 +149,9 @@ class TActiveListBox extends TListBox implements IActiveControl, ICallbackEventH { parent::addAttributesToRender($writer); $writer->addAttribute('id',$this->getClientID()); - $this->getActiveControl()->registerCallbackClientScript( - $this->getClientClassName(), $this->getPostBackOptions()); + if ($this->getAutoPostBack()) + $this->getActiveControl()->registerCallbackClientScript( + $this->getClientClassName(), $this->getPostBackOptions()); } } diff --git a/framework/Web/UI/ActiveControls/TActivePageAdapter.php b/framework/Web/UI/ActiveControls/TActivePageAdapter.php index c52f0775..90eed970 100644 --- a/framework/Web/UI/ActiveControls/TActivePageAdapter.php +++ b/framework/Web/UI/ActiveControls/TActivePageAdapter.php @@ -1,369 +1,369 @@ -<?php -/** - * TActivePageAdapter, TCallbackErrorHandler and TInvalidCallbackException class file. - * - * @author Wei Zhuo <weizhuo[at]gamil[dot]com> - * @link http://www.pradosoft.com/ - * @copyright Copyright © 2005-2008 PradoSoft - * @license http://www.pradosoft.com/license/ - * @version $Id$ - * @package System.Web.UI.ActiveControls - */ - -/** - * Load callback response adapter class. - */ -Prado::using('System.Web.UI.ActiveControls.TCallbackResponseAdapter'); -Prado::using('System.Web.UI.ActiveControls.TCallbackClientScript'); -Prado::using('System.Web.UI.ActiveControls.TCallbackEventParameter'); - -/** - * TActivePageAdapter class. - * - * Callback request handler. - * - * @author Wei Zhuo <weizhuo[at]gamil[dot]com> - * @version $Id$ - * @package System.Web.UI.ActiveControls - * @since 3.1 - */ -class TActivePageAdapter extends TControlAdapter -{ - /** - * Callback response data header name. - */ - const CALLBACK_DATA_HEADER = 'X-PRADO-DATA'; - /** - * Callback response client-side action header name. - */ - const CALLBACK_ACTION_HEADER = 'X-PRADO-ACTIONS'; - /** - * Callback error header name. - */ - const CALLBACK_ERROR_HEADER = 'X-PRADO-ERROR'; - /** - * Callback page state header name. - */ - const CALLBACK_PAGESTATE_HEADER = 'X-PRADO-PAGESTATE'; - - /** - * Callback redirect url header name. - */ - const CALLBACK_REDIRECT = 'X-PRADO-REDIRECT'; - - /** - * @var ICallbackEventHandler callback event handler. - */ - private $_callbackEventTarget; - /** - * @var mixed callback event parameter. - */ - private $_callbackEventParameter; - /** - * @var TCallbackClientScript callback client script handler - */ - private $_callbackClient; - - private $_controlsToRender=array(); - - /** - * Constructor, trap errors and exception to let the callback response - * handle them. - */ - public function __construct(TPage $control) - { - parent::__construct($control); - - //TODO: can this be done later? - $response = $this->getApplication()->getResponse(); - $response->setAdapter(new TCallbackResponseAdapter($response)); - - $this->trapCallbackErrorsExceptions(); - } - - /** - * Process the callback request. - * @param THtmlWriter html content writer. - */ - public function processCallbackEvent($writer) - { - Prado::trace("ActivePage raiseCallbackEvent()",'System.Web.UI.ActiveControls.TActivePageAdapter'); - $this->raiseCallbackEvent(); - } - - /** - * Register a control for defered render() call. - * @param TControl control for defered rendering - * @param THtmlWriter the renderer - */ - public function registerControlToRender($control,$writer) - { - $id = $control->getUniqueID(); - if(!isset($this->_controlsToRender[$id])) - $this->_controlsToRender[$id] = array($control,$writer); - } - - /** - * Trap errors and exceptions to be handled by TCallbackErrorHandler. - */ - protected function trapCallbackErrorsExceptions() - { - $this->getApplication()->setErrorHandler(new TCallbackErrorHandler); - } - - /** - * Render the callback response. - * @param THtmlWriter html content writer. - */ - public function renderCallbackResponse($writer) - { - Prado::trace("ActivePage renderCallbackResponse()",'System.Web.UI.ActiveControls.TActivePageAdapter'); - if(($url = $this->getResponse()->getAdapter()->getRedirectedUrl())===null) - $this->renderResponse($writer); - else - $this->redirect($url); - } - - /** - * Redirect url on the client-side using javascript. - * @param string new url to load. - */ - protected function redirect($url) - { - Prado::trace("ActivePage redirect()",'System.Web.UI.ActiveControls.TActivePageAdapter'); - $this->appendContentPart($this->getResponse(), self::CALLBACK_REDIRECT, $url); - //$this->getResponse()->appendHeader(self::CALLBACK_REDIRECT.': '.$url); - } - - /** - * Renders the callback response by adding additional callback data and - * javascript actions in the header and page state if required. - * @param THtmlWriter html content writer. - */ - protected function renderResponse($writer) - { - Prado::trace("ActivePage renderResponse()",'System.Web.UI.ActiveControls.TActivePageAdapter'); - //renders all the defered render() calls. - foreach($this->_controlsToRender as $rid => $forRender) - $forRender[0]->render($forRender[1]); - - $response = $this->getResponse(); - - //send response data in header - if($response->getHasAdapter()) - { - $responseData = $response->getAdapter()->getResponseData(); - if(!is_null($responseData)) - { - $data = TJavaScript::jsonEncode($responseData); - - $this->appendContentPart($response, self::CALLBACK_DATA_HEADER, $data); - //$response->appendHeader(self::CALLBACK_DATA_HEADER.': '.$data); - } - } - - //sends page state in header - if(($handler = $this->getCallbackEventTarget()) !== null) - { - if($handler->getActiveControl()->getClientSide()->getEnablePageStateUpdate()) - { - $pagestate = $this->getPage()->getClientState(); - $this->appendContentPart($response, self::CALLBACK_PAGESTATE_HEADER, $pagestate); - //$response->appendHeader(self::CALLBACK_PAGESTATE_HEADER.': '.$pagestate); - } - } - - //safari must receive at least 1 byte of data. - $writer->write(" "); - - //output the end javascript - if($this->getPage()->getClientScript()->hasEndScripts()) - { - $writer = $response->createHtmlWriter(); - $this->getPage()->getClientScript()->renderEndScripts($writer); - $this->getPage()->getCallbackClient()->evaluateScript($writer); - } - - //output the actions - $executeJavascript = $this->getCallbackClientHandler()->getClientFunctionsToExecute(); - $actions = TJavaScript::jsonEncode($executeJavascript); - $this->appendContentPart($response, self::CALLBACK_ACTION_HEADER, $actions); - //$response->appendHeader(self::CALLBACK_ACTION_HEADER.': '.$actions); - } - - /** - * Appends data or javascript code to the body content surrounded with delimiters - */ - private function appendContentPart($response, $delimiter, $data) - { - $content = $response->createHtmlWriter(); - $content->getWriter()->setBoundary($delimiter); - $content->write($data); - } - - /** - * Trys to find the callback event handler and raise its callback event. - * @throws TInvalidCallbackException if call back target is not found. - * @throws TInvalidCallbackException if the requested target does not - * implement ICallbackEventHandler. - */ - private function raiseCallbackEvent() - { - if(($callbackHandler=$this->getCallbackEventTarget())!==null) - { - if($callbackHandler instanceof ICallbackEventHandler) - { - $param = $this->getCallbackEventParameter(); - $result = new TCallbackEventParameter($this->getResponse(), $param); - $callbackHandler->raiseCallbackEvent($result); - } - else - { - throw new TInvalidCallbackException( - 'callback_invalid_handler', $callbackHandler->getUniqueID()); - } - } - else - { - $target = $this->getRequest()->itemAt(TPage::FIELD_CALLBACK_TARGET); - throw new TInvalidCallbackException('callback_invalid_target', $target); - } - } - - /** - * @return TControl the control responsible for the current callback event, - * null if nonexistent - */ - public function getCallbackEventTarget() - { - if($this->_callbackEventTarget===null) - { - $eventTarget=$this->getRequest()->itemAt(TPage::FIELD_CALLBACK_TARGET); - if(!empty($eventTarget)) - $this->_callbackEventTarget=$this->getPage()->findControl($eventTarget); - } - return $this->_callbackEventTarget; - } - - /** - * Registers a control to raise callback event in the current request. - * @param TControl control registered to raise callback event. - */ - public function setCallbackEventTarget(TControl $control) - { - $this->_callbackEventTarget=$control; - } - - /** - * Gets callback parameter. JSON encoding is assumed. - * @return string postback event parameter - */ - public function getCallbackEventParameter() - { - if($this->_callbackEventParameter===null) - { - $param = $this->getRequest()->itemAt(TPage::FIELD_CALLBACK_PARAMETER); - if(strlen($param) > 0) - $this->_callbackEventParameter=TJavaScript::jsonDecode((string)$param); - } - return $this->_callbackEventParameter; - } - - /** - * @param mixed postback event parameter - */ - public function setCallbackEventParameter($value) - { - $this->_callbackEventParameter=$value; - } - - /** - * Gets the callback client script handler. It handlers the javascript functions - * to be executed during the callback response. - * @return TCallbackClientScript callback client handler. - */ - public function getCallbackClientHandler() - { - if(is_null($this->_callbackClient)) - $this->_callbackClient = new TCallbackClientScript; - return $this->_callbackClient; - } -} - -/** - * TCallbackErrorHandler class. - * - * Captures errors and exceptions and send them back during callback response. - * When the application is in debug mode, the error and exception stack trace - * are shown. A TJavascriptLogger must be present on the client-side to view - * the error stack trace. - * - * @author Wei Zhuo <weizhuo[at]gmail[dot]com> - * @version $Id$ - * @package System.Web.UI.ActiveControls - * @since 3.1 - */ -class TCallbackErrorHandler extends TErrorHandler -{ - /** - * Displays the exceptions to the client-side TJavascriptLogger. - * A HTTP 500 status code is sent and the stack trace is sent as JSON encoded. - * @param Exception exception details. - */ - protected function displayException($exception) - { - if($this->getApplication()->getMode()===TApplication::STATE_DEBUG) - { - $response = $this->getApplication()->getResponse(); - $trace = TJavaScript::jsonEncode($this->getExceptionStackTrace($exception)); - $response->appendHeader('HTTP/1.0 500 Internal Error'); - $response->appendHeader(TActivePageAdapter::CALLBACK_ERROR_HEADER.': '.$trace); - } - else - { - error_log("Error happened while processing an existing error:\n".$exception->__toString()); - header('HTTP/1.0 500 Internal Error'); - } - $this->getApplication()->getResponse()->flush(); - } - - /** - * @param Exception exception details. - * @return array exception stack trace details. - */ - private function getExceptionStackTrace($exception) - { - $data['code']=$exception->getCode() > 0 ? $exception->getCode() : 500; - $data['file']=$exception->getFile(); - $data['line']=$exception->getLine(); - $data['trace']=$exception->getTrace(); - if($exception instanceof TPhpErrorException) - { - // if PHP exception, we want to show the 2nd stack level context - // because the 1st stack level is of little use (it's in error handler) - if(isset($trace[0]) && isset($trace[0]['file']) && isset($trace[0]['line'])) - { - $data['file']=$trace[0]['file']; - $data['line']=$trace[0]['line']; - } - } - $data['type']=get_class($exception); - $data['message']=$exception->getMessage(); - $data['version']=$_SERVER['SERVER_SOFTWARE'].' '.Prado::getVersion(); - $data['time']=@strftime('%Y-%m-%d %H:%M',time()); - return $data; - } -} - -/** - * TInvalidCallbackException class. - * - * @author Wei Zhuo <weizhuo[at]gmail[dot]com> - * @version $Id$ - * @package System.Web.UI.ActiveControls - * @since 3.1 - */ -class TInvalidCallbackException extends TException -{ -} - +<?php
+/**
+ * TActivePageAdapter, TCallbackErrorHandler and TInvalidCallbackException class file.
+ *
+ * @author Wei Zhuo <weizhuo[at]gamil[dot]com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright © 2005-2008 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @package System.Web.UI.ActiveControls
+ */
+
+/**
+ * Load callback response adapter class.
+ */
+Prado::using('System.Web.UI.ActiveControls.TCallbackResponseAdapter');
+Prado::using('System.Web.UI.ActiveControls.TCallbackClientScript');
+Prado::using('System.Web.UI.ActiveControls.TCallbackEventParameter');
+
+/**
+ * TActivePageAdapter class.
+ *
+ * Callback request handler.
+ *
+ * @author Wei Zhuo <weizhuo[at]gamil[dot]com>
+ * @version $Id$
+ * @package System.Web.UI.ActiveControls
+ * @since 3.1
+ */
+class TActivePageAdapter extends TControlAdapter
+{
+ /**
+ * Callback response data header name.
+ */
+ const CALLBACK_DATA_HEADER = 'X-PRADO-DATA';
+ /**
+ * Callback response client-side action header name.
+ */
+ const CALLBACK_ACTION_HEADER = 'X-PRADO-ACTIONS';
+ /**
+ * Callback error header name.
+ */
+ const CALLBACK_ERROR_HEADER = 'X-PRADO-ERROR';
+ /**
+ * Callback page state header name.
+ */
+ const CALLBACK_PAGESTATE_HEADER = 'X-PRADO-PAGESTATE';
+
+ /**
+ * Callback redirect url header name.
+ */
+ const CALLBACK_REDIRECT = 'X-PRADO-REDIRECT';
+
+ /**
+ * @var ICallbackEventHandler callback event handler.
+ */
+ private $_callbackEventTarget;
+ /**
+ * @var mixed callback event parameter.
+ */
+ private $_callbackEventParameter;
+ /**
+ * @var TCallbackClientScript callback client script handler
+ */
+ private $_callbackClient;
+
+ private $_controlsToRender=array();
+
+ /**
+ * Constructor, trap errors and exception to let the callback response
+ * handle them.
+ */
+ public function __construct(TPage $control)
+ {
+ parent::__construct($control);
+
+ //TODO: can this be done later?
+ $response = $this->getApplication()->getResponse();
+ $response->setAdapter(new TCallbackResponseAdapter($response));
+
+ $this->trapCallbackErrorsExceptions();
+ }
+
+ /**
+ * Process the callback request.
+ * @param THtmlWriter html content writer.
+ */
+ public function processCallbackEvent($writer)
+ {
+ Prado::trace("ActivePage raiseCallbackEvent()",'System.Web.UI.ActiveControls.TActivePageAdapter');
+ $this->raiseCallbackEvent();
+ }
+
+ /**
+ * Register a control for defered render() call.
+ * @param TControl control for defered rendering
+ * @param THtmlWriter the renderer
+ */
+ public function registerControlToRender($control,$writer)
+ {
+ $id = $control->getUniqueID();
+ if(!isset($this->_controlsToRender[$id]))
+ $this->_controlsToRender[$id] = array($control,$writer);
+ }
+
+ /**
+ * Trap errors and exceptions to be handled by TCallbackErrorHandler.
+ */
+ protected function trapCallbackErrorsExceptions()
+ {
+ $this->getApplication()->setErrorHandler(new TCallbackErrorHandler);
+ }
+
+ /**
+ * Render the callback response.
+ * @param THtmlWriter html content writer.
+ */
+ public function renderCallbackResponse($writer)
+ {
+ Prado::trace("ActivePage renderCallbackResponse()",'System.Web.UI.ActiveControls.TActivePageAdapter');
+ if(($url = $this->getResponse()->getAdapter()->getRedirectedUrl())===null)
+ $this->renderResponse($writer);
+ else
+ $this->redirect($url);
+ }
+
+ /**
+ * Redirect url on the client-side using javascript.
+ * @param string new url to load.
+ */
+ protected function redirect($url)
+ {
+ Prado::trace("ActivePage redirect()",'System.Web.UI.ActiveControls.TActivePageAdapter');
+ $this->appendContentPart($this->getResponse(), self::CALLBACK_REDIRECT, $url);
+ //$this->getResponse()->appendHeader(self::CALLBACK_REDIRECT.': '.$url);
+ }
+
+ /**
+ * Renders the callback response by adding additional callback data and
+ * javascript actions in the header and page state if required.
+ * @param THtmlWriter html content writer.
+ */
+ protected function renderResponse($writer)
+ {
+ Prado::trace("ActivePage renderResponse()",'System.Web.UI.ActiveControls.TActivePageAdapter');
+ //renders all the defered render() calls.
+ foreach($this->_controlsToRender as $rid => $forRender)
+ $forRender[0]->render($forRender[1]);
+
+ $response = $this->getResponse();
+
+ //send response data in header
+ if($response->getHasAdapter())
+ {
+ $responseData = $response->getAdapter()->getResponseData();
+ if($responseData!==null)
+ {
+ $data = TJavaScript::jsonEncode($responseData);
+
+ $this->appendContentPart($response, self::CALLBACK_DATA_HEADER, $data);
+ //$response->appendHeader(self::CALLBACK_DATA_HEADER.': '.$data);
+ }
+ }
+
+ //sends page state in header
+ if(($handler = $this->getCallbackEventTarget()) !== null)
+ {
+ if($handler->getActiveControl()->getClientSide()->getEnablePageStateUpdate())
+ {
+ $pagestate = $this->getPage()->getClientState();
+ $this->appendContentPart($response, self::CALLBACK_PAGESTATE_HEADER, $pagestate);
+ //$response->appendHeader(self::CALLBACK_PAGESTATE_HEADER.': '.$pagestate);
+ }
+ }
+
+ //safari must receive at least 1 byte of data.
+ $writer->write(" ");
+
+ //output the end javascript
+ if($this->getPage()->getClientScript()->hasEndScripts())
+ {
+ $writer = $response->createHtmlWriter();
+ $this->getPage()->getClientScript()->renderEndScripts($writer);
+ $this->getPage()->getCallbackClient()->evaluateScript($writer);
+ }
+
+ //output the actions
+ $executeJavascript = $this->getCallbackClientHandler()->getClientFunctionsToExecute();
+ $actions = TJavaScript::jsonEncode($executeJavascript);
+ $this->appendContentPart($response, self::CALLBACK_ACTION_HEADER, $actions);
+ //$response->appendHeader(self::CALLBACK_ACTION_HEADER.': '.$actions);
+ }
+
+ /**
+ * Appends data or javascript code to the body content surrounded with delimiters
+ */
+ private function appendContentPart($response, $delimiter, $data)
+ {
+ $content = $response->createHtmlWriter();
+ $content->getWriter()->setBoundary($delimiter);
+ $content->write($data);
+ }
+
+ /**
+ * Trys to find the callback event handler and raise its callback event.
+ * @throws TInvalidCallbackException if call back target is not found.
+ * @throws TInvalidCallbackException if the requested target does not
+ * implement ICallbackEventHandler.
+ */
+ private function raiseCallbackEvent()
+ {
+ if(($callbackHandler=$this->getCallbackEventTarget())!==null)
+ {
+ if($callbackHandler instanceof ICallbackEventHandler)
+ {
+ $param = $this->getCallbackEventParameter();
+ $result = new TCallbackEventParameter($this->getResponse(), $param);
+ $callbackHandler->raiseCallbackEvent($result);
+ }
+ else
+ {
+ throw new TInvalidCallbackException(
+ 'callback_invalid_handler', $callbackHandler->getUniqueID());
+ }
+ }
+ else
+ {
+ $target = $this->getRequest()->itemAt(TPage::FIELD_CALLBACK_TARGET);
+ throw new TInvalidCallbackException('callback_invalid_target', $target);
+ }
+ }
+
+ /**
+ * @return TControl the control responsible for the current callback event,
+ * null if nonexistent
+ */
+ public function getCallbackEventTarget()
+ {
+ if($this->_callbackEventTarget===null)
+ {
+ $eventTarget=$this->getRequest()->itemAt(TPage::FIELD_CALLBACK_TARGET);
+ if(!empty($eventTarget))
+ $this->_callbackEventTarget=$this->getPage()->findControl($eventTarget);
+ }
+ return $this->_callbackEventTarget;
+ }
+
+ /**
+ * Registers a control to raise callback event in the current request.
+ * @param TControl control registered to raise callback event.
+ */
+ public function setCallbackEventTarget(TControl $control)
+ {
+ $this->_callbackEventTarget=$control;
+ }
+
+ /**
+ * Gets callback parameter. JSON encoding is assumed.
+ * @return string postback event parameter
+ */
+ public function getCallbackEventParameter()
+ {
+ if($this->_callbackEventParameter===null)
+ {
+ $param = $this->getRequest()->itemAt(TPage::FIELD_CALLBACK_PARAMETER);
+ if(strlen($param) > 0)
+ $this->_callbackEventParameter=TJavaScript::jsonDecode((string)$param);
+ }
+ return $this->_callbackEventParameter;
+ }
+
+ /**
+ * @param mixed postback event parameter
+ */
+ public function setCallbackEventParameter($value)
+ {
+ $this->_callbackEventParameter=$value;
+ }
+
+ /**
+ * Gets the callback client script handler. It handlers the javascript functions
+ * to be executed during the callback response.
+ * @return TCallbackClientScript callback client handler.
+ */
+ public function getCallbackClientHandler()
+ {
+ if($this->_callbackClient===null)
+ $this->_callbackClient = new TCallbackClientScript;
+ return $this->_callbackClient;
+ }
+}
+
+/**
+ * TCallbackErrorHandler class.
+ *
+ * Captures errors and exceptions and send them back during callback response.
+ * When the application is in debug mode, the error and exception stack trace
+ * are shown. A TJavascriptLogger must be present on the client-side to view
+ * the error stack trace.
+ *
+ * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
+ * @version $Id$
+ * @package System.Web.UI.ActiveControls
+ * @since 3.1
+ */
+class TCallbackErrorHandler extends TErrorHandler
+{
+ /**
+ * Displays the exceptions to the client-side TJavascriptLogger.
+ * A HTTP 500 status code is sent and the stack trace is sent as JSON encoded.
+ * @param Exception exception details.
+ */
+ protected function displayException($exception)
+ {
+ if($this->getApplication()->getMode()===TApplication::STATE_DEBUG)
+ {
+ $response = $this->getApplication()->getResponse();
+ $trace = TJavaScript::jsonEncode($this->getExceptionStackTrace($exception));
+ $response->appendHeader('HTTP/1.0 500 Internal Error');
+ $response->appendHeader(TActivePageAdapter::CALLBACK_ERROR_HEADER.': '.$trace);
+ }
+ else
+ {
+ error_log("Error happened while processing an existing error:\n".$exception->__toString());
+ header('HTTP/1.0 500 Internal Error');
+ }
+ $this->getApplication()->getResponse()->flush();
+ }
+
+ /**
+ * @param Exception exception details.
+ * @return array exception stack trace details.
+ */
+ private function getExceptionStackTrace($exception)
+ {
+ $data['code']=$exception->getCode() > 0 ? $exception->getCode() : 500;
+ $data['file']=$exception->getFile();
+ $data['line']=$exception->getLine();
+ $data['trace']=$exception->getTrace();
+ if($exception instanceof TPhpErrorException)
+ {
+ // if PHP exception, we want to show the 2nd stack level context
+ // because the 1st stack level is of little use (it's in error handler)
+ if(isset($trace[0]) && isset($trace[0]['file']) && isset($trace[0]['line']))
+ {
+ $data['file']=$trace[0]['file'];
+ $data['line']=$trace[0]['line'];
+ }
+ }
+ $data['type']=get_class($exception);
+ $data['message']=$exception->getMessage();
+ $data['version']=$_SERVER['SERVER_SOFTWARE'].' '.Prado::getVersion();
+ $data['time']=@strftime('%Y-%m-%d %H:%M',time());
+ return $data;
+ }
+}
+
+/**
+ * TInvalidCallbackException class.
+ *
+ * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
+ * @version $Id$
+ * @package System.Web.UI.ActiveControls
+ * @since 3.1
+ */
+class TInvalidCallbackException extends TException
+{
+}
+
diff --git a/framework/Web/UI/ActiveControls/TActivePanel.php b/framework/Web/UI/ActiveControls/TActivePanel.php index 51e9fb08..25a42eb7 100644 --- a/framework/Web/UI/ActiveControls/TActivePanel.php +++ b/framework/Web/UI/ActiveControls/TActivePanel.php @@ -4,7 +4,7 @@ *
* @author Wei Zhuo <weizhuo[at]gamil[dot]com>
* @link http://www.pradosoft.com/
- * @copyright Copyright © 2005-2008 PradoSoft + * @copyright Copyright © 2005-2008 PradoSoft
* @license http://www.pradosoft.com/license/
* @version $Id$
* @package System.Web.UI.ActiveControls
@@ -58,6 +58,15 @@ class TActivePanel extends TPanel implements IActiveControl }
/**
+ * Adds attribute id to the renderer.
+ * @param THtmlWriter the writer used for the rendering purpose
+ */
+ protected function addAttributesToRender($writer) {
+ $writer->addAttribute('id',$this->getClientID());
+ parent::addAttributesToRender($writer);
+ }
+
+ /**
* Renders and replaces the panel's content on the client-side.
* When render() is called before the OnPreRender event, such as when render()
* is called during a callback event handler, the rendering
@@ -74,16 +83,16 @@ class TActivePanel extends TPanel implements IActiveControl }
else
{
- $this->getPage()->getAdapter()->registerControlToRender($this,$writer); - if ($this->getHasControls()) - { - // If we update a TActivePanel on callback, - // We shouldn't update all childs, because the whole content will be replaced by - // the parent - foreach ($this->findControlsByType('IActiveControl', false) as $control) - { - $control->getActiveControl()->setEnableUpdate(false); - } + $this->getPage()->getAdapter()->registerControlToRender($this,$writer);
+ if ($this->getHasControls())
+ {
+ // If we update a TActivePanel on callback,
+ // We shouldn't update all childs, because the whole content will be replaced by
+ // the parent
+ foreach ($this->findControlsByType('IActiveControl', false) as $control)
+ {
+ $control->getActiveControl()->setEnableUpdate(false);
+ }
}
}
}
diff --git a/framework/Web/UI/ActiveControls/TActiveRadioButton.php b/framework/Web/UI/ActiveControls/TActiveRadioButton.php index f7e9a286..8e2195d3 100644 --- a/framework/Web/UI/ActiveControls/TActiveRadioButton.php +++ b/framework/Web/UI/ActiveControls/TActiveRadioButton.php @@ -120,12 +120,15 @@ class TActiveRadioButton extends TRadioButton implements IActiveControl, ICallba /** * Ensure that the ID attribute is rendered and registers the javascript code * for initializing the active control. + * Since 3.1.4, the javascript code is not rendered if {@link setAutoPostBack AutoPostBack} is false + * */ protected function renderInputTag($writer,$clientID,$onclick) { parent::renderInputTag($writer,$clientID,$onclick); - $this->getActiveControl()->registerCallbackClientScript( - $this->getClientClassName(), $this->getPostBackOptions()); + if ($this->getAutoPostBack()) + $this->getActiveControl()->registerCallbackClientScript( + $this->getClientClassName(), $this->getPostBackOptions()); } /** diff --git a/framework/Web/UI/ActiveControls/TAutoComplete.php b/framework/Web/UI/ActiveControls/TAutoComplete.php index 5a3633ec..13200e51 100644 --- a/framework/Web/UI/ActiveControls/TAutoComplete.php +++ b/framework/Web/UI/ActiveControls/TAutoComplete.php @@ -235,7 +235,7 @@ class TAutoComplete extends TActiveTextBox implements INamingContainer */
public function getResultPanel()
{
- if(is_null($this->_resultPanel))
+ if($this->_resultPanel===null)
$this->_resultPanel = $this->createResultPanel();
return $this->_resultPanel;
}
@@ -256,7 +256,7 @@ class TAutoComplete extends TActiveTextBox implements INamingContainer */
public function getSuggestions()
{
- if(is_null($this->_repeater))
+ if($this->_repeater===null)
$this->_repeater = $this->createRepeater();
return $this->_repeater;
}
diff --git a/framework/Web/UI/ActiveControls/TBaseActiveControl.php b/framework/Web/UI/ActiveControls/TBaseActiveControl.php index 8f55e27b..f301f2c3 100644 --- a/framework/Web/UI/ActiveControls/TBaseActiveControl.php +++ b/framework/Web/UI/ActiveControls/TBaseActiveControl.php @@ -58,8 +58,8 @@ class TBaseActiveControl extends TComponent */
protected function setOption($name,$value,$default=null)
{
- $value = is_null($value) ? $default : $value;
- if(!is_null($value))
+ $value = ($value===null) ? $default : $value;
+ if($value!==null)
$this->_options->add($name,$value);
}
@@ -73,7 +73,7 @@ class TBaseActiveControl extends TComponent protected function getOption($name,$default=null)
{
$item = $this->_options->itemAt($name);
- return is_null($item) ? $default : $item;
+ return ($item===null) ? $default : $item;
}
/**
@@ -168,7 +168,7 @@ class TBaseActiveCallbackControl extends TBaseActiveControl */
public function getClientSide()
{
- if(is_null($client = $this->getOption('ClientSide')))
+ if(($client = $this->getOption('ClientSide'))===null)
{
$client = $this->createClientSide();
$this->setOption('ClientSide', $client);
@@ -182,7 +182,7 @@ class TBaseActiveCallbackControl extends TBaseActiveControl */
public function setClientSide($client)
{
- if(is_null($this->getOption('ClientSide')))
+ if( $this->getOption('ClientSide')===null)
$this->setOption('ClientSide', $client);
else
throw new TConfigurationException(
diff --git a/framework/Web/UI/ActiveControls/TCallbackClientScript.php b/framework/Web/UI/ActiveControls/TCallbackClientScript.php index 8f275ef8..062f63dc 100644 --- a/framework/Web/UI/ActiveControls/TCallbackClientScript.php +++ b/framework/Web/UI/ActiveControls/TCallbackClientScript.php @@ -4,7 +4,7 @@ *
* @author Wei Zhuo <weizhuo[at]gamil[dot]com>
* @link http://www.pradosoft.com/
- * @copyright Copyright © 2005-2008 PradoSoft + * @copyright Copyright © 2005-2008 PradoSoft
* @license http://www.pradosoft.com/license/
* @version $Id$
* @package System.Web.UI.ActiveControls
@@ -104,7 +104,7 @@ class TCallbackClientScript extends TApplicationComponent {
$method = TPropertyValue::ensureEnum($method,
'Value', 'Index', 'Clear', 'Indices', 'Values', 'All', 'Invert');
- $type = is_null($type) ? $this->getSelectionControlType($control) : $type;
+ $type = ($type===null) ? $this->getSelectionControlType($control) : $type;
$total = $this->getSelectionControlIsListType($control) ? $control->getItemCount() : 1;
$this->callClientFunction('Prado.Element.select',
array($control, $type.$method, $value, $total));
@@ -164,8 +164,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function setAttribute($control, $name, $value)
{
- if ($control instanceof ISurroundable) - $control=$control->getSurroundingTagID(); + if ($control instanceof ISurroundable)
+ $control=$control->getSurroundingTagID();
$this->callClientFunction('Prado.Element.setAttribute',array($control, $name, $value));
}
@@ -177,6 +177,18 @@ class TCallbackClientScript extends TApplicationComponent public function setListItems($control, $items)
{
$options = array();
+ if($control instanceof TListControl)
+ {
+ $promptText = $control->getPromptText();
+ $promptValue = $control->getPromptValue();
+
+ if($promptValue==='')
+ $promptValue = $promptText;
+
+ if($promptValue!=='')
+ $options[] = array($promptText, $promptValue);
+ }
+
foreach($items as $item)
{
if($item->getHasAttributes())
@@ -193,8 +205,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function show($element)
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->callClientFunction('Element.show', $element);
}
@@ -204,8 +216,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function hide($element)
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->callClientFunction('Element.hide', $element);
}
@@ -217,8 +229,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function toggle($element, $effect=null, $options=array())
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->callClientFunction('Element.toggle', array($element,$effect,$options));
}
@@ -228,8 +240,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function remove($element)
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->callClientFunction('Element.remove', $element);
}
@@ -246,8 +258,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function update($element, $content)
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->replace($element, $content, 'Element.update');
}
@@ -258,8 +270,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function addCssClass($element, $cssClass)
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->callClientFunction('Element.addClassName', array($element, $cssClass));
}
@@ -270,8 +282,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function removeCssClass($element, $cssClass)
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->callClientFunction('Element.removeClassName', array($element, $cssClass));
}
@@ -292,8 +304,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function scrollTo($element)
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->callClientFunction('Element.scrollTo', $element);
}
@@ -313,9 +325,9 @@ class TCallbackClientScript extends TApplicationComponent * @param array list of key-value pairs as style property and style value.
*/
public function setStyle($element, $styles)
- { - if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + {
+ if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->callClientFunction('Prado.Element.setStyle', array($element, $styles));
}
@@ -326,8 +338,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function appendContent($element, $content)
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->replace($element, $content, 'Prado.Element.Insert.append');
}
@@ -338,8 +350,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function prependContent($element, $content)
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->replace($element, $content, 'Prado.Element.Insert.prepend');
}
@@ -350,8 +362,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function insertContentAfter($element, $content)
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->replace($element, $content, 'Prado.Element.Insert.after');
}
@@ -362,8 +374,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function insertContentBefore($element, $content)
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->replace($element, $content, 'Prado.Element.Insert.before');
}
@@ -406,8 +418,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function replaceContent($element,$content)
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->replace($element, $content);
}
@@ -458,8 +470,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function visualEffect($type, $element, $options=null)
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->callClientFunction($type, array($element, $options));
}
@@ -470,8 +482,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function appear($element, $options=null)
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->visualEffect('Effect.Appear', $element, $options);
}
@@ -482,8 +494,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function blindDown($element, $options=null)
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->visualEffect('Effect.BlindDown', $element, $options);
}
@@ -494,8 +506,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function blindUp($element, $options=null)
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->visualEffect('Effect.BlindUp', $element, $options);
}
@@ -507,8 +519,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function dropOut($element, $options=null)
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->visualEffect('Effect.DropOut', $element, $options);
}
@@ -519,8 +531,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function fade($element, $options=null)
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->visualEffect('Effect.Fade', $element, $options);
}
@@ -531,8 +543,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function fold($element, $options = null)
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->visualEffect('Effect.Fold', $element, $options);
}
@@ -543,8 +555,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function grow($element, $options=null)
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->visualEffect('Effect.Grow', $element, $options);
}
@@ -555,8 +567,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function puff($element, $options=null)
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->visualEffect('Effect.Puff', $element, $options);
}
@@ -567,8 +579,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function pulsate($element, $options=null)
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->visualEffect('Effect.Pulsate', $element, $options);
}
@@ -579,8 +591,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function shake($element, $options=null)
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->visualEffect('Effect.Shake', $element, $options);
}
@@ -591,8 +603,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function shrink($element, $options=null)
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->visualEffect('Effect.Shrink', $element, $options);
}
@@ -603,8 +615,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function slideDown($element, $options=null)
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->visualEffect('Effect.SlideDown', $element, $options);
}
@@ -615,8 +627,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function slideUp($element, $options=null)
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->visualEffect('Effect.SlideUp', $element, $options);
}
@@ -627,8 +639,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function squish($element, $options=null)
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->visualEffect('Effect.Squish', $element, $options);
}
@@ -639,8 +651,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function switchOff($element, $options=null)
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->visualEffect('Effect.SwitchOff', $element, $options);
}
@@ -651,8 +663,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function highlight($element, $options=null)
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$this->visualEffect('Prado.Effect.Highlight', $element, $options);
}
@@ -663,8 +675,8 @@ class TCallbackClientScript extends TApplicationComponent */
public function setOpacity($element, $value)
{
- if ($element instanceof ISurroundable) - $element=$element->getSurroundingTagID(); + if ($element instanceof ISurroundable)
+ $element=$element->getSurroundingTagID();
$value = TPropertyValue::ensureFloat($value);
$this->callClientFunction('Element.setOpacity', array($element,$value));
}
diff --git a/framework/Web/UI/ActiveControls/TCallbackClientSide.php b/framework/Web/UI/ActiveControls/TCallbackClientSide.php index 57436278..31b806c3 100644 --- a/framework/Web/UI/ActiveControls/TCallbackClientSide.php +++ b/framework/Web/UI/ActiveControls/TCallbackClientSide.php @@ -4,7 +4,7 @@ *
* @author Wei Zhuo <weizhuo[at]gamil[dot]com>
* @link http://www.pradosoft.com/
- * @copyright Copyright © 2005-2008 PradoSoft + * @copyright Copyright © 2005-2008 PradoSoft
* @license http://www.pradosoft.com/license/
* @version $Id$
* @package System.Web.UI.ActiveControls
@@ -22,13 +22,13 @@ * - <b>onLoaded</b>* executed when callback request begins.
* - <b>onInteractive</b> executed when callback request is in progress.
* - <b>onComplete</b>executed when callback response returns.
- * - * * Note that theses 2 events are not fired correctly by Opera. To make - * them work in this browser, Prado will fire them just after onPreDispatch. - * - * In a general way, onUninitialized, onLoading, onLoaded and onInteractive events - * are not implemented consistently in all browsers.When cross browser compatibility is - * needed, it is best to avoid use them + *
+ * * Note that theses 2 events are not fired correctly by Opera. To make
+ * them work in this browser, Prado will fire them just after onPreDispatch.
+ *
+ * In a general way, onUninitialized, onLoading, onLoaded and onInteractive events
+ * are not implemented consistently in all browsers.When cross browser compatibility is
+ * needed, it is best to avoid use them
*
* The OnSuccess and OnFailure events are raised when the
* response is returned. A successful request/response will raise
@@ -247,7 +247,7 @@ class TCallbackClientSide extends TClientSideOptions public function getHasPriority()
{
$option = $this->getOption('HasPriority');
- return is_null($option) ? true : $option;
+ return ($option===null) ? true : $option;
}
/**
@@ -284,7 +284,7 @@ class TCallbackClientSide extends TClientSideOptions public function getEnablePageStateUpdate()
{
$option = $this->getOption('EnablePageStateUpdate');
- return is_null($option) ? true : $option;
+ return ($option===null) ? true : $option;
}
/**
diff --git a/framework/Web/UI/ActiveControls/TCallbackOptions.php b/framework/Web/UI/ActiveControls/TCallbackOptions.php index 7c48b795..c9b649d8 100644 --- a/framework/Web/UI/ActiveControls/TCallbackOptions.php +++ b/framework/Web/UI/ActiveControls/TCallbackOptions.php @@ -4,7 +4,7 @@ *
* @author Wei Zhuo <weizhuo[at]gamil[dot]com>
* @link http://www.pradosoft.com/
- * @copyright Copyright © 2005-2008 PradoSoft + * @copyright Copyright © 2005-2008 PradoSoft
* @license http://www.pradosoft.com/license/
* @version $Id$
* @package System.Web.UI.ActiveControls
@@ -37,7 +37,7 @@ class TCallbackOptions extends TControl */
public function getClientSide()
{
- if(is_null($this->_clientSide))
+ if($this->_clientSide===null)
$this->_clientSide = $this->createClientSide();
return $this->_clientSide;
}
diff --git a/framework/Web/UI/ActiveControls/TDropContainer.php b/framework/Web/UI/ActiveControls/TDropContainer.php index 5d090d95..75a80625 100755 --- a/framework/Web/UI/ActiveControls/TDropContainer.php +++ b/framework/Web/UI/ActiveControls/TDropContainer.php @@ -123,12 +123,8 @@ class TDropContainer extends TPanel implements IActiveControl, ICallbackEventHan { // Find the control // Warning, this will not work if you have a '_' in your control Id ! - $control=$this->getPage(); - $namingContainers=explode(TControl::CLIENT_ID_SEPARATOR, $dropControlId); - foreach ($namingContainers as $nc) - { - $control=$control->findControl($nc); - } + $dropControlId=str_replace(TControl::CLIENT_ID_SEPARATOR,TControl::ID_SEPARATOR,$dropControlId); + $control=$this->getPage()->findControl($dropControlId); $this->raiseEvent('OnDrop', $this, new TDropContainerEventParameter ($control)); } @@ -196,7 +192,7 @@ class TDropContainer extends TPanel implements IActiveControl, ICallbackEventHan if ($this->_container===null) { $this->_container=Prado::CreateComponent('System.Web.UI.ActiveControls.TActivePanel'); - $this->_container->setId($this->getId().'_content'); + $this->_container->setId($this->getId(false).'_content'); parent::getControls()->add($this->_container); } } diff --git a/framework/Web/UI/ActiveControls/TInPlaceTextBox.php b/framework/Web/UI/ActiveControls/TInPlaceTextBox.php index 6e1c6b7a..b8dd666b 100644 --- a/framework/Web/UI/ActiveControls/TInPlaceTextBox.php +++ b/framework/Web/UI/ActiveControls/TInPlaceTextBox.php @@ -4,7 +4,7 @@ *
* @author Wei Zhuo <weizhuo[at]gamil[dot]com>
* @link http://www.pradosoft.com/
- * @copyright Copyright © 2005-2008 PradoSoft + * @copyright Copyright © 2005-2008 PradoSoft
* @license http://www.pradosoft.com/license/
* @version $Id$
* @package System.Web.UI.ActiveControls
@@ -35,9 +35,9 @@ Prado::using('System.Web.UI.ActiveControls.TActiveTextBox'); * After the callback request returns sucessfully, the textbox is enabled.
* If the {@link setAutoHideTextBox AutoHideTextBox} property is true, then
* the textbox will be hidden and the label is then shown.
- * - * Since 3.1.2, you can set the {@link setReadOnly ReadOnly} property to make - * the control not editable. This property can be also changed on callback + *
+ * Since 3.1.2, you can set the {@link setReadOnly ReadOnly} property to make
+ * the control not editable. This property can be also changed on callback
*
* @author Wei Zhuo <weizhuo[at]gmail[dot]com>
* @version $Id$
@@ -124,7 +124,7 @@ class TInPlaceTextBox extends TActiveTextBox protected function getExternalControlID()
{
$extID = $this->getEditTriggerControlID();
- if(is_null($extID)) return '';
+ if($extID===null) return '';
if(($control = $this->findControl($extID))!==null)
return $control->getClientID();
return $extID;
@@ -144,21 +144,21 @@ class TInPlaceTextBox extends TActiveTextBox $client->update($this->getLabelClientID(), $value);
$client->setValue($this, $value);
}
- } - - /** - * Update ClientSide Readonly property - * @param boolean value - * @since 3.1.2 - */ - public function setReadOnly ($value) - { - $value=TPropertyValue::ensureBoolean($value); - TTextBox::setReadOnly($value); - if ($this->getActiveControl()->canUpdateClientSide()) - { - $this->callClientFunction('setReadOnly', $value); - } + }
+
+ /**
+ * Update ClientSide Readonly property
+ * @param boolean value
+ * @since 3.1.2
+ */
+ public function setReadOnly ($value)
+ {
+ $value=TPropertyValue::ensureBoolean($value);
+ TTextBox::setReadOnly($value);
+ if ($this->getActiveControl()->canUpdateClientSide())
+ {
+ $this->callClientFunction('setReadOnly', $value);
+ }
}
/**
@@ -231,8 +231,8 @@ class TInPlaceTextBox extends TActiveTextBox }
if($this->hasEventHandler('OnLoadingText'))
- $options['LoadTextOnEdit'] = true; - + $options['LoadTextOnEdit'] = true;
+
$options['ReadOnly']=$this->getReadOnly();
return $options;
}
diff --git a/framework/Web/UI/TClientScriptManager.php b/framework/Web/UI/TClientScriptManager.php index f0eb6157..200bcba5 100644 --- a/framework/Web/UI/TClientScriptManager.php +++ b/framework/Web/UI/TClientScriptManager.php @@ -76,7 +76,12 @@ class TClientScriptManager extends TApplicationComponent * @var array */ private static $_pradoScripts; - + /** + * Client-side javascript library packages, loads from SCRIPT_PATH.'/packages.php'; + * @var array + */ + private static $_pradoPackages; + /** * Constructor. * @param TPage page that owns this client script manager @@ -120,6 +125,7 @@ class TClientScriptManager extends TApplicationComponent $packageFile = Prado::getFrameworkPath().DIRECTORY_SEPARATOR.self::SCRIPT_PATH.'/packages.php'; list($packages,$deps)= include($packageFile); self::$_pradoScripts = $deps; + self::$_pradoPackages = $packages; } if(isset(self::$_pradoScripts[$name])) @@ -147,9 +153,31 @@ class TClientScriptManager extends TApplicationComponent { if(($packages=array_keys($this->_registeredPradoScripts))!==array()) { - $base = Prado::getFrameworkPath().DIRECTORY_SEPARATOR.self::SCRIPT_PATH; - $url = $this->registerJavascriptPackages($base, $packages); - $writer->write(TJavaScript::renderScriptFile($url)); + if (Prado::getApplication()->getMode()!==TApplicationMode::Debug) + { + $base = Prado::getFrameworkPath().DIRECTORY_SEPARATOR.self::SCRIPT_PATH; + $url = $this->registerJavascriptPackages($base, $packages); + $writer->write(TJavaScript::renderScriptFile($url)); + } + else + { + // In debug mode, we add 1 <script> line by file + $base = Prado::getFrameworkPath().DIRECTORY_SEPARATOR.self::SCRIPT_PATH; + list($path,$baseUrl)=$this->getPackagePathUrl($base); + $packagesUrl=array(); + foreach ($packages as $p) + { + foreach (self::$_pradoScripts[$p] as $dep) + { + foreach (self::$_pradoPackages[$dep] as $script) + { + if (!in_array($url=$baseUrl.'/'.$script,$packagesUrl)) + $packagesUrl[]=$url; + } + } + } + $writer->write(TJavaScript::renderScriptFiles($packagesUrl)); + } } } diff --git a/framework/Web/UI/THtmlWriter.php b/framework/Web/UI/THtmlWriter.php index 217b9663..9713d941 100644 --- a/framework/Web/UI/THtmlWriter.php +++ b/framework/Web/UI/THtmlWriter.php @@ -232,12 +232,12 @@ class THtmlWriter extends TApplicationComponent implements ITextWriter if(isset(self::$_simpleTags[$tagName]))
{
$str.=' />';
- array_push($this->_openTags,'');
+ $this->_openTags[] = '';
}
else
{
$str.='>';
- array_push($this->_openTags,$tagName);
+ $this->_openTags[] = $tagName;
}
$this->_writer->write($str);
$this->_attributes=array();
diff --git a/framework/Web/UI/TTemplateManager.php b/framework/Web/UI/TTemplateManager.php index f44d414c..6d44d7d7 100644 --- a/framework/Web/UI/TTemplateManager.php +++ b/framework/Web/UI/TTemplateManager.php @@ -608,7 +608,7 @@ class TTemplate extends TApplicationComponent implements ITemplate $tpl[$c++]=array($container,$type,$attributes);
if($str[strlen($str)-2]!=='/') // open tag
{
- array_push($stack,$type);
+ $stack[] = $type;
$container=$c-1;
}
}
@@ -695,7 +695,7 @@ class TTemplate extends TApplicationComponent implements ITemplate else // regular property
{
$prop=strtolower($match[3][0]);
- array_push($stack,'@'.$prop);
+ $stack[] = '@'.$prop;
if(!$expectPropEnd)
{
if($matchStart>$textStart)
diff --git a/framework/Web/UI/WebControls/TBaseValidator.php b/framework/Web/UI/WebControls/TBaseValidator.php index b418885c..6daae4d0 100644 --- a/framework/Web/UI/WebControls/TBaseValidator.php +++ b/framework/Web/UI/WebControls/TBaseValidator.php @@ -1,733 +1,733 @@ -<?php -/** - * TBaseValidator class file - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @link http://www.pradosoft.com/ - * @copyright Copyright © 2005-2008 PradoSoft - * @license http://www.pradosoft.com/license/ - * @version $Id$ - * @package System.Web.UI.WebControls - */ - -/** - * Using TLabel class - */ -Prado::using('System.Web.UI.WebControls.TLabel'); - -/** - * TBaseValidator class - * - * TBaseValidator serves as the base class for validator controls. - * - * Validation is performed when a postback control, such as a TButton, a TLinkButton - * or a TTextBox (under AutoPostBack mode) is submitting the page and - * its <b>CausesValidation</b> property is true. - * You can also manually perform validation by calling {@link TPage::validate()}. - * The input control to be validated is specified by {@link setControlToValidate ControlToValidate}. - * - * Validator controls always validate the associated input control on the serve side. - * In addition, if {@link getEnableClientScript EnableClientScript} is true, - * validation will also be performed on the client-side using javascript. - * Client-side validation will validate user input before it is sent to the server. - * The form data will not be submitted if any error is detected. This avoids - * the round-trip of information necessary for server-side validation. - * - * You can use multiple validator controls to validate a single input control, - * each responsible for validating against a different criteria. - * For example, on a user registration form, you may want to make sure the user - * enters a value in the username text box, and the input must consist of only word - * characters. You can use a {@link TRequiredFieldValidator} to ensure the input - * of username and a {@link TRegularExpressionValidator} to ensure the proper input. - * - * If an input control fails validation, the text specified by the {@link setErrorMessage ErrorMessage} - * property is displayed in the validation control. However, if the {@link setText Text} - * property is set, it will be displayed instead. If both {@link setErrorMessage ErrorMessage} - * and {@link setText Text} are empty, the body content of the validator will - * be displayed. Error display is controlled by {@link setDisplay Display} property. - * - * You can also customized the client-side behaviour by adding javascript - * code to the subproperties of the {@link getClientSide ClientSide} - * property. See quickstart documentation for further details. - * - * You can also place a {@link TValidationSummary} control on a page to display error messages - * from the validators together. In this case, only the {@link setErrorMessage ErrorMessage} - * property of the validators will be displayed in the {@link TValidationSummary} control. - * - * Validators can be partitioned into validation groups by setting their - * {@link setValidationGroup ValidationGroup} property. If the control causing the - * validation also sets its ValidationGroup property, only those validators having - * the same ValidationGroup value will do input validation. - * - * Note, the {@link TPage::getIsValid IsValid} property of the current {@link TPage} - * instance will be automatically updated by the validation process which occurs - * after {@link TPage::onLoad onLoad} of {@link TPage} and before the postback events. - * Therefore, if you use the {@link TPage::getIsValid()} property in - * the {@link TPage::onLoad()} method, you must first explicitly call - * the {@link TPage::validate()} method. - * - * <b>Notes to Inheritors</b> When you inherit from TBaseValidator, you must - * override the method {@link evaluateIsValid}. - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id$ - * @package System.Web.UI.WebControls - * @since 3.0 - */ -abstract class TBaseValidator extends TLabel implements IValidator -{ - /** - * @var boolean whether the validation succeeds - */ - private $_isValid=true; - /** - * @var boolean whether the validator has been registered with the page - */ - private $_registered=false; - /** - * @var TValidatorClientSide validator client-script options. - */ - private $_clientSide; - /** - * Controls for which the client-side validation3.js file needs to handle - * them specially. - * @var array list of control class names - */ - private static $_clientClass = array('THtmlArea', 'TDatePicker', 'TListBox', 'TCheckBoxList'); - - /** - * Constructor. - * This method sets the foreground color to red. - */ - public function __construct() - { - parent::__construct(); - $this->setForeColor('red'); - } - - /** - * Registers the validator with page. - * @param mixed event parameter - */ - public function onInit($param) - { - parent::onInit($param); - $this->getPage()->getValidators()->add($this); - $this->_registered=true; - } - - /** - * Unregisters the validator from page. - * @param mixed event parameter - */ - public function onUnload($param) - { - if($this->_registered && ($page=$this->getPage())!==null) - $page->getValidators()->remove($this); - $this->_registered=false; - parent::onUnload($param); - } - - /** - * Adds attributes to renderer. Calls parent implementation and renders the - * client control scripts. - * @param THtmlWriter the renderer - */ - protected function addAttributesToRender($writer) - { - $display=$this->getDisplay(); - $visible=$this->getEnabled(true) && !$this->getIsValid(); - if($display===TValidatorDisplayStyle::None || (!$visible && $display===TValidatorDisplayStyle::Dynamic)) - $writer->addStyleAttribute('display','none'); - else if(!$visible) - $writer->addStyleAttribute('visibility','hidden'); - $writer->addAttribute('id',$this->getClientID()); - parent::addAttributesToRender($writer); - $this->renderClientControlScript($writer); - } - - /** - * Returns an array of javascript validator options. - * @return array javascript validator options. - */ - protected function getClientScriptOptions() - { - $control = $this->getValidationTarget(); - $options['ID'] = $this->getClientID(); - $options['FormID'] = $this->getPage()->getForm()->getClientID(); - $options['Display'] = $this->getDisplay(); - $options['ErrorMessage'] = $this->getErrorMessage(); - if($this->getFocusOnError()) - { - $options['FocusOnError'] = $this->getFocusOnError(); - $options['FocusElementID'] = $this->getFocusElementID(); - } - $options['ValidationGroup'] = $this->getValidationGroup(); - $options['ControlToValidate'] = $control->getClientID(); - $options['ControlCssClass'] = $this->getControlCssClass(); - - $options['ControlType'] = $this->getClientControlClass($control); - - //get date format from date picker target control - if($control instanceof TDatePicker) - $options['DateFormat'] = $control->getDateFormat(); - - $options = array_merge($options,$this->getClientSide()->getOptions()->toArray()); - - return $options; - } - - /** - * Gets the Control type for client-side validation. If new cases exists in - * TBaseValidator::$_clientClass, be sure to update the corresponding - * "Javascript/validation3.js" file as well. - * @param TControl control to validate. - * @return string control type for client-side validation. - */ - private function getClientControlClass($control) - { - foreach(self::$_clientClass as $type) - if($control instanceof $type) - return $type; - return get_class($control); - } - - /** - * Gets the TValidatorClientSide that allows modification of the client- - * side validator events. - * - * The client-side validator supports the following events. - * # <tt>OnValidate</tt> -- raised before client-side validation is - * executed. - * # <tt>OnValidationSuccess</tt> -- raised after client-side validation is completed - * and is successfull, overrides default validator error messages updates. - * # <tt>OnValidationError</tt> -- raised after client-side validation is completed - * and failed, overrides default validator error message updates. - * - * You can attach custom javascript code to each of these events - * - * @return TValidatorClientSide javascript validator event options. - */ - public function getClientSide() - { - if(is_null($this->_clientSide)) - $this->_clientSide = $this->createClientSide(); - return $this->_clientSide; - } - - /** - * @return TValidatorClientSide javascript validator event options. - */ - protected function createClientSide() - { - return new TValidatorClientSide; - } - - /** - * Renders the javascript code to the end script. - * If you override this method, be sure to call the parent implementation - * so that the event handlers can be invoked. - * @param THtmlWriter the renderer - */ - public function renderClientControlScript($writer) - { - $scripts = $this->getPage()->getClientScript(); - $formID=$this->getPage()->getForm()->getClientID(); - $scriptKey = "TBaseValidator:$formID"; - if($this->getEnableClientScript() && !$scripts->isEndScriptRegistered($scriptKey)) - { - $manager['FormID'] = $formID; - $options = TJavaScript::encode($manager); - $scripts->registerPradoScript('validator'); - $scripts->registerEndScript($scriptKey, "new Prado.ValidationManager({$options});"); - } - if($this->getEnableClientScript() & $this->getEnabled(true)) - $this->registerClientScriptValidator(); - } - - /** - * Override parent implementation to update the control CSS Class before - * the validated control is rendered - */ - public function onPreRender ($param) - { - parent::onPreRender($param); - $this->updateControlCssClass(); - } - - /** - * Update the ControlToValidate component's css class depending - * if the ControlCssClass property is set, and whether this is valid. - * @return boolean true if change, false otherwise. - */ - protected function updateControlCssClass() - { - if(($cssClass=$this->getControlCssClass())!=='') - { - $control=$this->getValidationTarget(); - if($control instanceof TWebControl) - { - $class = preg_replace ('/ '.preg_quote($cssClass).'/', '',$control->getCssClass()); - if(!$this->getIsValid()) - { - $class .= ' '.$cssClass; - $control->setCssClass($class); - } elseif ($control->getIsValid()) - $control->setCssClass($class); - } - } - } - - /** - * Registers the individual validator client-side javascript code. - */ - protected function registerClientScriptValidator() - { - $key = 'prado:'.$this->getClientID(); - if(!$this->getPage()->getClientScript()->isEndScriptRegistered($key)) - { - $options = TJavaScript::encode($this->getClientScriptOptions()); - $script = 'new '.$this->getClientClassName().'('.$options.');'; - $this->getPage()->getClientScript()->registerEndScript($key, $script); - } - } - - /** - * Gets the name of the javascript class responsible for performing validation for this control. - * This method overrides the parent implementation. - * @return string the javascript class name - */ - abstract protected function getClientClassName(); - - /** - * This method overrides the parent implementation to forbid setting ForControl. - * @param string the associated control ID - * @throws TNotSupportedException whenever this method is called - */ - public function setForControl($value) - { - throw new TNotSupportedException('basevalidator_forcontrol_unsupported',get_class($this)); - } - - /** - * This method overrides parent's implementation by setting {@link setIsValid IsValid} to true if disabled. - * @param boolean whether the validator is enabled. - */ - public function setEnabled($value) - { - $value=TPropertyValue::ensureBoolean($value); - parent::setEnabled($value); - if(!$value) - $this->_isValid=true; - } - - /** - * @return TValidatorDisplayStyle the style of displaying the error message. Defaults to TValidatorDisplayStyle::Fixed. - */ - public function getDisplay() - { - return $this->getViewState('Display',TValidatorDisplayStyle::Fixed); - } - - /** - * @param TValidatorDisplayStyle the style of displaying the error message - */ - public function setDisplay($value) - { - $this->setViewState('Display',TPropertyValue::ensureEnum($value,'TValidatorDisplayStyle'),TValidatorDisplayStyle::Fixed); - } - - /** - * @return boolean whether client-side validation is enabled. - */ - public function getEnableClientScript() - { - return $this->getViewState('EnableClientScript',true); - } - - /** - * @param boolean whether client-side validation is enabled. - */ - public function setEnableClientScript($value) - { - $this->setViewState('EnableClientScript',TPropertyValue::ensureBoolean($value),true); - } - - /** - * @return string the text for the error message. - */ - public function getErrorMessage() - { - return $this->getViewState('ErrorMessage',''); - } - - /** - * Sets the text for the error message. - * @param string the error message - */ - public function setErrorMessage($value) - { - $this->setViewState('ErrorMessage',$value,''); - } - - /** - * @return string the ID path of the input control to validate - */ - public function getControlToValidate() - { - return $this->getViewState('ControlToValidate',''); - } - - /** - * Sets the ID path of the input control to validate. - * The ID path is the dot-connected IDs of the controls reaching from - * the validator's naming container to the target control. - * @param string the ID path - */ - public function setControlToValidate($value) - { - $this->setViewState('ControlToValidate',$value,''); - } - - /** - * @return boolean whether to set focus at the validating place if the validation fails. Defaults to false. - */ - public function getFocusOnError() - { - return $this->getViewState('FocusOnError',false); - } - - /** - * @param boolean whether to set focus at the validating place if the validation fails - */ - public function setFocusOnError($value) - { - $this->setViewState('FocusOnError',TPropertyValue::ensureBoolean($value),false); - } - - /** - * Gets the ID of the HTML element that will receive focus if validation fails and {@link getFocusOnError FocusOnError} is true. - * Defaults to the client ID of the {@link getControlToValidate ControlToValidate}. - * @return string the ID of the HTML element to receive focus - */ - public function getFocusElementID() - { - if(($id=$this->getViewState('FocusElementID',''))==='') - $id=$this->getValidationTarget()->getClientID(); - return $id; - } - - /** - * Sets the ID of the HTML element that will receive focus if validation fails and {@link getFocusOnError FocusOnError} is true. - * @param string the ID of the HTML element to receive focus - */ - public function setFocusElementID($value) - { - $this->setViewState('FocusElementID', $value, ''); - } - - /** - * @return string the group which this validator belongs to - */ - public function getValidationGroup() - { - return $this->getViewState('ValidationGroup',''); - } - - /** - * @param string the group which this validator belongs to - */ - public function setValidationGroup($value) - { - $this->setViewState('ValidationGroup',$value,''); - } - - /** - * @return boolean whether the validation succeeds - */ - public function getIsValid() - { - return $this->_isValid; - } - - /** - * Sets the value indicating whether the validation succeeds - * @param boolean whether the validation succeeds - */ - public function setIsValid($value) - { - $this->_isValid=TPropertyValue::ensureBoolean($value); - } - - /** - * @return TControl control to be validated. Null if no control is found. - * @throws TConfigurationException if {@link getControlToValidate - * ControlToValidate} is empty or does not point to a valid control - */ - protected function getValidationTarget() - { - if(($id=$this->getControlToValidate())!=='' && ($control=$this->findControl($id))!==null) - return $control; - else - throw new TConfigurationException('basevalidator_controltovalidate_invalid',get_class($this)); - } - - /** - * Retrieves the property value of the control being validated. - * @param TControl control being validated - * @return string property value to be validated - * @throws TInvalidDataTypeException if the control to be validated does not implement {@link IValidatable}. - */ - protected function getValidationValue($control) - { - if($control instanceof IValidatable) - return $control->getValidationPropertyValue(); - else - throw new TInvalidDataTypeException('basevalidator_validatable_required',get_class($this)); - } - - /** - * Validates the specified control. - * Do not override this method. Override {@link evaluateIsValid} instead. - * @return boolean whether the validation succeeds - */ - public function validate() - { - $this->setIsValid(true); - $this->onValidate(); - if($this->getVisible(true) && $this->getEnabled(true)) - { - // if the target is not a disabled web control - if(($target=$this->getValidationTarget())!==null && !($target instanceof TWebControl && !$target->getEnabled(true))) - { - if($this->evaluateIsValid()) - { - $this->setIsValid(true); - $this->onValidationSuccess(); - } - else - { - $target->setIsValid(false); - $this->setIsValid(false); - $this->onValidationError(); - } - } - else - { - $this->evaluateIsValid(); - $this->setIsValid(true); - $this->onValidationSuccess(); - } - } - return $this->getIsValid(); - } - - /** - * @return string the css class that is applied to the control being validated in case the validation fails - */ - public function getControlCssClass() - { - return $this->getViewState('ControlCssClass',''); - } - - /** - * @param string the css class that is applied to the control being validated in case the validation fails - */ - public function setControlCssClass($value) - { - $this->setViewState('ControlCssClass',$value,''); - } - - /** - * This is the major method for validation. - * Derived classes should implement this method to provide customized validation. - * @return boolean whether the validation succeeds - */ - abstract protected function evaluateIsValid(); - - /** - * This event is raised when the validator succeeds in validation. - */ - public function onValidationSuccess() - { - $this->raiseEvent('OnValidationSuccess',$this,null); - } - - /** - * This event is raised when the validator fails in validation. - */ - public function onValidationError() - { - $this->raiseEvent('OnValidationError',$this,null); - } - - /** - * This event is raised right before the validator starts to perform validation. - * You may use this event to change the behavior of validation. - * For example, you may disable the validator if certain condition is satisfied. - * Note, the event will NOT be raised if the validator is invisible. - */ - public function onValidate() - { - $this->raiseEvent('OnValidate',$this,null); - } - - /** - * Renders the validator control. - * @param THtmlWriter writer for the rendering purpose - */ - public function renderContents($writer) - { - if(($text=$this->getText())!=='') - $writer->write($text); - else if(($text=$this->getErrorMessage())!=='') - $writer->write($text); - else - parent::renderContents($writer); - } -} - -/** - * TValidatorClientSide class. - * - * Client-side validator events can be modified through the {@link - * TBaseValidator::getClientSide ClientSide} property of a validator. The - * subproperties of ClientSide are those of the TValidatorClientSide - * properties. The client-side validator supports the following events. - * - * The <tt>OnValidate</tt> event is raise before the validator validation - * functions are called. - * - * The <tt>OnValidationSuccess</tt> event is raised after the validator has successfully - * validate the control. - * - * The <tt>OnValidationError</tt> event is raised after the validator fails validation. - * - * See the quickstart documentation for further details. - * - * @author Wei Zhuo <weizhuo[at]gmail[dot]com> - * @version $Id$ - * @package System.Web.UI.WebControls - * @since 3.0 - */ -class TValidatorClientSide extends TClientSideOptions -{ - /** - * @return string javascript code for client-side OnValidate event. - */ - public function getOnValidate() - { - return $this->getOption('OnValidate'); - } - - /** - * Client-side OnValidate validator event is raise before the validators - * validation functions are called. - * @param string javascript code for client-side OnValidate event. - */ - public function setOnValidate($javascript) - { - $this->setFunction('OnValidate', $javascript); - } - - /** - * Client-side OnSuccess event is raise after validation is successfull. - * This will override the default client-side validator behaviour. - * @param string javascript code for client-side OnSuccess event. - */ - public function setOnValidationSuccess($javascript) - { - $this->setFunction('OnValidationSuccess', $javascript); - } - - /** - * @return string javascript code for client-side OnSuccess event. - */ - public function getOnValidationSuccess() - { - return $this->getOption('OnValidationSuccess'); - } - - /** - * Client-side OnError event is raised after validation failure. - * This will override the default client-side validator behaviour. - * @param string javascript code for client-side OnError event. - */ - public function setOnValidationError($javascript) - { - $this->setFunction('OnValidationError', $javascript); - } - - /** - * @return string javascript code for client-side OnError event. - */ - public function getOnValidationError() - { - return $this->getOption('OnValidationError'); - } - - /** - * @param boolean true to revalidate when the control to validate changes value. - */ - public function setObserveChanges($value) - { - $this->setOption('ObserveChanges', TPropertyValue::ensureBoolean($value)); - } - - /** - * @return boolean true to observe changes. - */ - public function getObserveChanges() - { - $changes = $this->getOption('ObserveChanges'); - return is_null($changes) ? true : $changes; - } -} - - -/** - * TValidatorDisplayStyle class. - * TValidatorDisplayStyle defines the enumerable type for the possible styles - * that a validator control can display the error message. - * - * The following enumerable values are defined: - * - None: the error message is not displayed - * - Dynamic: the error message dynamically appears when the validator fails validation - * - Fixed: Similar to Dynamic except that the error message physically occupies the page layout (even though it may not be visible) - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id$ - * @package System.Web.UI.WebControls - * @since 3.0.4 - */ -class TValidatorDisplayStyle extends TEnumerable -{ - const None='None'; - const Dynamic='Dynamic'; - const Fixed='Fixed'; -} - -/** - * TValidationDataType class. - * TValidationDataType defines the enumerable type for the possible data types that - * a comparison validator can validate upon. - * - * The following enumerable values are defined: - * - Integer - * - Float - * - Date - * - String - * - * @author Qiang Xue <qiang.xue@gmail.com> - * @version $Id$ - * @package System.Web.UI.WebControls - * @since 3.0.4 - */ -class TValidationDataType extends TEnumerable -{ - const Integer='Integer'; - const Float='Float'; - const Date='Date'; - const String='String'; -} - +<?php
+/**
+ * TBaseValidator class file
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright © 2005-2008 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @package System.Web.UI.WebControls
+ */
+
+/**
+ * Using TLabel class
+ */
+Prado::using('System.Web.UI.WebControls.TLabel');
+
+/**
+ * TBaseValidator class
+ *
+ * TBaseValidator serves as the base class for validator controls.
+ *
+ * Validation is performed when a postback control, such as a TButton, a TLinkButton
+ * or a TTextBox (under AutoPostBack mode) is submitting the page and
+ * its <b>CausesValidation</b> property is true.
+ * You can also manually perform validation by calling {@link TPage::validate()}.
+ * The input control to be validated is specified by {@link setControlToValidate ControlToValidate}.
+ *
+ * Validator controls always validate the associated input control on the serve side.
+ * In addition, if {@link getEnableClientScript EnableClientScript} is true,
+ * validation will also be performed on the client-side using javascript.
+ * Client-side validation will validate user input before it is sent to the server.
+ * The form data will not be submitted if any error is detected. This avoids
+ * the round-trip of information necessary for server-side validation.
+ *
+ * You can use multiple validator controls to validate a single input control,
+ * each responsible for validating against a different criteria.
+ * For example, on a user registration form, you may want to make sure the user
+ * enters a value in the username text box, and the input must consist of only word
+ * characters. You can use a {@link TRequiredFieldValidator} to ensure the input
+ * of username and a {@link TRegularExpressionValidator} to ensure the proper input.
+ *
+ * If an input control fails validation, the text specified by the {@link setErrorMessage ErrorMessage}
+ * property is displayed in the validation control. However, if the {@link setText Text}
+ * property is set, it will be displayed instead. If both {@link setErrorMessage ErrorMessage}
+ * and {@link setText Text} are empty, the body content of the validator will
+ * be displayed. Error display is controlled by {@link setDisplay Display} property.
+ *
+ * You can also customized the client-side behaviour by adding javascript
+ * code to the subproperties of the {@link getClientSide ClientSide}
+ * property. See quickstart documentation for further details.
+ *
+ * You can also place a {@link TValidationSummary} control on a page to display error messages
+ * from the validators together. In this case, only the {@link setErrorMessage ErrorMessage}
+ * property of the validators will be displayed in the {@link TValidationSummary} control.
+ *
+ * Validators can be partitioned into validation groups by setting their
+ * {@link setValidationGroup ValidationGroup} property. If the control causing the
+ * validation also sets its ValidationGroup property, only those validators having
+ * the same ValidationGroup value will do input validation.
+ *
+ * Note, the {@link TPage::getIsValid IsValid} property of the current {@link TPage}
+ * instance will be automatically updated by the validation process which occurs
+ * after {@link TPage::onLoad onLoad} of {@link TPage} and before the postback events.
+ * Therefore, if you use the {@link TPage::getIsValid()} property in
+ * the {@link TPage::onLoad()} method, you must first explicitly call
+ * the {@link TPage::validate()} method.
+ *
+ * <b>Notes to Inheritors</b> When you inherit from TBaseValidator, you must
+ * override the method {@link evaluateIsValid}.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Id$
+ * @package System.Web.UI.WebControls
+ * @since 3.0
+ */
+abstract class TBaseValidator extends TLabel implements IValidator
+{
+ /**
+ * @var boolean whether the validation succeeds
+ */
+ private $_isValid=true;
+ /**
+ * @var boolean whether the validator has been registered with the page
+ */
+ private $_registered=false;
+ /**
+ * @var TValidatorClientSide validator client-script options.
+ */
+ private $_clientSide;
+ /**
+ * Controls for which the client-side validation3.js file needs to handle
+ * them specially.
+ * @var array list of control class names
+ */
+ private static $_clientClass = array('THtmlArea', 'TDatePicker', 'TListBox', 'TCheckBoxList');
+
+ /**
+ * Constructor.
+ * This method sets the foreground color to red.
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ $this->setForeColor('red');
+ }
+
+ /**
+ * Registers the validator with page.
+ * @param mixed event parameter
+ */
+ public function onInit($param)
+ {
+ parent::onInit($param);
+ $this->getPage()->getValidators()->add($this);
+ $this->_registered=true;
+ }
+
+ /**
+ * Unregisters the validator from page.
+ * @param mixed event parameter
+ */
+ public function onUnload($param)
+ {
+ if($this->_registered && ($page=$this->getPage())!==null)
+ $page->getValidators()->remove($this);
+ $this->_registered=false;
+ parent::onUnload($param);
+ }
+
+ /**
+ * Adds attributes to renderer. Calls parent implementation and renders the
+ * client control scripts.
+ * @param THtmlWriter the renderer
+ */
+ protected function addAttributesToRender($writer)
+ {
+ $display=$this->getDisplay();
+ $visible=$this->getEnabled(true) && !$this->getIsValid();
+ if($display===TValidatorDisplayStyle::None || (!$visible && $display===TValidatorDisplayStyle::Dynamic))
+ $writer->addStyleAttribute('display','none');
+ else if(!$visible)
+ $writer->addStyleAttribute('visibility','hidden');
+ $writer->addAttribute('id',$this->getClientID());
+ parent::addAttributesToRender($writer);
+ $this->renderClientControlScript($writer);
+ }
+
+ /**
+ * Returns an array of javascript validator options.
+ * @return array javascript validator options.
+ */
+ protected function getClientScriptOptions()
+ {
+ $control = $this->getValidationTarget();
+ $options['ID'] = $this->getClientID();
+ $options['FormID'] = $this->getPage()->getForm()->getClientID();
+ $options['Display'] = $this->getDisplay();
+ $options['ErrorMessage'] = $this->getErrorMessage();
+ if($this->getFocusOnError())
+ {
+ $options['FocusOnError'] = $this->getFocusOnError();
+ $options['FocusElementID'] = $this->getFocusElementID();
+ }
+ $options['ValidationGroup'] = $this->getValidationGroup();
+ $options['ControlToValidate'] = $control->getClientID();
+ $options['ControlCssClass'] = $this->getControlCssClass();
+
+ $options['ControlType'] = $this->getClientControlClass($control);
+
+ //get date format from date picker target control
+ if($control instanceof TDatePicker)
+ $options['DateFormat'] = $control->getDateFormat();
+
+ $options = array_merge($options,$this->getClientSide()->getOptions()->toArray());
+
+ return $options;
+ }
+
+ /**
+ * Gets the Control type for client-side validation. If new cases exists in
+ * TBaseValidator::$_clientClass, be sure to update the corresponding
+ * "Javascript/validation3.js" file as well.
+ * @param TControl control to validate.
+ * @return string control type for client-side validation.
+ */
+ private function getClientControlClass($control)
+ {
+ foreach(self::$_clientClass as $type)
+ if($control instanceof $type)
+ return $type;
+ return get_class($control);
+ }
+
+ /**
+ * Gets the TValidatorClientSide that allows modification of the client-
+ * side validator events.
+ *
+ * The client-side validator supports the following events.
+ * # <tt>OnValidate</tt> -- raised before client-side validation is
+ * executed.
+ * # <tt>OnValidationSuccess</tt> -- raised after client-side validation is completed
+ * and is successfull, overrides default validator error messages updates.
+ * # <tt>OnValidationError</tt> -- raised after client-side validation is completed
+ * and failed, overrides default validator error message updates.
+ *
+ * You can attach custom javascript code to each of these events
+ *
+ * @return TValidatorClientSide javascript validator event options.
+ */
+ public function getClientSide()
+ {
+ if($this->_clientSide===null)
+ $this->_clientSide = $this->createClientSide();
+ return $this->_clientSide;
+ }
+
+ /**
+ * @return TValidatorClientSide javascript validator event options.
+ */
+ protected function createClientSide()
+ {
+ return new TValidatorClientSide;
+ }
+
+ /**
+ * Renders the javascript code to the end script.
+ * If you override this method, be sure to call the parent implementation
+ * so that the event handlers can be invoked.
+ * @param THtmlWriter the renderer
+ */
+ public function renderClientControlScript($writer)
+ {
+ $scripts = $this->getPage()->getClientScript();
+ $formID=$this->getPage()->getForm()->getClientID();
+ $scriptKey = "TBaseValidator:$formID";
+ if($this->getEnableClientScript() && !$scripts->isEndScriptRegistered($scriptKey))
+ {
+ $manager['FormID'] = $formID;
+ $options = TJavaScript::encode($manager);
+ $scripts->registerPradoScript('validator');
+ $scripts->registerEndScript($scriptKey, "new Prado.ValidationManager({$options});");
+ }
+ if($this->getEnableClientScript() & $this->getEnabled(true))
+ $this->registerClientScriptValidator();
+ }
+
+ /**
+ * Override parent implementation to update the control CSS Class before
+ * the validated control is rendered
+ */
+ public function onPreRender ($param)
+ {
+ parent::onPreRender($param);
+ $this->updateControlCssClass();
+ }
+
+ /**
+ * Update the ControlToValidate component's css class depending
+ * if the ControlCssClass property is set, and whether this is valid.
+ * @return boolean true if change, false otherwise.
+ */
+ protected function updateControlCssClass()
+ {
+ if(($cssClass=$this->getControlCssClass())!=='')
+ {
+ $control=$this->getValidationTarget();
+ if($control instanceof TWebControl)
+ {
+ $class = preg_replace ('/ '.preg_quote($cssClass).'/', '',$control->getCssClass());
+ if(!$this->getIsValid())
+ {
+ $class .= ' '.$cssClass;
+ $control->setCssClass($class);
+ } elseif ($control->getIsValid())
+ $control->setCssClass($class);
+ }
+ }
+ }
+
+ /**
+ * Registers the individual validator client-side javascript code.
+ */
+ protected function registerClientScriptValidator()
+ {
+ $key = 'prado:'.$this->getClientID();
+ if(!$this->getPage()->getClientScript()->isEndScriptRegistered($key))
+ {
+ $options = TJavaScript::encode($this->getClientScriptOptions());
+ $script = 'new '.$this->getClientClassName().'('.$options.');';
+ $this->getPage()->getClientScript()->registerEndScript($key, $script);
+ }
+ }
+
+ /**
+ * Gets the name of the javascript class responsible for performing validation for this control.
+ * This method overrides the parent implementation.
+ * @return string the javascript class name
+ */
+ abstract protected function getClientClassName();
+
+ /**
+ * This method overrides the parent implementation to forbid setting ForControl.
+ * @param string the associated control ID
+ * @throws TNotSupportedException whenever this method is called
+ */
+ public function setForControl($value)
+ {
+ throw new TNotSupportedException('basevalidator_forcontrol_unsupported',get_class($this));
+ }
+
+ /**
+ * This method overrides parent's implementation by setting {@link setIsValid IsValid} to true if disabled.
+ * @param boolean whether the validator is enabled.
+ */
+ public function setEnabled($value)
+ {
+ $value=TPropertyValue::ensureBoolean($value);
+ parent::setEnabled($value);
+ if(!$value)
+ $this->_isValid=true;
+ }
+
+ /**
+ * @return TValidatorDisplayStyle the style of displaying the error message. Defaults to TValidatorDisplayStyle::Fixed.
+ */
+ public function getDisplay()
+ {
+ return $this->getViewState('Display',TValidatorDisplayStyle::Fixed);
+ }
+
+ /**
+ * @param TValidatorDisplayStyle the style of displaying the error message
+ */
+ public function setDisplay($value)
+ {
+ $this->setViewState('Display',TPropertyValue::ensureEnum($value,'TValidatorDisplayStyle'),TValidatorDisplayStyle::Fixed);
+ }
+
+ /**
+ * @return boolean whether client-side validation is enabled.
+ */
+ public function getEnableClientScript()
+ {
+ return $this->getViewState('EnableClientScript',true);
+ }
+
+ /**
+ * @param boolean whether client-side validation is enabled.
+ */
+ public function setEnableClientScript($value)
+ {
+ $this->setViewState('EnableClientScript',TPropertyValue::ensureBoolean($value),true);
+ }
+
+ /**
+ * @return string the text for the error message.
+ */
+ public function getErrorMessage()
+ {
+ return $this->getViewState('ErrorMessage','');
+ }
+
+ /**
+ * Sets the text for the error message.
+ * @param string the error message
+ */
+ public function setErrorMessage($value)
+ {
+ $this->setViewState('ErrorMessage',$value,'');
+ }
+
+ /**
+ * @return string the ID path of the input control to validate
+ */
+ public function getControlToValidate()
+ {
+ return $this->getViewState('ControlToValidate','');
+ }
+
+ /**
+ * Sets the ID path of the input control to validate.
+ * The ID path is the dot-connected IDs of the controls reaching from
+ * the validator's naming container to the target control.
+ * @param string the ID path
+ */
+ public function setControlToValidate($value)
+ {
+ $this->setViewState('ControlToValidate',$value,'');
+ }
+
+ /**
+ * @return boolean whether to set focus at the validating place if the validation fails. Defaults to false.
+ */
+ public function getFocusOnError()
+ {
+ return $this->getViewState('FocusOnError',false);
+ }
+
+ /**
+ * @param boolean whether to set focus at the validating place if the validation fails
+ */
+ public function setFocusOnError($value)
+ {
+ $this->setViewState('FocusOnError',TPropertyValue::ensureBoolean($value),false);
+ }
+
+ /**
+ * Gets the ID of the HTML element that will receive focus if validation fails and {@link getFocusOnError FocusOnError} is true.
+ * Defaults to the client ID of the {@link getControlToValidate ControlToValidate}.
+ * @return string the ID of the HTML element to receive focus
+ */
+ public function getFocusElementID()
+ {
+ if(($id=$this->getViewState('FocusElementID',''))==='')
+ $id=$this->getValidationTarget()->getClientID();
+ return $id;
+ }
+
+ /**
+ * Sets the ID of the HTML element that will receive focus if validation fails and {@link getFocusOnError FocusOnError} is true.
+ * @param string the ID of the HTML element to receive focus
+ */
+ public function setFocusElementID($value)
+ {
+ $this->setViewState('FocusElementID', $value, '');
+ }
+
+ /**
+ * @return string the group which this validator belongs to
+ */
+ public function getValidationGroup()
+ {
+ return $this->getViewState('ValidationGroup','');
+ }
+
+ /**
+ * @param string the group which this validator belongs to
+ */
+ public function setValidationGroup($value)
+ {
+ $this->setViewState('ValidationGroup',$value,'');
+ }
+
+ /**
+ * @return boolean whether the validation succeeds
+ */
+ public function getIsValid()
+ {
+ return $this->_isValid;
+ }
+
+ /**
+ * Sets the value indicating whether the validation succeeds
+ * @param boolean whether the validation succeeds
+ */
+ public function setIsValid($value)
+ {
+ $this->_isValid=TPropertyValue::ensureBoolean($value);
+ }
+
+ /**
+ * @return TControl control to be validated. Null if no control is found.
+ * @throws TConfigurationException if {@link getControlToValidate
+ * ControlToValidate} is empty or does not point to a valid control
+ */
+ public function getValidationTarget()
+ {
+ if(($id=$this->getControlToValidate())!=='' && ($control=$this->findControl($id))!==null)
+ return $control;
+ else
+ throw new TConfigurationException('basevalidator_controltovalidate_invalid',get_class($this));
+ }
+
+ /**
+ * Retrieves the property value of the control being validated.
+ * @param TControl control being validated
+ * @return string property value to be validated
+ * @throws TInvalidDataTypeException if the control to be validated does not implement {@link IValidatable}.
+ */
+ protected function getValidationValue($control)
+ {
+ if($control instanceof IValidatable)
+ return $control->getValidationPropertyValue();
+ else
+ throw new TInvalidDataTypeException('basevalidator_validatable_required',get_class($this));
+ }
+
+ /**
+ * Validates the specified control.
+ * Do not override this method. Override {@link evaluateIsValid} instead.
+ * @return boolean whether the validation succeeds
+ */
+ public function validate()
+ {
+ $this->setIsValid(true);
+ $this->onValidate();
+ if($this->getVisible(true) && $this->getEnabled(true))
+ {
+ // if the target is not a disabled web control
+ if(($target=$this->getValidationTarget())!==null && !($target instanceof TWebControl && !$target->getEnabled(true)))
+ {
+ if($this->evaluateIsValid())
+ {
+ $this->setIsValid(true);
+ $this->onValidationSuccess();
+ }
+ else
+ {
+ $target->setIsValid(false);
+ $this->setIsValid(false);
+ $this->onValidationError();
+ }
+ }
+ else
+ {
+ $this->evaluateIsValid();
+ $this->setIsValid(true);
+ $this->onValidationSuccess();
+ }
+ }
+ return $this->getIsValid();
+ }
+
+ /**
+ * @return string the css class that is applied to the control being validated in case the validation fails
+ */
+ public function getControlCssClass()
+ {
+ return $this->getViewState('ControlCssClass','');
+ }
+
+ /**
+ * @param string the css class that is applied to the control being validated in case the validation fails
+ */
+ public function setControlCssClass($value)
+ {
+ $this->setViewState('ControlCssClass',$value,'');
+ }
+
+ /**
+ * This is the major method for validation.
+ * Derived classes should implement this method to provide customized validation.
+ * @return boolean whether the validation succeeds
+ */
+ abstract protected function evaluateIsValid();
+
+ /**
+ * This event is raised when the validator succeeds in validation.
+ */
+ public function onValidationSuccess()
+ {
+ $this->raiseEvent('OnValidationSuccess',$this,null);
+ }
+
+ /**
+ * This event is raised when the validator fails in validation.
+ */
+ public function onValidationError()
+ {
+ $this->raiseEvent('OnValidationError',$this,null);
+ }
+
+ /**
+ * This event is raised right before the validator starts to perform validation.
+ * You may use this event to change the behavior of validation.
+ * For example, you may disable the validator if certain condition is satisfied.
+ * Note, the event will NOT be raised if the validator is invisible.
+ */
+ public function onValidate()
+ {
+ $this->raiseEvent('OnValidate',$this,null);
+ }
+
+ /**
+ * Renders the validator control.
+ * @param THtmlWriter writer for the rendering purpose
+ */
+ public function renderContents($writer)
+ {
+ if(($text=$this->getText())!=='')
+ $writer->write($text);
+ else if(($text=$this->getErrorMessage())!=='')
+ $writer->write($text);
+ else
+ parent::renderContents($writer);
+ }
+}
+
+/**
+ * TValidatorClientSide class.
+ *
+ * Client-side validator events can be modified through the {@link
+ * TBaseValidator::getClientSide ClientSide} property of a validator. The
+ * subproperties of ClientSide are those of the TValidatorClientSide
+ * properties. The client-side validator supports the following events.
+ *
+ * The <tt>OnValidate</tt> event is raise before the validator validation
+ * functions are called.
+ *
+ * The <tt>OnValidationSuccess</tt> event is raised after the validator has successfully
+ * validate the control.
+ *
+ * The <tt>OnValidationError</tt> event is raised after the validator fails validation.
+ *
+ * See the quickstart documentation for further details.
+ *
+ * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
+ * @version $Id$
+ * @package System.Web.UI.WebControls
+ * @since 3.0
+ */
+class TValidatorClientSide extends TClientSideOptions
+{
+ /**
+ * @return string javascript code for client-side OnValidate event.
+ */
+ public function getOnValidate()
+ {
+ return $this->getOption('OnValidate');
+ }
+
+ /**
+ * Client-side OnValidate validator event is raise before the validators
+ * validation functions are called.
+ * @param string javascript code for client-side OnValidate event.
+ */
+ public function setOnValidate($javascript)
+ {
+ $this->setFunction('OnValidate', $javascript);
+ }
+
+ /**
+ * Client-side OnSuccess event is raise after validation is successfull.
+ * This will override the default client-side validator behaviour.
+ * @param string javascript code for client-side OnSuccess event.
+ */
+ public function setOnValidationSuccess($javascript)
+ {
+ $this->setFunction('OnValidationSuccess', $javascript);
+ }
+
+ /**
+ * @return string javascript code for client-side OnSuccess event.
+ */
+ public function getOnValidationSuccess()
+ {
+ return $this->getOption('OnValidationSuccess');
+ }
+
+ /**
+ * Client-side OnError event is raised after validation failure.
+ * This will override the default client-side validator behaviour.
+ * @param string javascript code for client-side OnError event.
+ */
+ public function setOnValidationError($javascript)
+ {
+ $this->setFunction('OnValidationError', $javascript);
+ }
+
+ /**
+ * @return string javascript code for client-side OnError event.
+ */
+ public function getOnValidationError()
+ {
+ return $this->getOption('OnValidationError');
+ }
+
+ /**
+ * @param boolean true to revalidate when the control to validate changes value.
+ */
+ public function setObserveChanges($value)
+ {
+ $this->setOption('ObserveChanges', TPropertyValue::ensureBoolean($value));
+ }
+
+ /**
+ * @return boolean true to observe changes.
+ */
+ public function getObserveChanges()
+ {
+ $changes = $this->getOption('ObserveChanges');
+ return ($changes===null) ? true : $changes;
+ }
+}
+
+
+/**
+ * TValidatorDisplayStyle class.
+ * TValidatorDisplayStyle defines the enumerable type for the possible styles
+ * that a validator control can display the error message.
+ *
+ * The following enumerable values are defined:
+ * - None: the error message is not displayed
+ * - Dynamic: the error message dynamically appears when the validator fails validation
+ * - Fixed: Similar to Dynamic except that the error message physically occupies the page layout (even though it may not be visible)
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Id$
+ * @package System.Web.UI.WebControls
+ * @since 3.0.4
+ */
+class TValidatorDisplayStyle extends TEnumerable
+{
+ const None='None';
+ const Dynamic='Dynamic';
+ const Fixed='Fixed';
+}
+
+/**
+ * TValidationDataType class.
+ * TValidationDataType defines the enumerable type for the possible data types that
+ * a comparison validator can validate upon.
+ *
+ * The following enumerable values are defined:
+ * - Integer
+ * - Float
+ * - Date
+ * - String
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Id$
+ * @package System.Web.UI.WebControls
+ * @since 3.0.4
+ */
+class TValidationDataType extends TEnumerable
+{
+ const Integer='Integer';
+ const Float='Float';
+ const Date='Date';
+ const String='String';
+}
+
diff --git a/framework/Web/UI/WebControls/TColorPicker.php b/framework/Web/UI/WebControls/TColorPicker.php index 67a4ccfe..0fc7eef4 100644 --- a/framework/Web/UI/WebControls/TColorPicker.php +++ b/framework/Web/UI/WebControls/TColorPicker.php @@ -112,7 +112,7 @@ class TColorPicker extends TTextBox */
public function getClientSide()
{
- if(is_null($this->_clientSide))
+ if($this->_clientSide===null)
$this->_clientSide = $this->createClientSide();
return $this->_clientSide;
}
diff --git a/framework/Web/UI/WebControls/TCustomValidator.php b/framework/Web/UI/WebControls/TCustomValidator.php index 0b82ac5c..7fed2b84 100644 --- a/framework/Web/UI/WebControls/TCustomValidator.php +++ b/framework/Web/UI/WebControls/TCustomValidator.php @@ -112,11 +112,11 @@ class TCustomValidator extends TBaseValidator else
return $param->getIsValid();
}
-
+
/**
* @return TControl control to be validated. Null if no control is found.
*/
- protected function getValidationTarget()
+ public function getValidationTarget()
{
if(($id=$this->getControlToValidate())!=='' && ($control=$this->findControl($id))!==null)
return $control;
diff --git a/framework/Web/UI/WebControls/TDatePicker.php b/framework/Web/UI/WebControls/TDatePicker.php index 770099eb..e678b046 100644 --- a/framework/Web/UI/WebControls/TDatePicker.php +++ b/framework/Web/UI/WebControls/TDatePicker.php @@ -366,7 +366,7 @@ class TDatePicker extends TTextBox */
public function getClientSide()
{
- if(is_null($this->_clientScript))
+ if($this->_clientScript===null)
$this->_clientScript = $this->createClientScript();
return $this->_clientScript;
}
@@ -529,7 +529,7 @@ class TDatePicker extends TTextBox $options['PositionMode'] = $this->getPositionMode();
$options = array_merge($options, $this->getCulturalOptions());
- if(!is_null($this->_clientScript))
+ if($this->_clientScript!==null)
$options = array_merge($options,
$this->_clientScript->getOptions()->toArray());
return $options;
@@ -610,7 +610,7 @@ class TDatePicker extends TTextBox {
$formatter = Prado::createComponent('System.Util.TSimpleDateFormatter',
$this->getDateFormat());
- return !is_null($formatter->getDayPattern());
+ return ($formatter->getDayPattern()!==null);
}
/**
diff --git a/framework/Web/UI/WebControls/THead.php b/framework/Web/UI/WebControls/THead.php index 62ee46d3..36b81648 100644 --- a/framework/Web/UI/WebControls/THead.php +++ b/framework/Web/UI/WebControls/THead.php @@ -29,13 +29,6 @@ * <com:TMetaTag Name="keywords" Content="Prado" />
* </com:THead>
* </code>
- *
- * A MetaTag for "generator" is added by default if you haven't specified your own generator meta tag. You can override
- * the property by adding the following code to your template:
- * <com:THead>
- * <com:TMetaTag Name="generator" Content="Custom name" />
- * </com:THead>
- * </code>
*
* Note, {@link TPage} has a property {@link TPage::getHead Head} that refers to
* the THead control currently on the page. A page can have at most once THead
@@ -162,24 +155,14 @@ class THead extends TControl if(($icon=$this->getShortcutIcon())!=='')
$writer->write('<link rel="shortcut icon" href="'.$icon."\" />\n");
- $generatorAdded = false;
if(($metaTags=$this->getMetaTags())!==null)
{
foreach($metaTags as $metaTag)
{
- if(strtolower($metaTag->getName()) == 'generator')
- $generatorAdded = true;
$metaTag->render($writer);
$writer->writeLine();
}
}
- if(!$generatorAdded)
- {
- $metaTag = new TMetaTag();
- $metaTag->setName('generator');
- $metaTag->setContent(Prado::metaGenerator());
- $metaTag->render($writer);
- }
$cs=$page->getClientScript();
$cs->renderStyleSheetFiles($writer);
$cs->renderStyleSheets($writer);
diff --git a/framework/Web/UI/WebControls/THtmlArea.php b/framework/Web/UI/WebControls/THtmlArea.php index 7fea5862..8d55c074 100644 --- a/framework/Web/UI/WebControls/THtmlArea.php +++ b/framework/Web/UI/WebControls/THtmlArea.php @@ -4,7 +4,7 @@ *
* @author Wei Zhuo <weizhuo[at]gmail[dot]com>
* @link http://www.pradosoft.com/
- * @copyright Copyright © 2005-2008 PradoSoft + * @copyright Copyright © 2005-2008 PradoSoft
* @license http://www.pradosoft.com/license/
* @version $Id$
* @package System.Web.UI
@@ -334,7 +334,7 @@ class THtmlArea extends TTextBox $options['languages'] = $this->getLanguageSuffix($this->getCulture());
$options['disk_cache'] = true;
$options['debug'] = false;
- $js = TJavaScript::encode($options);
+ $js = TJavaScript::encode($options,true,true);
$script = "if(typeof(tinyMCE_GZ)!='undefined'){ tinyMCE_GZ.init({$js}); }";
$scripts->registerBeginScript($key, $script);
}
@@ -353,7 +353,7 @@ class THtmlArea extends TTextBox protected function registerEditorClientScript($writer)
{
$scripts = $this->getPage()->getClientScript();
- $options = TJavaScript::encode($this->getEditorOptions());
+ $options = TJavaScript::encode($this->getEditorOptions(),true,true); // Force encoding of empty strings
$script = "if(typeof(tinyMCE)!='undefined'){ tinyMCE.init($options); }";
$scripts->registerEndScript('prado:THtmlArea'.$this->ClientID,$script);
}
@@ -436,7 +436,14 @@ class THtmlArea extends TTextBox $option = explode(":",$bits,2);
if(count($option) == 2)
- $options[trim($option[0])] = trim(preg_replace('/\'|"/','', $option[1]));
+ {
+ $value=trim(preg_replace('/\'|"/','', $option[1]));
+ if (($s=strtolower($value))==='false')
+ $value=false;
+ elseif ($s==='true')
+ $value=true;
+ $options[trim($option[0])] = $value;
+ }
}
return $options;
}
@@ -447,10 +454,10 @@ class THtmlArea extends TTextBox protected function getLanguageSuffix($culture)
{
$app = $this->getApplication()->getGlobalization();
- if(empty($culture) && !is_null($app))
+ if(empty($culture) && ($app!==null))
$culture = $app->getCulture();
$variants = array();
- if(!is_null($app))
+ if($app!==null)
$variants = $app->getCultureVariants($culture);
foreach($variants as $variant)
diff --git a/framework/Web/UI/WebControls/TListControl.php b/framework/Web/UI/WebControls/TListControl.php index 84c23f88..c69b387e 100644 --- a/framework/Web/UI/WebControls/TListControl.php +++ b/framework/Web/UI/WebControls/TListControl.php @@ -487,8 +487,6 @@ abstract class TListControl extends TDataBoundControl implements IDataRenderer $this->clearSelection();
if($index>=0 && $index<$this->_items->getCount())
$this->_items->itemAt($index)->setSelected(true);
- else if($index!==-1)
- throw new TInvalidDataValueException('listcontrol_selectedindex_invalid',get_class($this),$index);
}
$this->_cachedSelectedIndex=$index;
if($this->getAdapter() instanceof IListControlAdapter)
@@ -601,7 +599,7 @@ abstract class TListControl extends TDataBoundControl implements IDataRenderer $item->setSelected(true);
}
else
- throw new TInvalidDataValueException('listcontrol_selectedvalue_invalid',get_class($this),$value);
+ $this->clearSelection();
}
$this->_cachedSelectedValue=$value;
if($this->getAdapter() instanceof IListControlAdapter)
@@ -643,8 +641,6 @@ abstract class TListControl extends TDataBoundControl implements IDataRenderer {
if(isset($lookup["$value"]))
$lookup["$value"]->setSelected(true);
- else
- throw new TInvalidDataValueException('listcontrol_selectedvalue_invalid',get_class($this),$value);
}
}
$this->_cachedSelectedValues=$values;
@@ -917,7 +913,7 @@ class TListItemCollection extends TList protected function createNewListItem($text=null)
{
$item = new TListItem;
- if(!is_null($text))
+ if($text!==null)
$item->setText($text);
return $item;
}
diff --git a/framework/Web/UI/WebControls/TStyle.php b/framework/Web/UI/WebControls/TStyle.php index 7cb1d8c8..1b94cc8e 100644 --- a/framework/Web/UI/WebControls/TStyle.php +++ b/framework/Web/UI/WebControls/TStyle.php @@ -4,7 +4,7 @@ *
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.pradosoft.com/
- * @copyright Copyright © 2005-2008 PradoSoft + * @copyright Copyright © 2005-2008 PradoSoft
* @license http://www.pradosoft.com/license/
* @version $Id$
* @package System.Web.UI.WebControls
@@ -63,7 +63,7 @@ class TStyle extends TComponent */
public function __clone()
{
- if(!is_null($this->_font))
+ if($this->_font!==null)
$this->_font = clone($this->_font);
}
@@ -157,7 +157,7 @@ class TStyle extends TComponent */
public function hasCssClass()
{
- return !is_null($this->_class);
+ return ($this->_class!==null);
}
/**
diff --git a/framework/Web/UI/WebControls/TValidationSummary.php b/framework/Web/UI/WebControls/TValidationSummary.php index 95679e15..ab066f78 100644 --- a/framework/Web/UI/WebControls/TValidationSummary.php +++ b/framework/Web/UI/WebControls/TValidationSummary.php @@ -4,7 +4,7 @@ *
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.pradosoft.com/
- * @copyright Copyright © 2005-2008 PradoSoft + * @copyright Copyright © 2005-2008 PradoSoft
* @license http://www.pradosoft.com/license/
* @version $Id$
* @package System.Web.UI.WebControls
@@ -261,7 +261,7 @@ class TValidationSummary extends TWebControl $options['ValidationGroup'] = $this->getValidationGroup();
$options['Display'] = $this->getDisplay();
- if(!is_null($this->_clientSide))
+ if($this->_clientSide!==null)
$options = array_merge($options,$this->_clientSide->getOptions()->toArray());
return $options;
@@ -273,7 +273,7 @@ class TValidationSummary extends TWebControl */
public function getClientSide()
{
- if(is_null($this->_clientSide))
+ if($this->_clientSide===null)
$this->_clientSide = $this->createClientScript();
return $this->_clientSide;
}
@@ -324,6 +324,9 @@ class TValidationSummary extends TWebControl case TValidationSummaryDisplayMode::BulletList:
$this->renderBulletList($writer);
break;
+ case TValidationSummaryDisplayMode::HeaderOnly:
+ $this->renderHeaderOnly($writer);
+ break;
}
}
}
@@ -382,6 +385,15 @@ class TValidationSummary extends TWebControl }
$writer->write($content);
}
+
+ /**
+ * Render the validation summary header text only.
+ * @param THtmlWriter the writer used for the rendering purpose
+ */
+ protected function renderHeaderOnly($writer)
+ {
+ $writer->write($this->getHeaderText());
+ }
}
/**
@@ -468,6 +480,7 @@ class TClientSideValidationSummaryOptions extends TClientSideOptions * - SimpleList: the error messages are displayed as a list without any decorations.
* - SingleParagraph: the error messages are concatenated together into a paragraph.
* - BulletList: the error messages are displayed as a bulleted list.
+ * - HeaderOnly: only the HeaderText will be display.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @version $Id$
@@ -479,6 +492,7 @@ class TValidationSummaryDisplayMode extends TEnumerable const SimpleList='SimpleList';
const SingleParagraph='SingleParagraph';
const BulletList='BulletList';
+ const HeaderOnly='HeaderOnly';
}
|