diff options
-rw-r--r-- | framework/Exceptions/messages.txt | 4 | ||||
-rw-r--r-- | framework/Web/UI/WebControls/TClientScript.php | 170 | ||||
-rw-r--r-- | framework/Web/UI/WebControls/TStyleSheet.php | 75 | ||||
-rw-r--r-- | tests/FunctionalTests/features/protected/pages/ClientScripTest.page | 30 | ||||
-rw-r--r-- | tests/FunctionalTests/features/protected/pages/test.js | 4 |
5 files changed, 281 insertions, 2 deletions
diff --git a/framework/Exceptions/messages.txt b/framework/Exceptions/messages.txt index 230789e7..a807130c 100644 --- a/framework/Exceptions/messages.txt +++ b/framework/Exceptions/messages.txt @@ -316,4 +316,6 @@ databoundcontrol_currentpageindex_invalid = {0}.CurrentPageIndex is out of range databoundcontrol_datasource_invalid = {0}.DataSource is not valid.
databoundcontrol_datasourceid_inexistent = databoundcontrol_datasourceid_inexistent.
databoundcontrol_datasourceid_invalid = databoundcontrol_datasourceid_invalid
-databoundcontrol_datamember_invalid = databoundcontrol_datamember_invalid
\ No newline at end of file +databoundcontrol_datamember_invalid = databoundcontrol_datamember_invalid
+
+clientscript_invalid_file_position = Invalid file position '{1}' for TClientScript control '{0}', must be 'Head', 'Here' or 'Begin'.
\ No newline at end of file diff --git a/framework/Web/UI/WebControls/TClientScript.php b/framework/Web/UI/WebControls/TClientScript.php index 23aa1425..b2fbf925 100644 --- a/framework/Web/UI/WebControls/TClientScript.php +++ b/framework/Web/UI/WebControls/TClientScript.php @@ -22,7 +22,29 @@ * <com:TClientScript UsingPradoScripts="effects, rico" />
* </code>
*
- * @TODO May be use it to include stylesheets as well.
+ * The {@link setPreRenderControlTypes PreRenderControlTypes} property can
+ * be used to specify that controls type/class names that should pre-render itself
+ * even though they may not be rendered on the page. This is useful to publish
+ * controls that require assets and is only visible after a callback response.
+ *
+ * Custom javascript files can be register using the {@link setScriptUrl ScriptUrl}
+ * property.
+ * <code>
+ * <com:TClientScript ScriptUrl=<%~ test.js %> />
+ * </code>
+ *
+ * Contents within TClientScript will be treated as javascript code and will be
+ * rendered.
+ *
+ * The {@link setScriptPosition ScriptPosition} property specifies where the script
+ * will be rendered. The allows values of {@link setScriptPosition ScriptPosition} are
+ *
+ * - <b>Head</b> -- renders the script within the <head>
+ * - <b>Begin</b> -- renders the script within and near the begining of TForm
+ * - <b>Here</b> -- renders the script inplace, this is the default
+ * - <b>End</b> -- renders the script within and near the end of TForm
+ *
+ * TODO: Allow binding expressions inside scripts
*
* @author Wei Zhuo <weizhuo[at]gmail[dot]com>
* @version $Revision: $ $Date: $
@@ -32,6 +54,11 @@ class TClientScript extends TControl
{
/**
+ * @var string body contents
+ */
+ private $_content = '';
+
+ /**
* @return string comma delimited list of javascript libraries to included
* on the page.
*/
@@ -54,6 +81,58 @@ class TClientScript extends TControl }
/**
+ * @return string custom javascript file url.
+ */
+ public function getScriptUrl()
+ {
+ return $this->getViewState('ScriptUrl', '');
+ }
+
+ /**
+ * @param string custom javascript file url.
+ */
+ public function setScriptUrl($value)
+ {
+ $this->setViewState('ScriptUrl', $value, '');
+ }
+
+ /**
+ * @param string comma delimited list of controls that wish to be prerendered
+ * so as to publish its assets.
+ */
+ public function setPreRenderControlTypes($value)
+ {
+ $this->setViewState('PreRenderControls', $value);
+ }
+
+ /**
+ * @return string comma delimited list of controls types that require prerendering.
+ */
+ public function getPreRenderControlTypes()
+ {
+ return $this->getViewState('PreRenderControls', '');
+ }
+
+ /**
+ * @return string position the script should be rendered, default is 'Here'.
+ */
+ public function getScriptPosition()
+ {
+ return $this->getViewState('ScriptPosition', 'Here');
+ }
+
+ /**
+ * Sets the position where the script will be rendered.
+ * The allow positions are 'Head', 'Begin', 'Here', and 'End', default is 'Here'.
+ * @param string script position 'Head', 'Begin', 'Here' or 'End'.
+ */
+ public function setScriptPosition($value)
+ {
+ $this->setViewState('ScriptPosition',
+ TPropertyValue::ensureEnum($value, 'Head', 'Begin', 'Here', 'End'), 'Here');
+ }
+
+ /**
* Calls the client script manager to add each of the requested client
* script libraries.
* @param mixed event parameter
@@ -69,6 +148,95 @@ class TClientScript extends TControl if(strlen($script) > 0)
$cs->registerPradoScript($script);
}
+ if($this->getEnabled(true))
+ {
+ $this->registerCustomScriptFile();
+ $this->registerCustomScript();
+ }
+ $this->preRenderControls($param);
+ }
+
+ /**
+ * Registers the custom script file.
+ */
+ protected function registerCustomScriptFile()
+ {
+ $scriptUrl = $this->getScriptUrl();
+ if(strlen($scriptUrl))
+ {
+ $position = $this->getScriptPosition();
+ $cs = $this->getPage()->getClientScript();
+ switch($this->getScriptPosition())
+ {
+ case 'Head':
+ $cs->registerHeadScriptFile($scriptUrl, $scriptUrl);
+ break;
+ case 'Begin':
+ $cs->registerScriptFile($scriptUrl, $scriptUrl);
+ break;
+ case 'Here':
+ $this->_content .= TJavascript::renderScriptFile($scriptUrl);
+ break;
+ default :
+ throw new TConfigurationException('clientscript_invalid_file_position',
+ $this->getID(), $position);
+ }
+ }
+ }
+
+ /**
+ * Renders the body content as javascript block.
+ * Overrides parent implementation, parent renderChildren method is called during
+ * {@link registerCustomScript}.
+ * @param THtmlWriter the renderer
+ */
+ public function render($writer)
+ {
+ if($this->getEnabled(true) && strlen($this->_content) > 0)
+ $writer->write($this->_content);
+ }
+
+ /**
+ * Registers the body content as scripts at specific locations. Calls
+ * {@link parent::renderChildren} to capture the body contents.
+ */
+ protected function registerCustomScript()
+ {
+ $textWriter=new TTextWriter;
+ $this->renderChildren(new THtmlWriter($textWriter));
+ $script=$textWriter->flush();
+ if(strlen($script)>0)
+ {
+ $cs = $this->getPage()->getClientScript();
+ $position = $this->getScriptPosition();
+ if($position == 'Here')
+ $this->_content .= TJavaScript::renderScriptBlock($script);
+ else
+ {
+ $key = sprintf('%08X', crc32($script));
+ $method = 'register'.$position.'Script';
+ $cs->{$method}($key, $script);
+ }
+ }
+ }
+
+ /**
+ * PreRender other controls to allow them to publish their assets. Useful
+ * when callback response components that require assets to be present on the page.
+ * @param mixed event paramater
+ */
+ protected function preRenderControls($param)
+ {
+ $types = preg_split('/,|\s+/', $this->getPreRenderControlTypes());
+ foreach($types as $type)
+ {
+ if(strlen($type))
+ {
+ $control = Prado::createComponent(trim($type));
+ $control->setPage($this->getPage());
+ $control->onPreRender($param);
+ }
+ }
}
}
diff --git a/framework/Web/UI/WebControls/TStyleSheet.php b/framework/Web/UI/WebControls/TStyleSheet.php new file mode 100644 index 00000000..5b4cc944 --- /dev/null +++ b/framework/Web/UI/WebControls/TStyleSheet.php @@ -0,0 +1,75 @@ +<?php + +/** + * TStyleSheet class. + * + * @author Wei Zhuo <weizhuo[at]gmail[dot]com> + * @version : $ Tue Jul 4 04:38:16 EST 2006 $ + * @package System.Web.UI.WebControl + * @since 3.0.2 + */ +class TStyleSheet extends TControl +{ + /** + * @param string stylesheet url or asset resource. + */ + public function setStyleUrl($value) + { + $this->setViewState('StyleUrl', $value); + } + + /** + * @return string stylesheet url. + */ + public function getStyleUrl() + { + return $this->getViewState('StyleUrl', ''); + } + + /** + * Registers the stylesheet urls. Calls {@link renderChildren} to capture + * the body content to render the stylesheet in the head. + * @param mixed event parameter + */ + public function onPreRender($param) + { + if($this->getEnabled(true)) + { + $this->registerCustomStyleSheetFile(); + $this->registerCustomStyleSheet(); + } + } + + /** + * Overrides parent implementation, renders nothing. + */ + public function renderChildren($writer) + { + + } + + /** + * Register custom stylesheet file. + */ + protected function registerCustomStyleSheetFile() + { + $cs = $this->getPage()->getClientScript(); + $url = $this->getStyleUrl(); + if(strlen($url) > 0) + $cs->registerStyleSheetFile($url, $url); + } + + /** + * Registers the body content as stylesheet. + */ + protected function registerCustomStyleSheet() + { + $cs = $this->getPage()->getClientScript(); + $textWriter=new TTextWriter; + parent::renderChildren(new THtmlWriter($textWriter)); + $text = $textWriter->flush(); + if(strlen($text)>0) + $cs->registerStyleSheet(sprintf('%08X', crc32($text)), $text); + } +} +?>
\ No newline at end of file diff --git a/tests/FunctionalTests/features/protected/pages/ClientScripTest.page b/tests/FunctionalTests/features/protected/pages/ClientScripTest.page new file mode 100644 index 00000000..8dbf7133 --- /dev/null +++ b/tests/FunctionalTests/features/protected/pages/ClientScripTest.page @@ -0,0 +1,30 @@ +<com:TContent ID="Content"> + <h1>ClientScript Test</h1> + + <com:TClientScript ScriptUrl=<%~ test.js %> ScriptPosition="Head"> + if(typeof(ClientScriptInfo) == "undefined") + ClientScriptInfo = []; + ClientScriptInfo.push("ok 3?") + </com:TClientScript> + + <com:TClientScript ScriptPosition="Begin"> + if(typeof(ClientScriptInfo) == "undefined") + ClientScriptInfo = []; + ClientScriptInfo.push("ok 2!") + </com:TClientScript> + + <com:TLabel ID="label1" Text="Label 1" /> + <input type="button" id="button1" value="update" /> + + <com:TClientScript ScriptPosition="End" UsingPradoScripts="prado"> + Event.observe("button1", "click", function() + { + element = $("<%= $this->label1->ClientID %>"); + if(element) + element.innerHTML = inspect(ClientScriptInfo); + else + alert("failed"); + }); + </com:TClientScript> + +</com:TContent>
\ No newline at end of file diff --git a/tests/FunctionalTests/features/protected/pages/test.js b/tests/FunctionalTests/features/protected/pages/test.js new file mode 100644 index 00000000..e8e80b19 --- /dev/null +++ b/tests/FunctionalTests/features/protected/pages/test.js @@ -0,0 +1,4 @@ +if(typeof(ClientScriptInfo) == "undefined") + ClientScriptInfo = []; + +ClientScriptInfo.push("ok")
\ No newline at end of file |