From 35c7ff28cbc311fba5e394b11fb756a4dc1edcb9 Mon Sep 17 00:00:00 2001 From: wei <> Date: Tue, 13 Dec 2005 07:08:30 +0000 Subject: Removed inline javascript from components. Adding TJavascriptLogger and logger.js --- framework/Web/UI/TAssetManager.php | 25 ++++++++- framework/Web/UI/TClientScriptManager.php | 20 ++++++- framework/Web/UI/WebControls/TBaseValidator.php | 6 +- framework/Web/UI/WebControls/TButton.php | 62 +++++++++------------ framework/Web/UI/WebControls/TCheckBox.php | 45 ++++++++++----- framework/Web/UI/WebControls/TImageButton.php | 33 +---------- framework/Web/UI/WebControls/TJavascriptLogger.php | 65 ++++++++++++++++++++++ framework/Web/UI/WebControls/TLinkButton.php | 63 +++++++++++---------- framework/Web/UI/WebControls/TRadioButton.php | 15 ----- framework/Web/UI/WebControls/TTextBox.php | 56 +++++++++++++------ 10 files changed, 238 insertions(+), 152 deletions(-) create mode 100644 framework/Web/UI/WebControls/TJavascriptLogger.php (limited to 'framework/Web/UI') diff --git a/framework/Web/UI/TAssetManager.php b/framework/Web/UI/TAssetManager.php index df189b58..dfc1fa53 100644 --- a/framework/Web/UI/TAssetManager.php +++ b/framework/Web/UI/TAssetManager.php @@ -150,7 +150,7 @@ class TAssetManager extends TModule return ''; else if(is_file($fullpath)) { - $dir=md5(dirname($fullpath)); + $dir=$this->hash(dirname($fullpath)); $file=$this->_basePath.'/'.$dir.'/'.basename($fullpath); if(!is_file($file) || $checkTimestamp || $this->_application->getMode()!=='Performance') { @@ -164,7 +164,7 @@ class TAssetManager extends TModule } else { - $dir=md5($fullpath); + $dir=$this->hash($fullpath); if(!is_dir($this->_basePath.'/'.$dir) || $checkTimestamp || $this->_application->getMode()!=='Performance') $this->copyDirectory($fullpath,$this->_basePath.'/'.$dir); $this->_published[$path]=$this->_baseUrl.'/'.$dir; @@ -172,6 +172,27 @@ class TAssetManager extends TModule } } + /** + * Generate a CRC32 hash for the directory path. Collisions are higher + * than MD5 but generates a much smaller hash string. + * @param string string to be hashed. + * @return string hashed string. + */ + private function hash($dir) + { + $num = sprintf('%u', crc32($dir)); + $base = 62; + $index = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + $out = ''; + for ( $t = floor( log10( $num ) / log10( $base ) ); $t >= 0; $t-- ) + { + $a = floor( $num / pow( $base, $t ) ); + $out = $out . substr( $index, $a, 1 ); + $num = $num - ( $a * pow( $base, $t ) ); + } + return $out; + } + /** * Copies a directory recursively as another. * If the destination directory does not exist, it will be created. diff --git a/framework/Web/UI/TClientScriptManager.php b/framework/Web/UI/TClientScriptManager.php index ca28751f..6106cfbf 100644 --- a/framework/Web/UI/TClientScriptManager.php +++ b/framework/Web/UI/TClientScriptManager.php @@ -165,13 +165,17 @@ class TClientScriptManager extends TComponent public function registerPradoScript($script) { - foreach(TPradoClientScript::getScript($script) as $scriptFile) + foreach(TPradoClientScript::getScripts($script) as $scriptFile) { if(isset($this->_publishedScriptFiles[$scriptFile])) $url=$this->_publishedScriptFiles[$scriptFile]; else { - $url=$this->_page->getService()->getAssetManager()->publishFilePath(Prado::getFrameworkPath().'/'.self::SCRIPT_DIR.'/'.$scriptFile); + $base = Prado::getFrameworkPath(); + $clientScripts = self::SCRIPT_DIR; + $file = "{$base}/{$clientScripts}/{$scriptFile}.js"; + $assetManager = $this->_page->getService()->getAssetManager(); + $url= $assetManager->publishFilePath($file); $this->_publishedScriptFiles[$scriptFile]=$url; $this->registerScriptFile('prado:'.$scriptFile,$url); } @@ -444,6 +448,16 @@ class TClientScriptManager extends TComponent return count($this->_onSubmitStatements)>0; } + public function registerClientEvent($control, $event, $code) + { + if(empty($code)) return; + $this->registerPradoScript("dom"); + $script= "Event.observe('{$control->ClientID}', '{$event}', function(e){ {$code} });"; + $key = "prado:{$control->ClientID}:{$event}"; + $this->registerEndScript($key, $script); + } + + /* private void EnsureEventValidationFieldLoaded(); @@ -619,7 +633,7 @@ class TPradoClientScript * @param array list of libraries to load. * @return array list of libraries including its dependencies. */ - protected static function getScripts($scripts) + public static function getScripts($scripts) { $files = array(); if(!is_array($scripts)) $scripts = array($scripts); diff --git a/framework/Web/UI/WebControls/TBaseValidator.php b/framework/Web/UI/WebControls/TBaseValidator.php index ab314087..0d88fc43 100644 --- a/framework/Web/UI/WebControls/TBaseValidator.php +++ b/framework/Web/UI/WebControls/TBaseValidator.php @@ -111,7 +111,7 @@ abstract class TBaseValidator extends TLabel implements IValidator * Returns an array of javascript validator options. * @return array javascript validator options. */ - protected function getClientScriptAttributes() + protected function getClientScriptOptions() { $options['ID'] = $this->getClientID(); $options['Display'] = $this->getDisplay(); @@ -153,8 +153,8 @@ abstract class TBaseValidator extends TLabel implements IValidator $class = get_class($this); $scriptKey = "prado:".$this->getClientID(); $scripts = $this->getPage()->getClientScript(); - $option = TJavascript::toList($this->getClientScriptAttributes()); - $js = "new Prado.Validation(Prado.Validation.{$class}, {$option});"; + $options = TJavascript::toList($this->getClientScriptOptions()); + $js = "new Prado.Validation(Prado.Validation.{$class}, {$options});"; $scripts->registerEndScript($scriptKey, $js); } } diff --git a/framework/Web/UI/WebControls/TButton.php b/framework/Web/UI/WebControls/TButton.php index e7c40a75..c18bcc62 100644 --- a/framework/Web/UI/WebControls/TButton.php +++ b/framework/Web/UI/WebControls/TButton.php @@ -44,10 +44,6 @@ * You can change the postback target by setting the {@link setPostBackUrl PostBackUrl} * property. * - * To set the client-side javascript associated with the user's click action, - * use the {@link setOnClientClick OnClientClick} property. The value will be rendered - * as the onclick attribute of the button. - * * TButton displays the {@link setText Text} property as the button caption. * * @author Qiang Xue @@ -78,18 +74,27 @@ class TButton extends TWebControl implements IPostBackEventHandler if(($uniqueID=$this->getUniqueID())!=='') $writer->addAttribute('name',$uniqueID); $writer->addAttribute('value',$this->getText()); + if(!$this->getEnabled()) // in this case, parent will not render 'disabled' + $writer->addAttribute('disabled','disabled'); + parent::addAttributesToRender($writer); + } + /** + * Registers the postback javascript code. + * If you override this method, be sure to call the parent implementation + * so that the event handlers can be invoked. + * @param TEventParameter event parameter to be passed to the event handlers + */ + protected function onPreRender($param) + { if($this->getEnabled(true)) { - $onclick=$this->removeAttribute('onclick'); - $onclick=THttpUtility::trimJavaScriptString($onclick).THttpUtility::trimJavaScriptString($this->getOnClientClick()); - $onclick.=$page->getClientScript()->getPostBackEventReference($this,'',$this->getPostBackOptions(),false); - if(!empty($onclick)) - $writer->addAttribute('onclick','javascript:'.$onclick); + $scripts = $this->getPage()->getClientScript(); + $options = $this->getPostBackOptions(); + $postback = $scripts->getPostBackEventReference($this, '', $options, false); + $scripts->registerClientEvent($this, "click", $postback); } - else if($this->getEnabled()) // in this case, parent will not render 'disabled' - $writer->addAttribute('disabled','disabled'); - parent::addAttributesToRender($writer); + parent::onPreRender($param); } /** @@ -99,16 +104,19 @@ class TButton extends TWebControl implements IPostBackEventHandler */ protected function getPostBackOptions() { - $options=new TPostBackOptions(); - if($this->getCausesValidation() && $this->getPage()->getValidators($this->getValidationGroup())->getCount()>0) + $option=new TPostBackOptions(); + $group = $this->getValidationGroup(); + $hasValidators = $this->getPage()->getValidators($group)->getCount()>0; + if($this->getCausesValidation() && $hasValidators) { - $options->setPerformValidation(true); - $options->setValidationGroup($this->getValidationGroup()); + $option->setPerformValidation(true); + $option->setValidationGroup($group); } if($this->getPostBackUrl()!=='') - $options->setActionUrl($this->getPostBackUrl()); - $options->setClientSubmit(!$this->getUseSubmitBehavior()); - return $options; + $option->setActionUrl($this->getPostBackUrl()); + $option->setClientSubmit(!$this->getUseSubmitBehavior()); + + return $option; } /** @@ -275,22 +283,6 @@ class TButton extends TWebControl implements IPostBackEventHandler { $this->setViewState('PostBackUrl',$value,''); } - - /** - * @return string the javascript to be executed when the button is clicked. - */ - public function getOnClientClick() - { - return $this->getViewState('OnClientClick',''); - } - - /** - * @param string the javascript to be executed when the button is clicked. - */ - public function setOnClientClick($value) - { - $this->setViewState('OnClientClick',$value,''); - } } ?> \ No newline at end of file diff --git a/framework/Web/UI/WebControls/TCheckBox.php b/framework/Web/UI/WebControls/TCheckBox.php index caaafa78..ba3a45f7 100644 --- a/framework/Web/UI/WebControls/TCheckBox.php +++ b/framework/Web/UI/WebControls/TCheckBox.php @@ -108,6 +108,9 @@ class TCheckBox extends TWebControl implements IPostBackDataHandler, IValidatabl * Registers the checkbox to receive postback data during postback. * This is necessary because a checkbox if unchecked, when postback, * does not have direct mapping between post data and the checkbox name. + * + * Auto-postback javascript code is also registered here. + * * This method overrides the parent implementation and is invoked before render. * @param mixed event parameter */ @@ -116,6 +119,15 @@ class TCheckBox extends TWebControl implements IPostBackDataHandler, IValidatabl parent::onPreRender($param); if($this->getEnabled(true)) $this->getPage()->registerRequiresPostData($this); + + if($this->getAutoPostBack() + && $this->getPage()->getClientSupportsJavaScript()) + { + $options = $this->getAutoPostBackOptions(); + $scripts = $this->getPage()->getClientScript(); + $postback = $scripts->getPostBackEventReference($this,'',$options,false); + $scripts->registerClientEvent($this, "click", $postback); + } } /** @@ -353,21 +365,6 @@ class TCheckBox extends TWebControl implements IPostBackDataHandler, IValidatabl if(!$this->getEnabled(true)) $writer->addAttribute('disabled','disabled'); $page=$this->getPage(); - if($this->getAutoPostBack() && $page->getClientSupportsJavaScript()) - { - $option=new TPostBackOptions(); - if($this->getCausesValidation() && $page->getValidators($this->getValidationGroup())->getCount()) - { - $option->setPerformValidation(true); - $option->setValidationGroup($this->getValidationGroup()); - } - $option->setAutoPostBack(true); - if(!empty($onclick)) - $onclick=THttpUtility::trimJavaScriptString($onclick); - $onclick.=$page->getClientScript()->getPostBackEventReference($this,'',$option,false); - } - if(!empty($onclick)) - $writer->addAttribute('onclick',$onclick); if(($accesskey=$this->getAccessKey())!=='') $writer->addAttribute('accesskey',$accesskey); if(($tabindex=$this->getTabIndex())>0) @@ -377,6 +374,24 @@ class TCheckBox extends TWebControl implements IPostBackDataHandler, IValidatabl $writer->renderBeginTag('input'); $writer->renderEndTag(); } + + /** + * Sets the post back options for this textbox. + * @return TPostBackOptions + */ + protected function getAutoPostBackOptions() + { + $option=new TPostBackOptions(); + $group = $this->getValidationGroup(); + $hasValidators = $this->getPage()->getValidators($group)->getCount()>0; + if($this->getCausesValidation() && $hasValidators) + { + $option->setPerformValidation(true); + $option->setValidationGroup($group); + } + $option->setAutoPostBack(true); + } + } ?> \ No newline at end of file diff --git a/framework/Web/UI/WebControls/TImageButton.php b/framework/Web/UI/WebControls/TImageButton.php index 96fbff67..131f7b1c 100644 --- a/framework/Web/UI/WebControls/TImageButton.php +++ b/framework/Web/UI/WebControls/TImageButton.php @@ -51,10 +51,6 @@ Prado::using('System.Web.UI.WebControls.TImage'); * You can change the postback target by setting the {@link setPostBackUrl PostBackUrl} * property. * - * To set the client-side javascript associated with the user's click action, - * use the {@link setOnClientClick OnClientClick} property. The value will be rendered - * as the onclick attribute of the button. - * * TImageButton displays the {@link setText Text} property as the hint text to the displayed image. * * @author Qiang Xue @@ -93,19 +89,8 @@ class TImageButton extends TImage implements IPostBackDataHandler, IPostBackEven $writer->addAttribute('type','image'); if(($uniqueID=$this->getUniqueID())!=='') $writer->addAttribute('name',$uniqueID); - - if($this->getEnabled(true)) - { - $onclick=$this->removeAttribute('onclick'); - $onclick=THttpUtility::trimJavaScriptString($onclick).THttpUtility::trimJavaScriptString($this->getOnClientClick()); - $onclick.=$page->getClientScript()->getPostBackEventReference($this,'',$this->getPostBackOptions(),false); - if(!empty($onclick)) - $writer->addAttribute('onclick','javascript:'.$onclick); - } - else if($this->getEnabled()) // in this case, parent will not render 'disabled' + if(!$this->getEnabled()) // in this case, parent will not render 'disabled' $writer->addAttribute('disabled','disabled'); - if($onclick!=='') - $writer->addAttribute('onclick','javascript:'.$onclick); parent::addAttributesToRender($writer); } @@ -279,22 +264,6 @@ class TImageButton extends TImage implements IPostBackDataHandler, IPostBackEven $this->setViewState('PostBackUrl',$value,''); } - /** - * @return string the javascript to be executed when the button is clicked. - */ - public function getOnClientClick() - { - return $this->getViewState('OnClientClick',''); - } - - /** - * @param string the javascript to be executed when the button is clicked. - */ - public function setOnClientClick($value) - { - $this->setViewState('OnClientClick',$value,''); - } - /** * @return string caption of the button */ diff --git a/framework/Web/UI/WebControls/TJavascriptLogger.php b/framework/Web/UI/WebControls/TJavascriptLogger.php new file mode 100644 index 00000000..d5761a90 --- /dev/null +++ b/framework/Web/UI/WebControls/TJavascriptLogger.php @@ -0,0 +1,65 @@ + + * @version $Revision: 1.2 $ $Date: 2005/11/06 23:02:33 $ + * @package System.Web.UI.WebControls + */ + +/** + * TJavascriptLogger class. + * + * Provides logging for client-side javascript. Example: template code + * + * + * Client-side javascript code to log info, error, warn, debug + * Logger.warn('A warning'); + * Logger.info('something happend'); + * + * + * To see the logger and console, press ALT-D (or CTRL-D on OS X). + * More information on the logger can be found at + * http://gleepglop.com/javascripts/logger/ + * + * @author Wei Zhuo + * @version $Revision: 1.2 $ $Date: 2005/11/06 23:02:33 $ + * @package System.Web.UI.WebControls + * @since 2.0.2 + */ +class TJavascriptLogger extends TWebControl +{ + + /** + * @return string tag name of the panel + */ + protected function getTagName() + { + return 'div'; + } + + /** + * Register the required javascript libraries and + * display some general usage information. + * @param THtmlWriter the writer used for the rendering purpose + */ + protected function renderContents($writer) + { + $this->Page->ClientScript->registerPradoScript('logger'); + $info = '(more info).'; + $usage = 'Press ALT-D (Or CTRL-D on OS X) to toggle the javascript log console'; + $writer->write("{$usage} {$info}"); + parent::renderContents($writer); + } +} + +?> \ No newline at end of file diff --git a/framework/Web/UI/WebControls/TLinkButton.php b/framework/Web/UI/WebControls/TLinkButton.php index dd2d8cb7..3ddb6f68 100644 --- a/framework/Web/UI/WebControls/TLinkButton.php +++ b/framework/Web/UI/WebControls/TLinkButton.php @@ -46,10 +46,6 @@ * You can change the postback target by setting the {@link setPostBackUrl PostBackUrl} * property. * - * To set the client-side javascript associated with the user's click action, - * use the {@link setOnClientClick OnClientClick} property. The value will be rendered - * as the onclick attribute of the link button. - * * TLinkButton will display the {@link setText Text} property value * as the hyperlink text. If {@link setText Text} is empty, the body content * of TLinkButton will be displayed. Therefore, you can use TLinkButton @@ -79,19 +75,41 @@ class TLinkButton extends TWebControl implements IPostBackEventHandler { $page=$this->getPage(); $page->ensureRenderInForm($this); - $onclick=$this->removeAttribute('onclick'); - $onclick=THttpUtility::trimJavaScriptString($onclick).THttpUtility::trimJavaScriptString($this->getOnClientClick()); - if(!empty($onclick)) - $writer->addAttribute('onclick','javascript:'.$onclick); + + $writer->addAttribute('id',$this->getClientID()); // We call parent implementation here because some attributes // may be overwritten in the following parent::addAttributesToRender($writer); + + if($this->getEnabled()) + { + $url = $this->getPostBackUrl(); + //create unique no-op url references + $nop = "javascript:;//{$this->ClientID}"; + $writer->addAttribute('href', $url ? $url : $nop); + } + else// in this case, parent will not render 'disabled' + $writer->addAttribute('disabled','disabled'); + } + /** + * Registers the postback javascript code. + * If you override this method, be sure to call the parent implementation + * so that the event handlers can be invoked. + * @param TEventParameter event parameter to be passed to the event handlers + */ + protected function onPreRender($param) + { if($this->getEnabled(true)) - $writer->addAttribute('href',$page->getClientScript()->getPostBackEventReference($this,'',$this->getPostBackOptions(),true)); - else if($this->getEnabled()) // in this case, parent will not render 'disabled' - $writer->addAttribute('disabled','disabled'); + { + $scripts = $this->getPage()->getClientScript(); + $options = $this->getPostBackOptions(); + $postback = $scripts->getPostBackEventReference($this, '', $options, false); + $code = "{$postback}; Event.stop(e);"; + $scripts->registerClientEvent($this, "click", $code); + } + parent::onPreRender($param); } /** @@ -102,8 +120,11 @@ class TLinkButton extends TWebControl implements IPostBackEventHandler protected function getPostBackOptions() { $flag=false; - $options=new TPostBackOptions(); - if($this->getCausesValidation() && $this->getPage()->getValidators($this->getValidationGroup())->getCount()>0) + + $option=new TPostBackOptions(); + $group = $this->getValidationGroup(); + $hasValidators = $this->getPage()->getValidators($group)->getCount()>0; + if($this->getCausesValidation() && $hasValidators) { $flag=true; $options->setPerformValidation(true); @@ -182,22 +203,6 @@ class TLinkButton extends TWebControl implements IPostBackEventHandler $this->setViewState('CommandParameter',$value,''); } - /** - * @return string the javascript to be executed when the button is clicked - */ - public function getOnClientClick() - { - return $this->getViewState('OnClientClick',''); - } - - /** - * @param string the javascript to be executed when the button is clicked. Do not prefix it with "javascript:". - */ - public function setOnClientClick($value) - { - $this->setViewState('OnClientClick',$value,''); - } - /** * @return string the URL of the page to post to when the button is clicked, default is empty meaning post to the current page itself */ diff --git a/framework/Web/UI/WebControls/TRadioButton.php b/framework/Web/UI/WebControls/TRadioButton.php index 302d088c..153da8e6 100644 --- a/framework/Web/UI/WebControls/TRadioButton.php +++ b/framework/Web/UI/WebControls/TRadioButton.php @@ -153,21 +153,6 @@ class TRadioButton extends TCheckBox if(!$this->getEnabled(true)) $writer->addAttribute('disabled','disabled'); $page=$this->getPage(); - if($this->getAutoPostBack() && $page->getClientSupportsJavaScript()) - { - $option=new TPostBackOptions(); - if($this->getCausesValidation() && $page->getValidators($this->getValidationGroup())->getCount()) - { - $option->setPerformValidation(true); - $option->setValidationGroup($this->getValidationGroup()); - } - $option->setAutoPostBack(true); - if(!empty($onclick)) - $onclick=THttpUtility::trimJavaScriptString($onclick); - $onclick.=$page->getClientScript()->getPostBackEventReference($this,'',$option,false); - } - if(!empty($onclick)) - $writer->addAttribute('onclick',$onclick); if(($accesskey=$this->getAccessKey())!=='') $writer->addAttribute('accesskey',$accesskey); if(($tabindex=$this->getTabIndex())>0) diff --git a/framework/Web/UI/WebControls/TTextBox.php b/framework/Web/UI/WebControls/TTextBox.php index 3e5f0107..1ad736db 100644 --- a/framework/Web/UI/WebControls/TTextBox.php +++ b/framework/Web/UI/WebControls/TTextBox.php @@ -117,29 +117,49 @@ class TTextBox extends TWebControl implements IPostBackDataHandler, IValidatable $writer->addAttribute('readonly','readonly'); if(!$this->getEnabled(true) && $this->getEnabled()) // in this case parent will not render 'disabled' $writer->addAttribute('disabled','disabled'); - if($this->getAutoPostBack() && $page->getClientSupportsJavaScript()) + parent::addAttributesToRender($writer); + } + + /** + * Registers the auto-postback javascript code. + * If you override this method, be sure to call the parent implementation + * so that the event handlers can be invoked. + * @param TEventParameter event parameter to be passed to the event handlers + */ + protected function onPreRender($param) + { + if($this->getAutoPostBack() + && $this->getPage()->getClientSupportsJavaScript()) { - $option=new TPostBackOptions(); - if($this->getCausesValidation() && $page->getValidators($this->getValidationGroup())->getCount()>0) - { - $option->setPerformValidation(true); - $option->setValidationGroup($this->getValidationGroup()); - } - $option->setAutoPostBack(true); - $onchange=$this->removeAttribute('onchange'); - $onchange.=THttpUtility::trimJavaScriptString($onchange).$page->getClientScript()->getPostBackEventReference($this,'',$option,false); - $writer->addAttribute('onchange','javascript:'.$onchange); + $options = $this->getAutoPostBackOptions(); + $scripts = $this->getPage()->getClientScript(); + $postback = $scripts->getPostBackEventReference($this,'',$options,false); + $scripts->registerClientEvent($this, "change", $postback); - if($textMode!=='MultiLine') + if($this->getTextMode() !== 'MultiLine') { - // note, Prado.TextBox.handleReturnKey is defined in base.js, - // which is included when AutoPostBack is true for textbox. - $onkeypress='javascript:if(Prado.TextBox.handleReturnKey(event)==false) return false;'; - $onkeypress.=THttpUtility::trimJavaScriptString($this->removeAttribute('onkeypress')); - $writer->addAttribute('onkeypress',$onkeypress); + $code = "if(Prado.TextBox.handleReturnKey(e)==false) Event.stop(e);"; + $scripts->registerClientEvent($this, "keypress", $code); } } - parent::addAttributesToRender($writer); + parent::onPreRender($param); + } + + /** + * Sets the post back options for this textbox. + * @return TPostBackOptions + */ + protected function getAutoPostBackOptions() + { + $option=new TPostBackOptions(); + $group = $this->getValidationGroup(); + $hasValidators = $this->getPage()->getValidators($group)->getCount()>0; + if($this->getCausesValidation() && $hasValidators) + { + $option->setPerformValidation(true); + $option->setValidationGroup($group); + } + $option->setAutoPostBack(true); } /** -- cgit v1.2.3