* @link http://www.pradosoft.com/ * @copyright Copyright © 2005 PradoSoft * @license http://www.pradosoft.com/license/ * @version $Revision: $ $Date: $ * @package System.Web.UI */ /** * TClientScriptManager class. * * TClientScriptManager manages javascript and CSS stylesheets for a page. * * @author Qiang Xue * @version $Revision: $ $Date: $ * @package System.Web.UI * @since 3.0 */ class TClientScriptManager extends TApplicationComponent { /** * directory containing Prado javascript files */ const SCRIPT_PATH='Web/Javascripts/js'; /** * the PHP script for loading Prado javascript files */ const SCRIPT_LOADER='clientscripts.php'; /** * @var TPage page who owns this manager */ private $_page; /** * @var array registered hidden fields, indexed by hidden field names */ private $_hiddenFields=array(); /** * @var array javascript blocks to be rendered at the beginning of the form */ private $_beginScripts=array(); /** * @var array javascript blocks to be rendered at the end of the form */ private $_endScripts=array(); /** * @var array javascript files to be rendered in the form */ private $_scriptFiles=array(); /** * @var array javascript files to be renderd in page head section */ private $_headScriptFiles=array(); /** * @var array javascript blocks to be renderd in page head section */ private $_headScripts=array(); /** * @var array CSS files */ private $_styleSheetFiles=array(); /** * @var array CSS declarations */ private $_styleSheets=array(); /** * @var array registered PRADO script libraries */ private $_registeredPradoScripts=array(); /** * @var array registered PRADO script files */ private $_registeredPradoFiles=array(); /** * Client-side javascript library dependencies * @var array */ private static $_pradoScripts=array( 'prado' => array('prado'), 'effects' => array('prado', 'effects'), 'ajax' => array('prado', 'effects', 'ajax'), 'validator' => array('prado', 'validator'), 'logger' => array('prado', 'logger'), 'datepicker' => array('prado', 'datepicker'), 'rico' => array('prado', 'effects', 'ajax', 'rico'), 'colorpicker' => array('prado', 'colorpicker') ); /** * Constructor. * @param TPage page that owns this client script manager */ public function __construct(TPage $owner) { $this->_page=$owner; } /** * Registers Prado scripts by library name. * Each library may include one or several script files. * Currently, the following libraries are available: * - prado : basic prado js framework * - effects : * - ajax : ajax related js * - validator : validator js * - logger : js logger * - datepicker : datepicker js * - rico : * - colorpicker : colorpicker js * The script files registered will be published. * @param string script library name. */ public function registerPradoScript($name) { $this->registerPradoScriptInternal($name); $params=func_get_args(); foreach($this->_page->getCachingStack() as $item) $item->registerAction('Page.ClientScript','registerPradoScript',$params); } private function registerPradoScriptInternal($name) { if(!isset($this->_registeredPradoScripts[$name])) { $this->_registeredPradoScripts[$name]=true; if(!isset(self::$_pradoScripts[$name])) throw new TInvalidOperationException('csmanager_pradoscript_invalid',$name); $basePath=Prado::getFrameworkPath().'/'.self::SCRIPT_PATH; foreach(self::$_pradoScripts[$name] as $script) { if(!isset($this->_registeredPradoFiles[$script])) { $this->publishFilePath($basePath.'/'.$script.'.js'); $this->_registeredPradoFiles[$script]=false; } } } } protected function renderPradoScripts($writer) { $files=''; foreach($this->_registeredPradoFiles as $file=>$rendered) { if(!$rendered) { $files.=','.$file; $this->_registeredPradoFiles[$file]=true; } } if($files!=='') { $basePath=Prado::getFrameworkPath().'/'.self::SCRIPT_PATH; $scriptLoader=$basePath.'/'.self::SCRIPT_LOADER; $url=$this->publishFilePath($scriptLoader).'?js='.trim($files,','); if($this->getApplication()->getMode()===TApplication::STATE_DEBUG) $url.='&__nocache'; $writer->write(TJavaScript::renderScriptFile($url)); } } public function getCallbackReference($callbackHandler, $options=null) { $options = !is_array($options) ? array() : $options; $class = new TReflectionClass($callbackHandler); if($class->hasMethod('getClientSide')) { $clientSide = $callbackHandler->getClientSide(); $options = array_merge($options, $clientSide->getOptions()->toArray()); } $optionString = TJavascript::encode($options); $this->registerPradoScriptInternal('ajax'); $id = $callbackHandler->getUniqueID(); return "new Prado.CallbackRequest('{$id}',{$optionString})"; } /** * Registers postback javascript for a control. * @param string javascript class responsible for the control being registered for postback * @param array postback options */ public function registerPostBackControl($jsClass,$options) { if(!isset($options['FormID']) && ($form=$this->_page->getForm())!==null) $options['FormID']=$form->getClientID(); $optionString=TJavaScript::encode($options); $code="new $jsClass($optionString);"; $this->_endScripts[sprintf('%08X', crc32($code))]=$code; $this->_hiddenFields[TPage::FIELD_POSTBACK_TARGET]=''; $this->_hiddenFields[TPage::FIELD_POSTBACK_PARAMETER]=''; $this->registerPradoScriptInternal('prado'); $params=func_get_args(); foreach($this->_page->getCachingStack() as $item) $item->registerAction('Page.ClientScript','registerPostBackControl',$params); } /** * Register a default button to panel. When the $panel is in focus and * the 'enter' key is pressed, the $button will be clicked. * @param string client ID of the container object * @param string client ID of the button */ public function registerDefaultButton($containerID, $buttonID) { $options = TJavaScript::encode($this->getDefaultButtonOptions($containerID, $buttonID)); $code = "new Prado.WebUI.DefaultButton($options);"; $this->_endScripts['prado:'.$containerID]=$code; $this->registerPradoScriptInternal('prado'); $params=func_get_args(); foreach($this->_page->getCachingStack() as $item) $item->registerAction('Page.ClientScript','registerDefaultButton',$params); } /** * Registers the control to receive default focus. * @param string the client ID of the control to receive default focus */ public function registerFocusControl($target) { $this->registerPradoScriptInternal('prado'); $this->_endScripts['prado:focus']='Prado.Focus.setFocus("'.TJavaScript::quoteString($target).'");'; $params=func_get_args(); foreach($this->_page->getCachingStack() as $item) $item->registerAction('Page.ClientScript','registerFocusControl',$params); } /** * @param string client ID of the container object * @param string client ID of the button * @return array default button options. */ protected function getDefaultButtonOptions($containerID, $buttonID) { $options['Panel'] = $containerID; $options['Target'] = $buttonID; $options['Event'] = 'click'; return $options; } /** * Registers a CSS file to be rendered in the page head * @param string a unique key identifying the file * @param string URL to the CSS file */ public function registerStyleSheetFile($key,$url) { $this->_styleSheetFiles[$key]=$url; $params=func_get_args(); foreach($this->_page->getCachingStack() as $item) $item->registerAction('Page.ClientScript','registerStyleSheetFile',$params); } /** * Registers a CSS block to be rendered in the page head * @param string a unique key identifying the CSS block * @param string CSS block */ public function registerStyleSheet($key,$css) { $this->_styleSheets[$key]=$css; $params=func_get_args(); foreach($this->_page->getCachingStack() as $item) $item->registerAction('Page.ClientScript','registerStyleSheet',$params); } /** * Registers a javascript file in the page head * @param string a unique key identifying the file * @param string URL to the javascript file */ public function registerHeadScriptFile($key,$url) { $this->_headScriptFiles[$key]=$url; $params=func_get_args(); foreach($this->_page->getCachingStack() as $item) $item->registerAction('Page.ClientScript','registerHeadScriptFile',$params); } /** * Registers a javascript block in the page head. * @param string a unique key identifying the script block * @param string javascript block */ public function registerHeadScript($key,$script) { $this->_headScripts[$key]=$script; $params=func_get_args(); foreach($this->_page->getCachingStack() as $item) $item->registerAction('Page.ClientScript','registerHeadScript',$params); } /** * Registers a javascript file to be rendered within the form * @param string a unique key identifying the file * @param string URL to the javascript file to be rendered */ public function registerScriptFile($key,$url) { $this->_scriptFiles[$key]=$url; $params=func_get_args(); foreach($this->_page->getCachingStack() as $item) $item->registerAction('Page.ClientScript','registerScriptFile',$params); } /** * Registers a javascript script block at the beginning of the form * @param string a unique key identifying the script block * @param string javascript block */ public function registerBeginScript($key,$script) { $this->_beginScripts[$key]=$script; $params=func_get_args(); foreach($this->_page->getCachingStack() as $item) $item->registerAction('Page.ClientScript','registerBeginScript',$params); } /** * Registers a javascript script block at the end of the form * @param string a unique key identifying the script block * @param string javascript block */ public function registerEndScript($key,$script) { $this->_endScripts[$key]=$script; $params=func_get_args(); foreach($this->_page->getCachingStack() as $item) $item->registerAction('Page.ClientScript','registerEndScript',$params); } /** * Registers a hidden field to be rendered in the form. * @param string a unique key identifying the hidden field * @param string|array hidden field value, if the value is an array, every element * in the array will be rendered as a hidden field value. */ public function registerHiddenField($name,$value) { $this->_hiddenFields[$name]=$value; $params=func_get_args(); foreach($this->_page->getCachingStack() as $item) $item->registerAction('Page.ClientScript','registerHiddenField',$params); } /** * @param string a unique key * @return boolean whether there is a CSS file registered with the specified key */ public function isStyleSheetFileRegistered($key) { return isset($this->_styleSheetFiles[$key]); } /** * @param string a unique key * @return boolean whether there is a CSS block registered with the specified key */ public function isStyleSheetRegistered($key) { return isset($this->_styleSheets[$key]); } /** * @param string a unique key * @return boolean whether there is a head javascript file registered with the specified key */ public function isHeadScriptFileRegistered($key) { return isset($this->_headScriptFiles[$key]); } /** * @param string a unique key * @return boolean whether there is a head javascript block registered with the specified key */ public function isHeadScriptRegistered($key) { return isset($this->_headScripts[$key]); } /** * @param string a unique key * @return boolean whether there is a javascript file registered with the specified key */ public function isScriptFileRegistered($key) { return isset($this->_scriptFiles[$key]); } /** * @param string a unique key * @return boolean whether there is a beginning javascript block registered with the specified key */ public function isBeginScriptRegistered($key) { return isset($this->_beginScripts[$key]); } /** * @param string a unique key * @return boolean whether there is an ending javascript block registered with the specified key */ public function isEndScriptRegistered($key) { return isset($this->_endScripts[$key]); } /** * @param string a unique key * @return boolean whether there is a hidden field registered with the specified key */ public function isHiddenFieldRegistered($key) { return isset($this->_hiddenFields[$key]); } /** * @param THtmlWriter writer for the rendering purpose */ public function renderStyleSheetFiles($writer) { $str=''; foreach($this->_styleSheetFiles as $url) $str.="\n"; $writer->write($str); } /** * @param THtmlWriter writer for the rendering purpose */ public function renderStyleSheets($writer) { if(count($this->_styleSheets)) $writer->write("\n"); } /** * @param THtmlWriter writer for the rendering purpose */ public function renderHeadScriptFiles($writer) { $writer->write(TJavaScript::renderScriptFiles($this->_headScriptFiles)); } /** * @param THtmlWriter writer for the rendering purpose */ public function renderHeadScripts($writer) { $writer->write(TJavaScript::renderScriptBlocks($this->_headScripts)); } /** * @param THtmlWriter writer for the rendering purpose */ public function renderScriptFiles($writer) { $this->renderPradoScripts($writer); $files=array(); foreach($this->_scriptFiles as $key=>$file) { if($file!==true) { $files[]=$file; $this->_scriptFiles[$key]=true; } } if(!empty($files)) $writer->write(TJavaScript::renderScriptFiles($files)); } /** * @param THtmlWriter writer for the rendering purpose */ public function renderBeginScripts($writer) { $writer->write(TJavaScript::renderScriptBlocks($this->_beginScripts)); } /** * @param THtmlWriter writer for the rendering purpose */ public function renderEndScripts($writer) { $writer->write(TJavaScript::renderScriptBlocks($this->_endScripts)); } /** * @param THtmlWriter writer for the rendering purpose */ public function renderHiddenFields($writer) { $str=''; foreach($this->_hiddenFields as $name=>$value) { if($value!==true) { if(is_array($value)) { foreach($value as $v) $str.='\n"; } else { $str.='\n"; } // set hidden field value to true to indicate this field is rendered // Note, hidden field rendering is invoked twice (at the beginning and ending of TForm) $this->_hiddenFields[$name]=true; } } if($str!=='') $writer->write("
\n".$str."
\n"); } } /** * TClientSideOptions abstract class. * * TClientSideOptions manages client-side options for components that have * common client-side javascript behaviours and client-side events such as * between ActiveControls and validators. * * @author * @version $Revision: $ $Date: $ * @package System.Web.UI * @since 3.0 */ abstract class TClientSideOptions extends TComponent { /** * @var TMap list of client-side options. */ private $_options; /** * Constructor, initialize the options list. */ public function __construct() { $this->_options = Prado::createComponent('System.Collections.TMap'); } /** * Adds on client-side event handler by wrapping the code within a * javascript function block. If the code begins with "javascript:", the * code is assumed to be a javascript function block rather than arbiturary * javascript statements. * @param string option name * @param string javascript statements. */ protected function setFunction($name, $code) { $this->_options->add($name, $this->ensureFunction($code)); } /** * @return string gets a particular option, null if not set. */ protected function getOption($name) { return $this->_options->itemAt($name); } /** * @return TMap gets the list of options as TMap */ public function getOptions() { return $this->_options; } /** * Ensure that the javascript statements are wrapped in a javascript * function block. Default has no wrapping. Override this method to * customize the wrapping javascript function block. */ protected function ensureFunction($javascript) { return $javascript; } } ?>