summaryrefslogtreecommitdiff
path: root/framework/Web
diff options
context:
space:
mode:
Diffstat (limited to 'framework/Web')
-rw-r--r--framework/Web/Javascripts/packages.php47
-rw-r--r--framework/Web/UI/ActiveControls/TActiveControlAdapter.php2
-rwxr-xr-xframework/Web/UI/ActiveControls/TActiveFileUpload.php2
-rwxr-xr-xframework/Web/UI/ActiveControls/TDraggable.php10
-rwxr-xr-xframework/Web/UI/ActiveControls/TDropContainer.php2
-rw-r--r--framework/Web/UI/TClientScriptManager.php102
-rw-r--r--framework/Web/UI/WebControls/TAccordion.php7
-rw-r--r--framework/Web/UI/WebControls/TBaseValidator.php1503
-rw-r--r--framework/Web/UI/WebControls/TClientScript.php288
-rw-r--r--framework/Web/UI/WebControls/THtmlArea.php1081
-rw-r--r--framework/Web/UI/WebControls/TTabPanel.php1459
-rw-r--r--framework/Web/UI/WebControls/TTextHighlighter.php419
12 files changed, 2478 insertions, 2444 deletions
diff --git a/framework/Web/Javascripts/packages.php b/framework/Web/Javascripts/packages.php
index a32c54b5..316716d6 100644
--- a/framework/Web/Javascripts/packages.php
+++ b/framework/Web/Javascripts/packages.php
@@ -8,13 +8,15 @@ if (!defined('SCRIPTACULOUS_DIR')) define ('SCRIPTACULOUS_DIR', 'scriptaculous-1
//package names and its contents (files relative to the current directory)
$packages = array(
- 'prado' => array(
+ 'prototype' => array(
PROTOTYPE_DIR.'/prototype.js',
SCRIPTACULOUS_DIR.'/builder.js',
- SCRIPTACULOUS_DIR.'/effects.js',
+ ),
+ 'prado' => array(
'prado/prado.js',
'prado/scriptaculous-adapter.js',
- 'prado/controls/controls.js'
+ 'prado/controls/controls.js',
+ SCRIPTACULOUS_DIR.'/effects.js'
),
'effects' => array(
@@ -41,7 +43,7 @@ $packages = array(
SCRIPTACULOUS_DIR.'/controls.js',
'prado/activecontrols/json2.js',
'prado/activecontrols/ajax3.js',
- 'prado/activecontrols/activecontrols3.js'
+ 'prado/activecontrols/activecontrols3.js',
),
'dragdrop'=>array(
@@ -94,24 +96,25 @@ $packages = array(
//package names and their dependencies
$dependencies = array(
- 'prado' => array('prado'),
- 'effects' => array('prado', 'effects'),
- 'validator' => array('prado', 'validator'),
- 'logger' => array('prado', 'logger'),
- 'datepicker' => array('prado', 'datepicker'),
- 'colorpicker' => array('prado', 'colorpicker'),
- 'ajax' => array('prado', 'effects', 'ajax'),
- 'dragdrop' => array('prado', 'effects', 'ajax', 'dragdrop'),
- 'slider' => array('prado', 'slider'),
- 'keyboard' => array('prado', 'keyboard'),
- 'tabpanel' => array('prado', 'tabpanel'),
- 'activedatepicker' => array('prado', 'datepicker', 'ajax', 'activedatepicker'),
- 'activefileupload' => array('prado', 'effects', 'ajax', 'activefileupload'),
- 'dragdropextra' => array('prado', 'effects', 'ajax', 'dragdrop','dragdropextra'),
- 'accordion' => array('prado', 'effects', 'accordion'),
- 'htmlarea' => array('prado', 'htmlarea'),
- 'ratings' => array('prado', 'effects', 'ajax', 'ratings'),
- 'inlineeditor' => array('prado', 'effects', 'ajax', 'inlineeditor'),
+ 'prototype' => array('prototype'),
+ 'prado' => array('prototype', 'prado'),
+ 'effects' => array('prototype', 'prado', 'effects'),
+ 'validator' => array('prototype', 'prado', 'validator'),
+ 'logger' => array('prototype', 'prado', 'logger'),
+ 'datepicker' => array('prototype', 'prado', 'datepicker'),
+ 'colorpicker' => array('prototype', 'prado', 'colorpicker'),
+ 'ajax' => array('prototype', 'prado', 'effects', 'ajax'),
+ 'dragdrop' => array('prototype', 'prado', 'effects', 'ajax', 'dragdrop'),
+ 'slider' => array('prototype', 'prado', 'slider'),
+ 'keyboard' => array('prototype', 'prado', 'keyboard'),
+ 'tabpanel' => array('prototype', 'prado', 'tabpanel'),
+ 'activedatepicker' => array('prototype', 'prado', 'datepicker', 'ajax', 'activedatepicker'),
+ 'activefileupload' => array('prototype', 'prado', 'effects', 'ajax', 'activefileupload'),
+ 'dragdropextra' => array('prototype', 'prado', 'effects', 'ajax', 'dragdrop','dragdropextra'),
+ 'accordion' => array('prototype', 'prado', 'effects', 'accordion'),
+ 'htmlarea' => array('prototype', 'prado', 'htmlarea'),
+ 'ratings' => array('prototype', 'prado', 'effects', 'ajax', 'ratings'),
+ 'inlineeditor' => array('prototype', 'prado', 'effects', 'ajax', 'inlineeditor'),
);
return array($packages, $dependencies);
diff --git a/framework/Web/UI/ActiveControls/TActiveControlAdapter.php b/framework/Web/UI/ActiveControls/TActiveControlAdapter.php
index 3e6747b3..a2e5d0ce 100644
--- a/framework/Web/UI/ActiveControls/TActiveControlAdapter.php
+++ b/framework/Web/UI/ActiveControls/TActiveControlAdapter.php
@@ -81,7 +81,6 @@ class TActiveControlAdapter extends TControlAdapter
public function onPreRender($param)
{
parent::onPreRender($param);
- $this->getPage()->getClientScript()->registerPradoScript('ajax');
}
/**
@@ -89,6 +88,7 @@ class TActiveControlAdapter extends TControlAdapter
*/
public function render($writer)
{
+ $this->getPage()->getClientScript()->registerPradoScript('ajax');
$this->renderCallbackClientScripts();
if($this->_control->getVisible(false))
{
diff --git a/framework/Web/UI/ActiveControls/TActiveFileUpload.php b/framework/Web/UI/ActiveControls/TActiveFileUpload.php
index b4557cd8..ca924026 100755
--- a/framework/Web/UI/ActiveControls/TActiveFileUpload.php
+++ b/framework/Web/UI/ActiveControls/TActiveFileUpload.php
@@ -270,7 +270,6 @@ EOS;
public function onPreRender($param)
{
parent::onPreRender($param);
- $this->getPage()->getClientScript()->registerPradoScript('activefileupload');
if(!$this->getPage()->getIsPostBack() && isset($_GET['TActiveFileUpload_InputId']) && isset($_GET['TActiveFileUpload_TargetId']) && $_GET['TActiveFileUpload_InputId'] == $this->getClientID())
{
@@ -369,6 +368,7 @@ EOS;
parent::addAttributesToRender($writer);
$writer->addAttribute('id',$this->getClientID());
+ $this->getPage()->getClientScript()->registerPradoScript('activefileupload');
$this->getActiveControl()->registerCallbackClientScript($this->getClientClassName(),$this->getClientOptions());
}
diff --git a/framework/Web/UI/ActiveControls/TDraggable.php b/framework/Web/UI/ActiveControls/TDraggable.php
index 10ecf5a5..fccc9328 100755
--- a/framework/Web/UI/ActiveControls/TDraggable.php
+++ b/framework/Web/UI/ActiveControls/TDraggable.php
@@ -145,11 +145,6 @@ class TDraggable extends TPanel
public function onPreRender($param)
{
parent::onPreRender($param);
- $cs=$this->getPage()->getClientScript();
- if ($this->getGhosting()==TDraggableGhostingOptions::SuperGhosting)
- $cs->registerPradoScript('dragdropextra');
- else
- $cs->registerPradoScript('dragdrop');
}
/**
@@ -159,7 +154,12 @@ class TDraggable extends TPanel
protected function addAttributesToRender($writer)
{
parent::addAttributesToRender($writer);
+
$cs=$this->getPage()->getClientScript();
+ if ($this->getGhosting()==TDraggableGhostingOptions::SuperGhosting)
+ $cs->registerPradoScript('dragdropextra');
+ else
+ $cs->registerPradoScript('dragdrop');
$writer->addAttribute('id',$this->getClientID());
$options=TJavascript::encode($this->getPostBackOptions());
$class=$this->getClientClassName();
diff --git a/framework/Web/UI/ActiveControls/TDropContainer.php b/framework/Web/UI/ActiveControls/TDropContainer.php
index daa8469b..072762df 100755
--- a/framework/Web/UI/ActiveControls/TDropContainer.php
+++ b/framework/Web/UI/ActiveControls/TDropContainer.php
@@ -181,7 +181,6 @@ class TDropContainer extends TPanel implements IActiveControl, ICallbackEventHan
public function onPreRender($param)
{
parent::onPreRender($param);
- $this->getPage()->getClientScript()->registerPradoScript('dragdrop');
}
/**
@@ -193,6 +192,7 @@ class TDropContainer extends TPanel implements IActiveControl, ICallbackEventHan
parent::addAttributesToRender($writer);
$writer->addAttribute('id',$this->getClientID());
+ $this->getPage()->getClientScript()->registerPradoScript('dragdrop');
$this->getActiveControl()->registerCallbackClientScript(
$this->getClientClassName(), $this->getPostBackOptions());
}
diff --git a/framework/Web/UI/TClientScriptManager.php b/framework/Web/UI/TClientScriptManager.php
index 3f1664ac..08b528b1 100644
--- a/framework/Web/UI/TClientScriptManager.php
+++ b/framework/Web/UI/TClientScriptManager.php
@@ -87,7 +87,7 @@ class TClientScriptManager extends TApplicationComponent
private $_renderedScriptFiles;
- private $_renderedPradoScripts;
+ private $_expandedPradoScripts;
/**
* Constructor.
@@ -133,7 +133,7 @@ class TClientScriptManager extends TApplicationComponent
/**
* Registers a Prado javascript library to be loaded.
*/
- private function registerPradoScriptInternal($name)
+ protected function registerPradoScriptInternal($name)
{
// $this->checkIfNotInRender();
if(!isset($this->_registeredPradoScripts[$name]))
@@ -146,70 +146,63 @@ class TClientScriptManager extends TApplicationComponent
self::$_pradoPackages = $packages;
}
- if(isset(self::$_pradoScripts[$name]))
+ if (isset(self::$_pradoScripts[$name]))
$this->_registeredPradoScripts[$name]=true;
else
throw new TInvalidOperationException('csmanager_pradoscript_invalid',$name);
- }
- }
-
- /**
- * @return string Prado javascript library base asset url.
- */
- public function getPradoScriptAssetUrl()
- {
- $base = Prado::getFrameworkPath().DIRECTORY_SEPARATOR.self::SCRIPT_PATH;
- $assets = Prado::getApplication()->getAssetManager();
- return $assets->getPublishedUrl($base);
- }
-
- /**
- * Renders the HTML tags for PRADO js files
- * @param THtmlWriter writer
- */
- protected function renderPradoScriptsInt($writer, $initial)
- {
- if($initial) $this->_renderedPradoScripts = array();
- $addedScripts = array_diff($this->_registeredPradoScripts,$this->_renderedPradoScripts);
- if(($packages=array_keys($addedScripts))!==array())
- {
- $base = Prado::getFrameworkPath().DIRECTORY_SEPARATOR.self::SCRIPT_PATH;
- list($path,$baseUrl)=$this->getPackagePathUrl($base);
- $packagesUrl=array();
- $isDebug=$this->getApplication()->getMode()===TApplicationMode::Debug;
- foreach ($packages as $p)
+
+ if(($packages=array_keys($this->_registeredPradoScripts))!==array())
{
- foreach (self::$_pradoScripts[$p] as $dep)
+ $base = Prado::getFrameworkPath().DIRECTORY_SEPARATOR.self::SCRIPT_PATH;
+ list($path,$baseUrl)=$this->getPackagePathUrl($base);
+ $packagesUrl=array();
+ $isDebug=$this->getApplication()->getMode()===TApplicationMode::Debug;
+ foreach ($packages as $p)
{
- foreach (self::$_pradoPackages[$dep] as $script)
+ foreach (self::$_pradoScripts[$p] as $dep)
{
- if($isDebug)
+ foreach (self::$_pradoPackages[$dep] as $script)
+ if (!isset($this->_expandedPradoScripts[$script]))
{
- if (!in_array($url=$baseUrl.'/'.$script,$packagesUrl))
- $packagesUrl[]=$url;
- } else {
- if (!in_array($url=$baseUrl.'/min/'.$script,$packagesUrl))
+ $this->_expandedPradoScripts[$script] = true;
+ if($isDebug)
{
- if(!is_file($filePath=$path.'/min/'.$script))
+ if (!in_array($url=$baseUrl.'/'.$script,$packagesUrl))
+ $packagesUrl[]=$url;
+ } else {
+ if (!in_array($url=$baseUrl.'/min/'.$script,$packagesUrl))
{
- $dirPath=dirname($filePath);
- if(!is_dir($dirPath))
- mkdir($dirPath, PRADO_CHMOD, true);
- file_put_contents($filePath, TJavaScript::JSMin(file_get_contents($base.'/'.$script)));
- chmod($filePath, PRADO_CHMOD);
+ if(!is_file($filePath=$path.'/min/'.$script))
+ {
+ $dirPath=dirname($filePath);
+ if(!is_dir($dirPath))
+ mkdir($dirPath, PRADO_CHMOD, true);
+ file_put_contents($filePath, TJavaScript::JSMin(file_get_contents($base.'/'.$script)));
+ chmod($filePath, PRADO_CHMOD);
+ }
+ $packagesUrl[]=$url;
}
- $packagesUrl[]=$url;
}
}
}
}
+ foreach($packagesUrl as $url)
+ $this->registerScriptFile($url,$url);
}
- $writer->write(TJavaScript::renderScriptFiles($packagesUrl));
- $this->_renderedPradoScripts = $this->_registeredPradoScripts;
}
}
/**
+ * @return string Prado javascript library base asset url.
+ */
+ public function getPradoScriptAssetUrl()
+ {
+ $base = Prado::getFrameworkPath().DIRECTORY_SEPARATOR.self::SCRIPT_PATH;
+ $assets = Prado::getApplication()->getAssetManager();
+ return $assets->getPublishedUrl($base);
+ }
+
+ /**
* Returns the URLs of all script files referenced on the page
* @return array Combined list of all script urls used in the page
*/
@@ -492,10 +485,10 @@ class TClientScriptManager extends TApplicationComponent
* @param string a unique key identifying the file
* @param string URL to the javascript file to be rendered
*/
- public function registerScriptFile($key,$url)
+ public function registerScriptFile($key, $url)
{
$this->_scriptFiles[$key]=$url;
-
+
$params=func_get_args();
$this->_page->registerCachingAction('Page.ClientScript','registerScriptFile',$params);
}
@@ -686,7 +679,6 @@ class TClientScriptManager extends TApplicationComponent
public function renderScriptFilesInt($writer, $initial)
{
if ($initial) $this->_renderedScriptFiles = array();
- $this->renderPradoScriptsInt($writer, $initial);
if(!empty($this->_scriptFiles))
{
$addedScripts = array_diff($this->_scriptFiles,$this->_renderedScriptFiles);
@@ -723,6 +715,16 @@ class TClientScriptManager extends TApplicationComponent
}
/**
+ * Flushes all pending script registrations
+ * @param THtmlWriter writer for the rendering purpose
+ */
+ public function flushScriptFiles($writer)
+ {
+ assert($this->_page->InFormRender);
+ $this->renderScriptFilesInt($writer,false);
+ }
+
+ /**
* @param THtmlWriter writer for the rendering purpose
*/
protected function renderHiddenFieldsInt($writer, $initial)
diff --git a/framework/Web/UI/WebControls/TAccordion.php b/framework/Web/UI/WebControls/TAccordion.php
index 8fd53e29..ba38d14d 100644
--- a/framework/Web/UI/WebControls/TAccordion.php
+++ b/framework/Web/UI/WebControls/TAccordion.php
@@ -415,7 +415,6 @@ class TAccordion extends TWebControl implements IPostBackDataHandler
parent::onPreRender($param);
$this->getActiveView(); // determine the active view
$this->registerStyleSheet();
- $this->registerClientScript();
}
/**
@@ -509,6 +508,12 @@ class TAccordion extends TWebControl implements IPostBackDataHandler
return $this->getControls();
}
+ public function render($writer)
+ {
+ $this->registerClientScript();
+ parent::render($writer);
+ }
+
/**
* Renders body contents of the accordion control.
* @param THtmlWriter the writer used for the rendering purpose.
diff --git a/framework/Web/UI/WebControls/TBaseValidator.php b/framework/Web/UI/WebControls/TBaseValidator.php
index abf959cd..a4307f70 100644
--- a/framework/Web/UI/WebControls/TBaseValidator.php
+++ b/framework/Web/UI/WebControls/TBaseValidator.php
@@ -1,752 +1,751 @@
-<?php
-/**
- * TBaseValidator class file
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright &copy; 2005-2011 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();
- if($control)
- $options['ControlToValidate'] = $control->getClientID();
- $options['ControlCssClass'] = $this->getControlCssClass();
-
- $options['ControlType'] = $this->getClientControlClass($control);
- $options['Enabled'] = $this->getEnabled(true);
-
- //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->registerEndScript($scriptKey, "new Prado.ValidationManager({$options});");
- }
- if($this->getEnableClientScript())
- $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();
- if ($this->getEnableClientScript())
- $this->getPage()->getClientScript()->registerPradoScript('validator');
- }
-
- /**
- * 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',''))==='')
- {
- $target=$this->getValidationTarget();
- /* Workaround: TCheckBoxList and TRadioButtonList nests the actual
- * inputs inside a table; we ensure the first input gets focused
- */
- if($target instanceof TCheckBoxList && $target->getItemCount()>0)
- {
- $id=$target->getClientID().'_c0';
- } else {
- $id=$target->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->onValidate();
- if($this->getVisible(true) && $this->getEnabled(true))
- {
- $target=$this->getValidationTarget();
- // if the target is not a disabled web control
- if($target===null ||
- ($target!==null &&
- !($target instanceof TWebControl && !$target->getEnabled(true))))
- {
- if($this->evaluateIsValid())
- {
- $this->setIsValid(true);
- $this->onValidationSuccess();
- }
- else
- {
- if($target)
- $target->setIsValid(false);
- $this->setIsValid(false);
- $this->onValidationError();
- }
- }
- else
- {
- $this->evaluateIsValid();
- $this->setIsValid(true);
- $this->onValidationSuccess();
- }
- } else {
- $this->setIsValid(true);
- }
- 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';
-}
-
+<?php
+/**
+ * TBaseValidator class file
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005-2011 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();
+ if($control)
+ $options['ControlToValidate'] = $control->getClientID();
+ $options['ControlCssClass'] = $this->getControlCssClass();
+
+ $options['ControlType'] = $this->getClientControlClass($control);
+ $options['Enabled'] = $this->getEnabled(true);
+
+ //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();
+ if ($this->getEnableClientScript())
+ $scripts->registerPradoScript('validator');
+ $formID=$this->getPage()->getForm()->getClientID();
+ $scriptKey = "TBaseValidator:$formID";
+ if($this->getEnableClientScript() && !$scripts->isEndScriptRegistered($scriptKey))
+ {
+ $manager['FormID'] = $formID;
+ $options = TJavaScript::encode($manager);
+ $scripts->registerEndScript($scriptKey, "new Prado.ValidationManager({$options});");
+ }
+ if($this->getEnableClientScript())
+ $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',''))==='')
+ {
+ $target=$this->getValidationTarget();
+ /* Workaround: TCheckBoxList and TRadioButtonList nests the actual
+ * inputs inside a table; we ensure the first input gets focused
+ */
+ if($target instanceof TCheckBoxList && $target->getItemCount()>0)
+ {
+ $id=$target->getClientID().'_c0';
+ } else {
+ $id=$target->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))
+ {
+ $target=$this->getValidationTarget();
+ // if the target is not a disabled web control
+ if($target===null ||
+ ($target!==null &&
+ !($target instanceof TWebControl && !$target->getEnabled(true))))
+ {
+ if($this->evaluateIsValid())
+ {
+ $this->setIsValid(true);
+ $this->onValidationSuccess();
+ }
+ else
+ {
+ if($target)
+ $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/TClientScript.php b/framework/Web/UI/WebControls/TClientScript.php
index 9e2f247d..6eba3d57 100644
--- a/framework/Web/UI/WebControls/TClientScript.php
+++ b/framework/Web/UI/WebControls/TClientScript.php
@@ -1,131 +1,157 @@
-<?php
-/**
- * TClientScript class file
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright &copy; 2005-2011 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Web.UI.WebControls
- */
-
-/**
- * TClientScript class
- *
- * Allows importing of Prado Client Scripts from template via the
- * {@link setPradoScripts PradoScripts} property. Multiple Prado
- * client-scripts can be specified using comma delimited string of the
- * javascript library to include on the page. For example,
- *
- * <code>
- * <com:TClientScript PradoScripts="effects, rico" />
- * </code>
- *
- * 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 in place.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @version $Id$
- * @package System.Web.UI.WebControls
- * @since 3.0
- */
-class TClientScript extends TControl
-{
- /**
- * @return string comma delimited list of javascript libraries to included
- * on the page.
- */
- public function getPradoScripts()
- {
- return $this->getViewState('PradoScripts', '');
- }
-
- /**
- * Include javascript library to the current page. The current supported
- * libraries are: "prado", "effects", "ajax", "validator", "logger",
- * "datepicker", "colorpicker". Library dependencies are automatically resolved.
- *
- * @param string comma delimited list of javascript libraries to include.
- */
- public function setPradoScripts($value)
- {
- $this->setViewState('PradoScripts', $value, '');
- }
-
- /**
- * @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, '');
- }
-
- /**
- * Calls the client script manager to add each of the requested client
- * script libraries.
- * @param mixed event parameter
- */
- public function onPreRender($param)
- {
- parent::onPreRender($param);
- $scripts = preg_split('/,|\s+/', $this->getPradoScripts());
- $cs = $this->getPage()->getClientScript();
- foreach($scripts as $script)
- {
- if(($script = trim($script))!=='')
- $cs->registerPradoScript($script);
- }
- }
-
- /**
- * 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)
- {
- $this->renderCustomScriptFile($writer);
- $this->renderCustomScript($writer);
- }
-
- /**
- * Renders the custom script file.
- * @param THtmLWriter the renderer
- */
- protected function renderCustomScriptFile($writer)
- {
- if(($scriptUrl = $this->getScriptUrl())!=='')
- $writer->write("<script type=\"text/javascript\" src=\"$scriptUrl\"></script>\n");
- }
-
- /**
- * Registers the body content as javascript.
- * @param THtmlWriter the renderer
- */
- protected function renderCustomScript($writer)
- {
- if($this->getHasControls())
- {
- $writer->write("<script type=\"text/javascript\">\n/*<![CDATA[*/\n");
- $this->renderChildren($writer);
- $writer->write("\n/*]]>*/\n</script>\n");
- }
- }
-}
-
+<?php
+/**
+ * TClientScript class file
+ *
+ * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005-2011 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @package System.Web.UI.WebControls
+ */
+
+/**
+ * TClientScript class
+ *
+ * Allows importing of Prado Client Scripts from template via the
+ * {@link setPradoScripts PradoScripts} property. Multiple Prado
+ * client-scripts can be specified using comma delimited string of the
+ * javascript library to include on the page. For example,
+ *
+ * <code>
+ * <com:TClientScript PradoScripts="effects, rico" />
+ * </code>
+ *
+ * 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 in place.
+ *
+ * Since Prado 3.2 the property {@link setFlushScriptFiles FlushScriptFiles} controls
+ * whether Prado will flush the script files defined in the page before rendering the
+ * TClientScript contents.
+ * If you're not using any external functions in your TClientScript block, you should
+ * set the {@link setFlushScriptFiles FlushScriptFiles} property to false, so Prado
+ * can postpone the loading of all the referenced script files further down the page
+ * generation cycle.
+ *
+ * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
+ * @version $Id$
+ * @package System.Web.UI.WebControls
+ * @since 3.0
+ */
+class TClientScript extends TControl
+{
+ /**
+ * @return string comma delimited list of javascript libraries to included
+ * on the page.
+ */
+ public function getPradoScripts()
+ {
+ return $this->getViewState('PradoScripts', '');
+ }
+
+ /**
+ * Include javascript library to the current page. The current supported
+ * libraries are: "prado", "effects", "ajax", "validator", "logger",
+ * "datepicker", "colorpicker". Library dependencies are automatically resolved.
+ *
+ * @param string comma delimited list of javascript libraries to include.
+ */
+ public function setPradoScripts($value)
+ {
+ $this->setViewState('PradoScripts', $value, '');
+ }
+
+ /**
+ * @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, '');
+ }
+
+ /**
+ * @return bool whether to flush script files using TClientScriptManager::flushScriptFiles() before rendering the script block
+ */
+ public function getFlushScriptFiles()
+ {
+ return TPropertyValue::ensureBoolean($this->getViewState('FlushScriptFiles', true));
+ }
+
+ /**
+ * @param bool whether to flush script files using TClientScriptManager::flushScriptFiles() before rendering the script block
+ */
+ public function setFlushScriptFiles($value)
+ {
+ $this->setViewState('FlushScriptFiles', TPropertyValue::ensureBoolean($value));
+ }
+
+ /**
+ * Calls the client script manager to add each of the requested client
+ * script libraries.
+ * @param mixed event parameter
+ */
+ public function onPreRender($param)
+ {
+ parent::onPreRender($param);
+ $scripts = preg_split('/,|\s+/', $this->getPradoScripts());
+ $cs = $this->getPage()->getClientScript();
+ foreach($scripts as $script)
+ {
+ if(($script = trim($script))!=='')
+ $cs->registerPradoScript($script);
+ }
+ }
+
+ /**
+ * 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->getFlushScriptFiles())
+ $this->getPage()->getClientScript()->flushScriptFiles($writer);
+ $this->renderCustomScriptFile($writer);
+ $this->renderCustomScript($writer);
+ }
+
+ /**
+ * Renders the custom script file.
+ * @param THtmLWriter the renderer
+ */
+ protected function renderCustomScriptFile($writer)
+ {
+ if(($scriptUrl = $this->getScriptUrl())!=='')
+ $writer->write("<script type=\"text/javascript\" src=\"$scriptUrl\"></script>\n");
+ }
+
+ /**
+ * Registers the body content as javascript.
+ * @param THtmlWriter the renderer
+ */
+ protected function renderCustomScript($writer)
+ {
+ if($this->getHasControls())
+ {
+ $writer->write("<script type=\"text/javascript\">\n/*<![CDATA[*/\n");
+ $this->renderChildren($writer);
+ $writer->write("\n/*]]>*/\n</script>\n");
+ }
+ }
+}
+
diff --git a/framework/Web/UI/WebControls/THtmlArea.php b/framework/Web/UI/WebControls/THtmlArea.php
index f2caa303..7844a131 100644
--- a/framework/Web/UI/WebControls/THtmlArea.php
+++ b/framework/Web/UI/WebControls/THtmlArea.php
@@ -1,546 +1,535 @@
-<?php
-/**
- * THtmlArea class file.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright &copy; 2005-2011 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Web.UI.WebControls
- */
-
-/**
- * Includes TTextBox class
- */
-Prado::using('System.Web.UI.WebControls.TTextBox');
-
-/**
- * THtmlArea class
- *
- * THtmlArea wraps the visual editting functionalities provided by the
- * TinyMCE project {@link http://tinymce.moxiecode.com/}.
- *
- * THtmlArea displays a WYSIWYG text area on the Web page for user input
- * in the HTML format. The text displayed in the THtmlArea component is
- * specified or determined by using the <b>Text</b> property.
- *
- * To enable the visual editting on the client side, set the property
- * <b>EnableVisualEdit</b> to true (which is default value).
- * To set the size of the editor when the visual editting is enabled,
- * set the <b>Width</b> and <b>Height</b> properties instead of
- * <b>Columns</b> and <b>Rows</b> because the latter has no meaning
- * under the situation.
- *
- * The default editor gives only the basic tool bar. To change or add
- * additional tool bars, use the {@link setOptions Options} property to add additional
- * editor options with each options on a new line.
- * See http://tinymce.moxiecode.com/tinymce/docs/index.html
- * for a list of options. The options can be change/added as shown in the
- * following example.
- * <code>
- * <com:THtmlArea>
- * <prop:Options>
- * plugins : "contextmenu,paste"
- * language : "zh_cn"
- * </prop:Options>
- * </com:THtmlArea>
- * </code>
- *
- * Compatibility
- * The client-side visual editting capability is supported by
- * Internet Explorer 5.0+ for Windows and Gecko-based browser.
- * If the browser does not support the visual editting,
- * a traditional textarea will be displayed.
- *
- * Browser support
- *
- * <code>
- * Windows XP MacOS X 10.4
- * ----------------------------------------------------
- * MSIE 6 OK
- * MSIE 5.5 SP2 OK
- * MSIE 5.0 OK
- * Mozilla 1.7.x OK OK
- * Firefox 1.0.x OK OK
- * Firefox 1.5b2 OK OK
- * Safari 2.0 (412) OK(1)
- * Opera 9 Preview 1 OK(1) OK(1)
- * ----------------------------------------------------
- * * (1) - Partialy working
- * ----------------------------------------------------
- * </code>
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @version $Id$
- * @package System.Web.UI.WebControls
- * @since 3.0
- */
-class THtmlArea extends TTextBox
-{
- /**
- * @var array list of locale => language file pairs.
- */
- private static $_langs = array(
- 'ar' => 'ar',
- 'az' => 'az',
- 'be' => 'be',
- 'bg' => 'bg',
- 'bn' => 'bn',
- 'br' => 'br',
- 'bs' => 'bs',
- 'ca' => 'ca',
- 'ch' => 'ch',
- 'cn' => 'cn',
- 'cs' => 'cs',
- 'cy' => 'cy',
- 'da' => 'da',
- 'de' => 'de',
- 'dv' => 'dv',
- 'el' => 'el',
- 'en' => 'en',
- 'eo' => 'eo',
- 'es' => 'es',
- 'et' => 'et',
- 'eu' => 'eu',
- 'fa' => 'fa',
- 'fi' => 'fi',
- 'fr' => 'fr',
- 'gl' => 'gl',
- 'gu' => 'gu',
- 'he' => 'he',
- 'hi' => 'hi',
- 'hr' => 'hr',
- 'hu' => 'hu',
- 'hy' => 'hy',
- 'ia' => 'ia',
- 'id' => 'id',
- 'is' => 'is',
- 'it' => 'it',
- 'ja' => 'ja',
- 'ka' => 'ka',
- 'kl' => 'kl',
- 'km' => 'km',
- 'ko' => 'ko',
- 'lb' => 'lb',
- 'lt' => 'lt',
- 'lv' => 'lv',
- 'mk' => 'mk',
- 'ml' => 'ml',
- 'mn' => 'mn',
- 'ms' => 'ms',
- 'my' => 'my',
- 'nb' => 'nb',
- 'nl' => 'nl',
- 'nn' => 'nn',
- 'no' => 'no',
- 'pl' => 'pl',
- 'ps' => 'ps',
- 'pt' => 'pt',
- 'ro' => 'ro',
- 'ru' => 'ru',
- 'sc' => 'sc',
- 'se' => 'se',
- 'si' => 'si',
- 'sk' => 'sk',
- 'sl' => 'sl',
- 'sq' => 'sq',
- 'sr' => 'sr',
- 'sv' => 'sv',
- 'ta' => 'ta',
- 'te' => 'te',
- 'th' => 'th',
- 'tn' => 'tn',
- 'tr' => 'tr',
- 'tt' => 'tt',
- 'tw' => 'tw',
- 'uk' => 'vi',
- 'ur' => 'vi',
- 'vi' => 'vi',
- 'zh_CN' => 'zh-cn',
- 'zh_TW' => 'zh-tw',
- 'zh' => 'zh',
- 'zu' => 'zu',
- );
-
- /**
- * @var array list of default plugins to load, override using getAvailablePlugins();
- */
- private static $_plugins = array(
- 'advhr',
- 'advimage',
- 'advlink',
- 'advlist',
- 'autolink',
- 'autoresize',
- 'autosave',
- 'bbcode',
- 'contextmenu',
- 'directionality',
- 'emotions',
- 'example',
- 'fullpage',
- 'fullscreen',
- 'iespell',
- 'inlinepopups',
- 'insertdatetime',
- 'layer',
- 'legacyoutput',
- 'lists',
- 'media',
- 'nonbreaking',
- 'noneditable',
- 'pagebreak',
- 'paste',
- 'preview',
- 'print',
- 'save',
- 'searchreplace',
- 'spellchecker',
- 'style',
- 'tabfocus',
- 'table',
- 'template',
- 'visualchars',
- 'wordc',
- 'wordcount',
- 'xhtmlxtras'
- );
-
- /**
- * @var array default themes to load
- */
- private static $_themes = array(
- 'simple',
- 'advanced'
- );
-
- /**
- * Constructor.
- * Sets default width and height.
- */
- public function __construct()
- {
- $this->setWidth('470px');
- $this->setHeight('250px');
- }
-
- /**
- * Overrides the parent implementation.
- * TextMode for THtmlArea control is always 'MultiLine'
- * @return string the behavior mode of the THtmlArea component.
- */
- public function getTextMode()
- {
- return 'MultiLine';
- }
-
- /**
- * Overrides the parent implementation.
- * TextMode for THtmlArea is always 'MultiLine' and cannot be changed to others.
- * @param string the text mode
- */
- public function setTextMode($value)
- {
- throw new TInvalidOperationException("htmlarea_textmode_readonly");
- }
-
- /**
- * @return boolean whether change of the content should cause postback. Return false if EnableVisualEdit is true.
- */
- public function getAutoPostBack()
- {
- return $this->getEnableVisualEdit() ? false : parent::getAutoPostBack();
- }
-
- /**
- * @return boolean whether to show WYSIWYG text editor. Defaults to true.
- */
- public function getEnableVisualEdit()
- {
- return $this->getViewState('EnableVisualEdit',true);
- }
-
- /**
- * Sets whether to show WYSIWYG text editor.
- * @param boolean whether to show WYSIWYG text editor
- */
- public function setEnableVisualEdit($value)
- {
- $this->setViewState('EnableVisualEdit',TPropertyValue::ensureBoolean($value),true);
- }
-
- /**
- * Gets the current culture.
- * @return string current culture, e.g. en_AU.
- */
- public function getCulture()
- {
- return $this->getViewState('Culture', '');
- }
-
- /**
- * Sets the culture/language for the html area
- * @param string a culture string, e.g. en_AU.
- */
- public function setCulture($value)
- {
- $this->setViewState('Culture', $value, '');
- }
-
- /**
- * Gets the list of options for the WYSIWYG (TinyMCE) editor
- * @see http://tinymce.moxiecode.com/tinymce/docs/index.html
- * @return string options
- */
- public function getOptions()
- {
- return $this->getViewState('Options', '');
- }
-
- /**
- * Sets the list of options for the WYSIWYG (TinyMCE) editor
- * @see http://tinymce.moxiecode.com/tinymce/docs/index.html
- * @param string options
- */
- public function setOptions($value)
- {
- $this->setViewState('Options', $value, '');
- }
-
- /**
- * @param string path to custom plugins to be copied.
- */
- public function setCustomPluginPath($value)
- {
- $this->setViewState('CustomPluginPath', $value);
- }
-
- /**
- * @return string path to custom plugins to be copied.
- */
- public function getCustomPluginPath()
- {
- return $this->getViewState('CustomPluginPath');
- }
-
- /**
- * @return boolean enable compression of the javascript files, default is true.
- */
- public function getEnableCompression()
- {
- return $this->getViewState('EnableCompression', true);
- }
-
- /**
- * @param boolean enable compression of the javascript files, default is true.
- */
- public function setEnableCompression($value)
- {
- $this->setViewState('EnableCompression', TPropertyValue::ensureBoolean($value));
- }
-
- /**
- * Registers clientscripts
- *
- * This method overrides the parent implementation and is invoked before render.
- * @param mixed event parameter
- */
- public function onPreRender($param)
- {
- parent::onPreRender($param);
- $this->loadJavascriptLibrary();
- }
-
- /**
- * Adds attribute name-value pairs to renderer.
- * This method overrides the parent implementation by registering
- * additional javacript code.
- * @param THtmlWriter the writer used for the rendering purpose
- */
- protected function addAttributesToRender($writer)
- {
- if($this->getEnableVisualEdit() && $this->getEnabled(true))
- {
- $writer->addAttribute('id',$this->getClientID());
- $this->registerEditorClientScript($writer);
- }
-
- parent::addAttributesToRender($writer);
- }
-
- /**
- * Returns a list of plugins to be loaded.
- * Override this method to customize.
- * @return array list of plugins to be loaded
- */
- public function getAvailablePlugins()
- {
- return self::$_plugins;
- }
-
- /**
- * @return array list of available themese
- */
- public function getAvailableThemes()
- {
- return self::$_themes;
- }
-
- protected function getCompressionOptions()
- {
- return array(
- 'plugins' => implode(',', $this->getAvailablePlugins()),
- 'themes' => implode(',', $this->getAvailableThemes()),
- 'languages' => $this->getLanguageSuffix($this->getCulture()),
- 'disk_cache' => true,
- 'debug' => false
- );
- }
-
- protected function loadJavascriptLibrary()
- {
- $scripts = $this->getPage()->getClientScript();
- $scripts->registerPradoScript('htmlarea');
- $scripts->registerScriptFile('prado:THtmlArea', $this->getScriptUrl());
- }
-
- /**
- * Registers the editor javascript file and code to initialize the editor.
- */
- protected function registerEditorClientScript($writer)
- {
- $scripts = $this->getPage()->getClientScript();
- $options = array(
- 'EditorOptions' => $this->getEditorOptions()
- );
- if($this->getEnableCompression())
- $options['CompressionOptions'] = $this->getCompressionOptions();
-
- $options = TJavaScript::encode($options,true,true);
- $script = "new Prado.WebUI.THtmlArea($options)";
- $scripts->registerEndScript('prado:THtmlArea'.$this->ClientID,$script);
- }
-
- /**
- * @return string editor script URL.
- */
- protected function getScriptUrl()
- {
- if($this->getEnableCompression())
- return $this->getScriptDeploymentPath().'/tiny_mce/tiny_mce_gzip.js';
- else
- return $this->getScriptDeploymentPath().'/tiny_mce/tiny_mce.js';
- }
-
- /**
- * Gets the editor script base URL by publishing the tarred source via TTarAssetManager.
- * @return string URL base path to the published editor script
- */
- protected function getScriptDeploymentPath()
- {
- $tarfile = Prado::getPathOfNamespace('System.3rdParty.TinyMCE.tiny_mce', '.tar');
- $md5sum = Prado::getPathOfNamespace('System.3rdParty.TinyMCE.tiny_mce', '.md5');
- if($tarfile===null || $md5sum===null)
- throw new TConfigurationException('htmlarea_tarfile_invalid');
- $url = $this->getApplication()->getAssetManager()->publishTarFile($tarfile, $md5sum);
- $this->copyCustomPlugins($url);
- return $url;
- }
-
- protected function copyCustomPlugins($url)
- {
- if($plugins = $this->getCustomPluginPath())
- {
- $assets = $this->getApplication()->getAssetManager();
- $path = is_dir($plugins) ? $plugins : Prado::getPathOfNameSpace($plugins);
- $dest = $assets->getBasePath().'/'.basename($url).'/tiny_mce/plugins/';
- if(!is_dir($dest) || $this->getApplication()->getMode()!==TApplicationMode::Performance)
- $assets->copyDirectory($path, $dest);
- }
- }
-
- /**
- * Default editor options gives basic tool bar only.
- * @return array editor initialization options.
- */
- protected function getEditorOptions()
- {
- $options['mode'] = 'exact';
- $options['elements'] = $this->getClientID();
- $options['language'] = $this->getLanguageSuffix($this->getCulture());
- $options['theme'] = 'advanced';
-
- //make it basic advanced to fit into 1 line of buttons.
- //$options['theme_advanced_buttons1'] = 'bold,italic,underline,strikethrough,separator,justifyleft,justifycenter,justifyright, justifyfull,separator,bullist,numlist,separator,undo,redo,separator,link,unlink,separator,charmap,separator,code,help';
- //$options['theme_advanced_buttons2'] = ' ';
- $options['theme_advanced_buttons1'] = 'formatselect,fontselect,fontsizeselect,separator,bold,italic,underline,strikethrough,sub,sup';
- $options['theme_advanced_buttons2'] = 'justifyleft,justifycenter,justifyright,justifyfull,separator,bullist,numlist,separator,outdent,indent,separator,forecolor,backcolor,separator,hr,link,unlink,image,charmap,separator,removeformat,code,help';
- $options['theme_advanced_buttons3'] = '';
-
- $options['theme_advanced_toolbar_location'] = 'top';
- $options['theme_advanced_toolbar_align'] = 'left';
- $options['theme_advanced_path_location'] = 'bottom';
- $options['extended_valid_elements'] = 'a[name|href|target|title|onclick],img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name],hr[class|width|size|noshade],font[face|size|color|style],span[class|align|style]';
-
- $options = array_merge($options, $this->parseEditorOptions($this->getOptions()));
- return $options;
- }
-
- /**
- * Parse additional options set in the Options property.
- * @return array additional custom options
- */
- protected function parseEditorOptions($string)
- {
- $options = array();
- $substrings = preg_split('/,\s*\n|\n/', trim($string));
- foreach($substrings as $bits)
- {
- $option = explode(":",$bits,2);
-
- if(count($option) == 2)
- {
- $value=trim(trim($option[1]),"'\"");
- if (($s=strtolower($value))==='false')
- $value=false;
- elseif ($s==='true')
- $value=true;
- $options[trim($option[0])] = $value;
- }
- }
- return $options;
- }
-
- /**
- * @return string localized editor interface language extension.
- */
- protected function getLanguageSuffix($culture)
- {
- $app = $this->getApplication()->getGlobalization();
- if(empty($culture) && ($app!==null))
- $culture = $app->getCulture();
- $variants = array();
- if($app!==null)
- $variants = $app->getCultureVariants($culture);
-
- foreach($variants as $variant)
- {
- if(isset(self::$_langs[$variant]))
- return self::$_langs[$variant];
- }
-
- return 'en';
- }
-
- /**
- * Gets the name of the javascript class responsible for performing postback for this control.
- * This method overrides the parent implementation.
- * @return string the javascript class name
- */
- protected function getClientClassName()
- {
- return 'Prado.WebUI.THtmlArea';
- }
-}
-
+<?php
+/**
+ * THtmlArea class file.
+ *
+ * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005-2011 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @package System.Web.UI.WebControls
+ */
+
+/**
+ * Includes TTextBox class
+ */
+Prado::using('System.Web.UI.WebControls.TTextBox');
+
+/**
+ * THtmlArea class
+ *
+ * THtmlArea wraps the visual editting functionalities provided by the
+ * TinyMCE project {@link http://tinymce.moxiecode.com/}.
+ *
+ * THtmlArea displays a WYSIWYG text area on the Web page for user input
+ * in the HTML format. The text displayed in the THtmlArea component is
+ * specified or determined by using the <b>Text</b> property.
+ *
+ * To enable the visual editting on the client side, set the property
+ * <b>EnableVisualEdit</b> to true (which is default value).
+ * To set the size of the editor when the visual editting is enabled,
+ * set the <b>Width</b> and <b>Height</b> properties instead of
+ * <b>Columns</b> and <b>Rows</b> because the latter has no meaning
+ * under the situation.
+ *
+ * The default editor gives only the basic tool bar. To change or add
+ * additional tool bars, use the {@link setOptions Options} property to add additional
+ * editor options with each options on a new line.
+ * See http://tinymce.moxiecode.com/tinymce/docs/index.html
+ * for a list of options. The options can be change/added as shown in the
+ * following example.
+ * <code>
+ * <com:THtmlArea>
+ * <prop:Options>
+ * plugins : "contextmenu,paste"
+ * language : "zh_cn"
+ * </prop:Options>
+ * </com:THtmlArea>
+ * </code>
+ *
+ * Compatibility
+ * The client-side visual editting capability is supported by
+ * Internet Explorer 5.0+ for Windows and Gecko-based browser.
+ * If the browser does not support the visual editting,
+ * a traditional textarea will be displayed.
+ *
+ * Browser support
+ *
+ * <code>
+ * Windows XP MacOS X 10.4
+ * ----------------------------------------------------
+ * MSIE 6 OK
+ * MSIE 5.5 SP2 OK
+ * MSIE 5.0 OK
+ * Mozilla 1.7.x OK OK
+ * Firefox 1.0.x OK OK
+ * Firefox 1.5b2 OK OK
+ * Safari 2.0 (412) OK(1)
+ * Opera 9 Preview 1 OK(1) OK(1)
+ * ----------------------------------------------------
+ * * (1) - Partialy working
+ * ----------------------------------------------------
+ * </code>
+ *
+ * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
+ * @version $Id$
+ * @package System.Web.UI.WebControls
+ * @since 3.0
+ */
+class THtmlArea extends TTextBox
+{
+ /**
+ * @var array list of locale => language file pairs.
+ */
+ private static $_langs = array(
+ 'ar' => 'ar',
+ 'az' => 'az',
+ 'be' => 'be',
+ 'bg' => 'bg',
+ 'bn' => 'bn',
+ 'br' => 'br',
+ 'bs' => 'bs',
+ 'ca' => 'ca',
+ 'ch' => 'ch',
+ 'cn' => 'cn',
+ 'cs' => 'cs',
+ 'cy' => 'cy',
+ 'da' => 'da',
+ 'de' => 'de',
+ 'dv' => 'dv',
+ 'el' => 'el',
+ 'en' => 'en',
+ 'eo' => 'eo',
+ 'es' => 'es',
+ 'et' => 'et',
+ 'eu' => 'eu',
+ 'fa' => 'fa',
+ 'fi' => 'fi',
+ 'fr' => 'fr',
+ 'gl' => 'gl',
+ 'gu' => 'gu',
+ 'he' => 'he',
+ 'hi' => 'hi',
+ 'hr' => 'hr',
+ 'hu' => 'hu',
+ 'hy' => 'hy',
+ 'ia' => 'ia',
+ 'id' => 'id',
+ 'is' => 'is',
+ 'it' => 'it',
+ 'ja' => 'ja',
+ 'ka' => 'ka',
+ 'kl' => 'kl',
+ 'km' => 'km',
+ 'ko' => 'ko',
+ 'lb' => 'lb',
+ 'lt' => 'lt',
+ 'lv' => 'lv',
+ 'mk' => 'mk',
+ 'ml' => 'ml',
+ 'mn' => 'mn',
+ 'ms' => 'ms',
+ 'my' => 'my',
+ 'nb' => 'nb',
+ 'nl' => 'nl',
+ 'nn' => 'nn',
+ 'no' => 'no',
+ 'pl' => 'pl',
+ 'ps' => 'ps',
+ 'pt' => 'pt',
+ 'ro' => 'ro',
+ 'ru' => 'ru',
+ 'sc' => 'sc',
+ 'se' => 'se',
+ 'si' => 'si',
+ 'sk' => 'sk',
+ 'sl' => 'sl',
+ 'sq' => 'sq',
+ 'sr' => 'sr',
+ 'sv' => 'sv',
+ 'ta' => 'ta',
+ 'te' => 'te',
+ 'th' => 'th',
+ 'tn' => 'tn',
+ 'tr' => 'tr',
+ 'tt' => 'tt',
+ 'tw' => 'tw',
+ 'uk' => 'vi',
+ 'ur' => 'vi',
+ 'vi' => 'vi',
+ 'zh_CN' => 'zh-cn',
+ 'zh_TW' => 'zh-tw',
+ 'zh' => 'zh',
+ 'zu' => 'zu',
+ );
+
+ /**
+ * @var array list of default plugins to load, override using getAvailablePlugins();
+ */
+ private static $_plugins = array(
+ 'advhr',
+ 'advimage',
+ 'advlink',
+ 'advlist',
+ 'autolink',
+ 'autoresize',
+ 'autosave',
+ 'bbcode',
+ 'contextmenu',
+ 'directionality',
+ 'emotions',
+ 'example',
+ 'fullpage',
+ 'fullscreen',
+ 'iespell',
+ 'inlinepopups',
+ 'insertdatetime',
+ 'layer',
+ 'legacyoutput',
+ 'lists',
+ 'media',
+ 'nonbreaking',
+ 'noneditable',
+ 'pagebreak',
+ 'paste',
+ 'preview',
+ 'print',
+ 'save',
+ 'searchreplace',
+ 'spellchecker',
+ 'style',
+ 'tabfocus',
+ 'table',
+ 'template',
+ 'visualchars',
+ 'wordc',
+ 'wordcount',
+ 'xhtmlxtras'
+ );
+
+ /**
+ * @var array default themes to load
+ */
+ private static $_themes = array(
+ 'simple',
+ 'advanced'
+ );
+
+ /**
+ * Constructor.
+ * Sets default width and height.
+ */
+ public function __construct()
+ {
+ $this->setWidth('470px');
+ $this->setHeight('250px');
+ }
+
+ /**
+ * Overrides the parent implementation.
+ * TextMode for THtmlArea control is always 'MultiLine'
+ * @return string the behavior mode of the THtmlArea component.
+ */
+ public function getTextMode()
+ {
+ return 'MultiLine';
+ }
+
+ /**
+ * Overrides the parent implementation.
+ * TextMode for THtmlArea is always 'MultiLine' and cannot be changed to others.
+ * @param string the text mode
+ */
+ public function setTextMode($value)
+ {
+ throw new TInvalidOperationException("htmlarea_textmode_readonly");
+ }
+
+ /**
+ * @return boolean whether change of the content should cause postback. Return false if EnableVisualEdit is true.
+ */
+ public function getAutoPostBack()
+ {
+ return $this->getEnableVisualEdit() ? false : parent::getAutoPostBack();
+ }
+
+ /**
+ * @return boolean whether to show WYSIWYG text editor. Defaults to true.
+ */
+ public function getEnableVisualEdit()
+ {
+ return $this->getViewState('EnableVisualEdit',true);
+ }
+
+ /**
+ * Sets whether to show WYSIWYG text editor.
+ * @param boolean whether to show WYSIWYG text editor
+ */
+ public function setEnableVisualEdit($value)
+ {
+ $this->setViewState('EnableVisualEdit',TPropertyValue::ensureBoolean($value),true);
+ }
+
+ /**
+ * Gets the current culture.
+ * @return string current culture, e.g. en_AU.
+ */
+ public function getCulture()
+ {
+ return $this->getViewState('Culture', '');
+ }
+
+ /**
+ * Sets the culture/language for the html area
+ * @param string a culture string, e.g. en_AU.
+ */
+ public function setCulture($value)
+ {
+ $this->setViewState('Culture', $value, '');
+ }
+
+ /**
+ * Gets the list of options for the WYSIWYG (TinyMCE) editor
+ * @see http://tinymce.moxiecode.com/tinymce/docs/index.html
+ * @return string options
+ */
+ public function getOptions()
+ {
+ return $this->getViewState('Options', '');
+ }
+
+ /**
+ * Sets the list of options for the WYSIWYG (TinyMCE) editor
+ * @see http://tinymce.moxiecode.com/tinymce/docs/index.html
+ * @param string options
+ */
+ public function setOptions($value)
+ {
+ $this->setViewState('Options', $value, '');
+ }
+
+ /**
+ * @param string path to custom plugins to be copied.
+ */
+ public function setCustomPluginPath($value)
+ {
+ $this->setViewState('CustomPluginPath', $value);
+ }
+
+ /**
+ * @return string path to custom plugins to be copied.
+ */
+ public function getCustomPluginPath()
+ {
+ return $this->getViewState('CustomPluginPath');
+ }
+
+ /**
+ * @return boolean enable compression of the javascript files, default is true.
+ */
+ public function getEnableCompression()
+ {
+ return $this->getViewState('EnableCompression', true);
+ }
+
+ /**
+ * @param boolean enable compression of the javascript files, default is true.
+ */
+ public function setEnableCompression($value)
+ {
+ $this->setViewState('EnableCompression', TPropertyValue::ensureBoolean($value));
+ }
+
+ /**
+ * Adds attribute name-value pairs to renderer.
+ * This method overrides the parent implementation by registering
+ * additional javacript code.
+ * @param THtmlWriter the writer used for the rendering purpose
+ */
+ protected function addAttributesToRender($writer)
+ {
+ if($this->getEnableVisualEdit() && $this->getEnabled(true))
+ {
+ $writer->addAttribute('id',$this->getClientID());
+ $this->registerEditorClientScript($writer);
+ }
+
+ parent::addAttributesToRender($writer);
+ }
+
+ /**
+ * Returns a list of plugins to be loaded.
+ * Override this method to customize.
+ * @return array list of plugins to be loaded
+ */
+ public function getAvailablePlugins()
+ {
+ return self::$_plugins;
+ }
+
+ /**
+ * @return array list of available themese
+ */
+ public function getAvailableThemes()
+ {
+ return self::$_themes;
+ }
+
+ protected function getCompressionOptions()
+ {
+ return array(
+ 'plugins' => implode(',', $this->getAvailablePlugins()),
+ 'themes' => implode(',', $this->getAvailableThemes()),
+ 'languages' => $this->getLanguageSuffix($this->getCulture()),
+ 'disk_cache' => true,
+ 'debug' => false
+ );
+ }
+
+ protected function loadJavascriptLibrary()
+ {
+ $scripts = $this->getPage()->getClientScript();
+ $scripts->registerPradoScript('htmlarea');
+ $scripts->registerScriptFile('prado:THtmlArea', $this->getScriptUrl());
+ }
+
+ /**
+ * Registers the editor javascript file and code to initialize the editor.
+ */
+ protected function registerEditorClientScript($writer)
+ {
+ $this->loadJavascriptLibrary();
+ $scripts = $this->getPage()->getClientScript();
+ $options = array(
+ 'EditorOptions' => $this->getEditorOptions()
+ );
+ if($this->getEnableCompression())
+ $options['CompressionOptions'] = $this->getCompressionOptions();
+
+ $options = TJavaScript::encode($options,true,true);
+ $script = "new Prado.WebUI.THtmlArea($options)";
+ $scripts->registerEndScript('prado:THtmlArea'.$this->ClientID,$script);
+ }
+
+ /**
+ * @return string editor script URL.
+ */
+ protected function getScriptUrl()
+ {
+ if($this->getEnableCompression())
+ return $this->getScriptDeploymentPath().'/tiny_mce/tiny_mce_gzip.js';
+ else
+ return $this->getScriptDeploymentPath().'/tiny_mce/tiny_mce.js';
+ }
+
+ /**
+ * Gets the editor script base URL by publishing the tarred source via TTarAssetManager.
+ * @return string URL base path to the published editor script
+ */
+ protected function getScriptDeploymentPath()
+ {
+ $tarfile = Prado::getPathOfNamespace('System.3rdParty.TinyMCE.tiny_mce', '.tar');
+ $md5sum = Prado::getPathOfNamespace('System.3rdParty.TinyMCE.tiny_mce', '.md5');
+ if($tarfile===null || $md5sum===null)
+ throw new TConfigurationException('htmlarea_tarfile_invalid');
+ $url = $this->getApplication()->getAssetManager()->publishTarFile($tarfile, $md5sum);
+ $this->copyCustomPlugins($url);
+ return $url;
+ }
+
+ protected function copyCustomPlugins($url)
+ {
+ if($plugins = $this->getCustomPluginPath())
+ {
+ $assets = $this->getApplication()->getAssetManager();
+ $path = is_dir($plugins) ? $plugins : Prado::getPathOfNameSpace($plugins);
+ $dest = $assets->getBasePath().'/'.basename($url).'/tiny_mce/plugins/';
+ if(!is_dir($dest) || $this->getApplication()->getMode()!==TApplicationMode::Performance)
+ $assets->copyDirectory($path, $dest);
+ }
+ }
+
+ /**
+ * Default editor options gives basic tool bar only.
+ * @return array editor initialization options.
+ */
+ protected function getEditorOptions()
+ {
+ $options['mode'] = 'exact';
+ $options['elements'] = $this->getClientID();
+ $options['language'] = $this->getLanguageSuffix($this->getCulture());
+ $options['theme'] = 'advanced';
+
+ //make it basic advanced to fit into 1 line of buttons.
+ //$options['theme_advanced_buttons1'] = 'bold,italic,underline,strikethrough,separator,justifyleft,justifycenter,justifyright, justifyfull,separator,bullist,numlist,separator,undo,redo,separator,link,unlink,separator,charmap,separator,code,help';
+ //$options['theme_advanced_buttons2'] = ' ';
+ $options['theme_advanced_buttons1'] = 'formatselect,fontselect,fontsizeselect,separator,bold,italic,underline,strikethrough,sub,sup';
+ $options['theme_advanced_buttons2'] = 'justifyleft,justifycenter,justifyright,justifyfull,separator,bullist,numlist,separator,outdent,indent,separator,forecolor,backcolor,separator,hr,link,unlink,image,charmap,separator,removeformat,code,help';
+ $options['theme_advanced_buttons3'] = '';
+
+ $options['theme_advanced_toolbar_location'] = 'top';
+ $options['theme_advanced_toolbar_align'] = 'left';
+ $options['theme_advanced_path_location'] = 'bottom';
+ $options['extended_valid_elements'] = 'a[name|href|target|title|onclick],img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name],hr[class|width|size|noshade],font[face|size|color|style],span[class|align|style]';
+
+ $options = array_merge($options, $this->parseEditorOptions($this->getOptions()));
+ return $options;
+ }
+
+ /**
+ * Parse additional options set in the Options property.
+ * @return array additional custom options
+ */
+ protected function parseEditorOptions($string)
+ {
+ $options = array();
+ $substrings = preg_split('/,\s*\n|\n/', trim($string));
+ foreach($substrings as $bits)
+ {
+ $option = explode(":",$bits,2);
+
+ if(count($option) == 2)
+ {
+ $value=trim(trim($option[1]),"'\"");
+ if (($s=strtolower($value))==='false')
+ $value=false;
+ elseif ($s==='true')
+ $value=true;
+ $options[trim($option[0])] = $value;
+ }
+ }
+ return $options;
+ }
+
+ /**
+ * @return string localized editor interface language extension.
+ */
+ protected function getLanguageSuffix($culture)
+ {
+ $app = $this->getApplication()->getGlobalization();
+ if(empty($culture) && ($app!==null))
+ $culture = $app->getCulture();
+ $variants = array();
+ if($app!==null)
+ $variants = $app->getCultureVariants($culture);
+
+ foreach($variants as $variant)
+ {
+ if(isset(self::$_langs[$variant]))
+ return self::$_langs[$variant];
+ }
+
+ return 'en';
+ }
+
+ /**
+ * Gets the name of the javascript class responsible for performing postback for this control.
+ * This method overrides the parent implementation.
+ * @return string the javascript class name
+ */
+ protected function getClientClassName()
+ {
+ return 'Prado.WebUI.THtmlArea';
+ }
+}
+
diff --git a/framework/Web/UI/WebControls/TTabPanel.php b/framework/Web/UI/WebControls/TTabPanel.php
index fd20b949..a79835ed 100644
--- a/framework/Web/UI/WebControls/TTabPanel.php
+++ b/framework/Web/UI/WebControls/TTabPanel.php
@@ -1,728 +1,731 @@
-<?php
-/**
- * TTabPanel class file.
- *
- * @author Tomasz Wolny <tomasz.wolny@polecam.to.pl> and Qiang Xue <qiang.xue@gmail.com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright &copy; 2005-2011 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Web.UI.WebControls
- * @since 3.1.1
- */
-
-/**
- * Class TTabPanel.
- *
- * TTabPanel displays a tabbed panel. Users can click on the tab bar to switching among
- * different tab views. Each tab view is an independent panel that can contain arbitrary content.
- *
- * If the {@link setAutoSwitch AutoSwitch} property is enabled, the user will be able to switch the active view
- * to another one just hovering its corresponding tab caption.
- *
- * A TTabPanel control consists of one or several {@link TTabView} controls representing the possible
- * tab views. At any time, only one tab view is visible (active), which is specified by any of
- * the following properties:
- * - {@link setActiveViewIndex ActiveViewIndex} - the zero-based integer index of the view in the view collection.
- * - {@link setActiveViewID ActiveViewID} - the text ID of the visible view.
- * - {@link setActiveView ActiveView} - the visible view instance.
- * If both {@link setActiveViewIndex ActiveViewIndex} and {@link setActiveViewID ActiveViewID}
- * are set, the latter takes precedence.
- *
- * TTabPanel uses CSS to specify the appearance of the tab bar and panel. By default,
- * an embedded CSS file will be published which contains the default CSS for TTabPanel.
- * You may also use your own CSS file by specifying the {@link setCssUrl CssUrl} property.
- * The following properties specify the CSS classes used for elements in a TTabPanel:
- * - {@link setCssClass CssClass} - the CSS class name for the outer-most div element (defaults to 'tab-panel');
- * - {@link setTabCssClass TabCssClass} - the CSS class name for nonactive tab div elements (defaults to 'tab-normal');
- * - {@link setActiveTabCssClass ActiveTabCssClass} - the CSS class name for the active tab div element (defaults to 'tab-active');
- * - {@link setViewCssClass ViewCssClass} - the CSS class for the div element enclosing view content (defaults to 'tab-view');
- *
- * To use TTabPanel, write a template like following:
- * <code>
- * <com:TTabPanel>
- * <com:TTabView Caption="View 1">
- * content for view 1
- * </com:TTabView>
- * <com:TTabView Caption="View 2">
- * content for view 2
- * </com:TTabView>
- * <com:TTabView Caption="View 3">
- * content for view 3
- * </com:TTabView>
- * </com:TTabPanel>
- * </code>
- *
- * @author Tomasz Wolny <tomasz.wolny@polecam.to.pl> and Qiang Xue <qiang.xue@gmail.com>
- * @version $Id$
- * @package System.Web.UI.WebControls
- * @since 3.1.1
- */
-class TTabPanel extends TWebControl implements IPostBackDataHandler
-{
- private $_dataChanged=false;
-
- /**
- * @return string tag name for the control
- */
- protected function getTagName()
- {
- return 'div';
- }
-
- /**
- * Adds object parsed from template to the control.
- * This method adds only {@link TTabView} objects into the {@link getViews Views} collection.
- * All other objects are ignored.
- * @param mixed object parsed from template
- */
- public function addParsedObject($object)
- {
- if($object instanceof TTabView)
- $this->getControls()->add($object);
- }
-
- /**
- * Returns the index of the active tab view.
- * Note, this property may not return the correct index.
- * To ensure the correctness, call {@link getActiveView()} first.
- * @return integer the zero-based index of the active tab view. If -1, it means no active tab view. Default is 0 (the first view is active).
- */
- public function getActiveViewIndex()
- {
- return $this->getViewState('ActiveViewIndex',0);
- }
-
- /**
- * @param integer the zero-based index of the current view in the view collection. -1 if no active view.
- * @throws TInvalidDataValueException if the view index is invalid
- */
- public function setActiveViewIndex($value)
- {
- $this->setViewState('ActiveViewIndex',TPropertyValue::ensureInteger($value),0);
- }
-
- /**
- * Returns the ID of the active tab view.
- * Note, this property may not return the correct ID.
- * To ensure the correctness, call {@link getActiveView()} first.
- * @return string The ID of the active tab view. Defaults to '', meaning not set.
- */
- public function getActiveViewID()
- {
- return $this->getViewState('ActiveViewID','');
- }
-
- /**
- * @param string The ID of the active tab view.
- */
- public function setActiveViewID($value)
- {
- $this->setViewState('ActiveViewID',$value,'');
- }
-
- /**
- * Returns the currently active view.
- * This method will examin the ActiveViewID, ActiveViewIndex and Views collection to
- * determine which view is currently active. It will update ActiveViewID and ActiveViewIndex accordingly.
- * @return TTabView the currently active view, null if no active view
- * @throws TInvalidDataValueException if the active view ID or index set previously is invalid
- */
- public function getActiveView()
- {
- $activeView=null;
- $views=$this->getViews();
- if(($id=$this->getActiveViewID())!=='')
- {
- if(($index=$views->findIndexByID($id))>=0)
- $activeView=$views->itemAt($index);
- else
- throw new TInvalidDataValueException('tabpanel_activeviewid_invalid',$id);
- }
- else if(($index=$this->getActiveViewIndex())>=0)
- {
- if($index<$views->getCount())
- $activeView=$views->itemAt($index);
- else
- throw new TInvalidDataValueException('tabpanel_activeviewindex_invalid',$index);
- }
- else
- {
- foreach($views as $index=>$view)
- {
- if($view->getActive())
- {
- $activeView=$view;
- break;
- }
- }
- }
- if($activeView!==null)
- $this->activateView($activeView);
- return $activeView;
- }
-
- /**
- * @param TTabView the view to be activated
- * @throws TInvalidOperationException if the view is not in the view collection
- */
- public function setActiveView($view)
- {
- if($this->getViews()->indexOf($view)>=0)
- $this->activateView($view);
- else
- throw new TInvalidOperationException('tabpanel_view_inexistent');
- }
-
- /**
- * @return bool status of automatic tab switch on hover
- */
- public function getAutoSwitch()
- {
- return TPropertyValue::ensureBoolean($this->getViewState('AutoSwitch'));
- }
-
- /**
- * @param bool whether to enable automatic tab switch on hover
- */
- public function setAutoSwitch($value)
- {
- $this->setViewState('AutoSwitch',TPropertyValue::ensureBoolean($value));
- }
-
-
- /**
- * @return string URL for the CSS file including all relevant CSS class definitions. Defaults to ''.
- */
- public function getCssUrl()
- {
- return $this->getViewState('CssUrl','default');
- }
-
- /**
- * @param string URL for the CSS file including all relevant CSS class definitions.
- */
- public function setCssUrl($value)
- {
- $this->setViewState('CssUrl',TPropertyValue::ensureString($value),'');
- }
-
- /**
- * @return string CSS class for the whole tab control div. Defaults to 'tab-panel'.
- */
- public function getCssClass()
- {
- $cssClass=parent::getCssClass();
- return $cssClass===''?'tab-panel':$cssClass;
- }
-
- /**
- * @return string CSS class for the currently displayed view div. Defaults to 'tab-view'.
- */
- public function getViewCssClass()
- {
- return $this->getViewStyle()->getCssClass();
- }
-
- /**
- * @param string CSS class for the currently displayed view div.
- */
- public function setViewCssClass($value)
- {
- $this->getViewStyle()->setCssClass($value);
- }
-
- /**
- * @return TStyle the style for all the view div
- */
- public function getViewStyle()
- {
- if(($style=$this->getViewState('ViewStyle',null))===null)
- {
- $style=new TStyle;
- $style->setCssClass('tab-view');
- $this->setViewState('ViewStyle',$style,null);
- }
- return $style;
- }
-
- /**
- * @return string CSS class for non-active tabs. Defaults to 'tab-normal'.
- */
- public function getTabCssClass()
- {
- return $this->getTabStyle()->getCssClass();
- }
-
- /**
- * @param string CSS class for non-active tabs.
- */
- public function setTabCssClass($value)
- {
- $this->getTabStyle()->setCssClass($value);
- }
-
- /**
- * @return TStyle the style for all the inactive tab div
- */
- public function getTabStyle()
- {
- if(($style=$this->getViewState('TabStyle',null))===null)
- {
- $style=new TStyle;
- $style->setCssClass('tab-normal');
- $this->setViewState('TabStyle',$style,null);
- }
- return $style;
- }
-
- /**
- * @return string CSS class for the active tab. Defaults to 'tab-active'.
- */
- public function getActiveTabCssClass()
- {
- return $this->getActiveTabStyle()->getCssClass();
- }
-
- /**
- * @param string CSS class for the active tab.
- */
- public function setActiveTabCssClass($value)
- {
- $this->getActiveTabStyle()->setCssClass($value);
- }
-
- /**
- * @return TStyle the style for the active tab div
- */
- public function getActiveTabStyle()
- {
- if(($style=$this->getViewState('ActiveTabStyle',null))===null)
- {
- $style=new TStyle;
- $style->setCssClass('tab-active');
- $this->setViewState('ActiveTabStyle',$style,null);
- }
- return $style;
- }
-
- /**
- * Activates the specified view.
- * If there is any other view currently active, it will be deactivated.
- * @param TTabView the view to be activated. If null, all views will be deactivated.
- */
- protected function activateView($view)
- {
- $this->setActiveViewIndex(-1);
- $this->setActiveViewID('');
- foreach($this->getViews() as $index=>$v)
- {
- if($view===$v)
- {
- $this->setActiveViewIndex($index);
- $this->setActiveViewID($view->getID(false));
- $view->setActive(true);
- }
- else
- $v->setActive(false);
- }
- }
-
- /**
- * Loads user input data.
- * This method is primarly used by framework developers.
- * @param string the key that can be used to retrieve data from the input data collection
- * @param array the input data collection
- * @return boolean whether the data of the control has been changed
- */
- public function loadPostData($key,$values)
- {
- if(($index=$values[$this->getClientID().'_1'])!==null)
- {
- $index=(int)$index;
- $currentIndex=$this->getActiveViewIndex();
- if($currentIndex!==$index)
- {
- $this->setActiveViewID(''); // clear up view ID
- $this->setActiveViewIndex($index);
- return $this->_dataChanged=true;
- }
- }
- return false;
- }
-
- /**
- * Raises postdata changed event.
- * This method is required by {@link IPostBackDataHandler} interface.
- * It is invoked by the framework when {@link getActiveViewIndex ActiveViewIndex} property
- * is changed on postback.
- * This method is primarly used by framework developers.
- */
- public function raisePostDataChangedEvent()
- {
- // do nothing
- }
-
- /**
- * Returns a value indicating whether postback has caused the control data change.
- * This method is required by the IPostBackDataHandler interface.
- * @return boolean whether postback has caused the control data change. False if the page is not in postback mode.
- */
- public function getDataChanged()
- {
- return $this->_dataChanged;
- }
-
- /**
- * Adds attributes to renderer.
- * @param THtmlWriter the renderer
- */
- protected function addAttributesToRender($writer)
- {
- $writer->addAttribute('id',$this->getClientID());
- $this->setCssClass($this->getCssClass());
- parent::addAttributesToRender($writer);
- }
-
- /**
- * Registers CSS and JS.
- * This method is invoked right before the control rendering, if the control is visible.
- * @param mixed event parameter
- */
- public function onPreRender($param)
- {
- parent::onPreRender($param);
- $this->getActiveView(); // determine the active view
- $this->registerStyleSheet();
- $this->registerClientScript();
- }
-
- /**
- * Registers the CSS relevant to the TTabControl.
- * It will register the CSS file specified by {@link getCssUrl CssUrl}.
- * If that is not set, it will use the default CSS.
- */
- protected function registerStyleSheet()
- {
- $url = $this->getCssUrl();
-
- if($url === '') {
- return;
- }
-
- if($url === 'default') {
- $url = $this->getApplication()->getAssetManager()->publishFilePath(dirname(__FILE__).DIRECTORY_SEPARATOR.'assets'.DIRECTORY_SEPARATOR.'tabpanel.css');
- }
-
- if($url !== '') {
- $this->getPage()->getClientScript()->registerStyleSheetFile($url, $url);
- }
- }
-
- /**
- * Registers the relevant JavaScript.
- */
- protected function registerClientScript()
- {
- $id=$this->getClientID();
- $options=TJavaScript::encode($this->getClientOptions());
- $className=$this->getClientClassName();
- $page=$this->getPage();
- $cs=$page->getClientScript();
- $cs->registerPradoScript('tabpanel');
- $code="new $className($options);";
- $cs->registerEndScript("prado:$id", $code);
- // ensure an item is always active and visible
- $index = $this->getActiveViewIndex();
- if(!$this->getViews()->itemAt($index)->Visible)
- $index=0;
- $cs->registerHiddenField($id.'_1', $index);
- $page->registerRequiresPostData($this);
- $page->registerRequiresPostData($id."_1");
- }
-
- /**
- * Gets the name of the javascript class responsible for performing postback for this control.
- * This method overrides the parent implementation.
- * @return string the javascript class name
- */
- protected function getClientClassName()
- {
- return 'Prado.WebUI.TTabPanel';
- }
-
- /**
- * @return array the options for JavaScript
- */
- protected function getClientOptions()
- {
- $options['ID'] = $this->getClientID();
- $options['ActiveCssClass'] = $this->getActiveTabCssClass();
- $options['NormalCssClass'] = $this->getTabCssClass();
- $viewIDs = array();
- $viewVis = array();
- foreach($this->getViews() as $view)
- {
- $viewIDs[] = $view->getClientID();
- $viewVis[] = $view->getVisible();
- }
- $options['Views'] = $viewIDs;
- $options['ViewsVis'] = $viewVis;
- $options['AutoSwitch'] = $this->getAutoSwitch();
-
- return $options;
- }
-
- /**
- * Creates a control collection object that is to be used to hold child controls
- * @return TTabViewCollection control collection
- */
- protected function createControlCollection()
- {
- return new TTabViewCollection($this);
- }
-
- /**
- * @return TTabViewCollection list of {@link TTabView} controls
- */
- public function getViews()
- {
- return $this->getControls();
- }
-
- /**
- * Renders body contents of the tab control.
- * @param THtmlWriter the writer used for the rendering purpose.
- */
- public function renderContents($writer)
- {
- $views=$this->getViews();
- if($views->getCount()>0)
- {
- $writer->writeLine();
- // render tab bar
- foreach($views as $view)
- {
- $view->renderTab($writer);
- $writer->writeLine();
- }
- // render tab views
- foreach($views as $view)
- {
- $view->renderControl($writer);
- $writer->writeLine();
- }
- }
- }
-}
-
-/**
- * TTabView class.
- *
- * TTabView represents a view in a {@link TTabPanel} control.
- *
- * The content in a TTabView can be specified by the {@link setText Text} property
- * or its child controls. In template syntax, the latter means enclosing the content
- * within the TTabView component element. If both are set, {@link getText Text} takes precedence.
- *
- * Each TTabView is associated with a tab in the tab bar of the TTabPanel control.
- * The tab caption is specified by {@link setCaption Caption}. If {@link setNavigateUrl NavigateUrl}
- * is set, the tab will contain a hyperlink pointing to the specified URL. In this case,
- * clicking on the tab will redirect the browser to the specified URL.
- *
- * TTabView may be toggled between visible (active) and invisible (inactive) by
- * setting the {@link setActive Active} property.
- *
- * @author Tomasz Wolny <tomasz.wolny@polecam.to.pl> and Qiang Xue <qiang.xue@gmail.com>
- * @version $Id$
- * @package System.Web.UI.WebControls
- * @since 3.1.1
- */
-class TTabView extends TWebControl
-{
- private $_active=false;
-
- /**
- * @return the tag name for the view element
- */
- protected function getTagName()
- {
- return 'div';
- }
-
- /**
- * Adds attributes to renderer.
- * @param THtmlWriter the renderer
- */
- protected function addAttributesToRender($writer)
- {
- if(!$this->getActive() && $this->getPage()->getClientSupportsJavaScript())
- $this->getStyle()->setStyleField('display','none');
-
- $this->getStyle()->mergeWith($this->getParent()->getViewStyle());
-
- parent::addAttributesToRender($writer);
-
- $writer->addAttribute('id',$this->getClientID());
- }
-
- /**
- * @return string the caption displayed on this tab. Defaults to ''.
- */
- public function getCaption()
- {
- return $this->getViewState('Caption','');
- }
-
- /**
- * @param string the caption displayed on this tab
- */
- public function setCaption($value)
- {
- $this->setViewState('Caption',TPropertyValue::ensureString($value),'');
- }
-
- /**
- * @return string the URL of the target page. Defaults to ''.
- */
- public function getNavigateUrl()
- {
- return $this->getViewState('NavigateUrl','');
- }
-
- /**
- * Sets the URL of the target page.
- * If not empty, clicking on this tab will redirect the browser to the specified URL.
- * @param string the URL of the target page.
- */
- public function setNavigateUrl($value)
- {
- $this->setViewState('NavigateUrl',TPropertyValue::ensureString($value),'');
- }
-
- /**
- * @return string the text content displayed on this view. Defaults to ''.
- */
- public function getText()
- {
- return $this->getViewState('Text','');
- }
-
- /**
- * Sets the text content to be displayed on this view.
- * If this is not empty, the child content of the view will be ignored.
- * @param string the text content displayed on this view
- */
- public function setText($value)
- {
- $this->setViewState('Text',TPropertyValue::ensureString($value),'');
- }
-
- /**
- * @return boolean whether this tab view is active. Defaults to false.
- */
- public function getActive()
- {
- return $this->_active;
- }
-
- /**
- * @param boolean whether this tab view is active.
- */
- public function setActive($value)
- {
- $this->_active=TPropertyValue::ensureBoolean($value);
- }
-
- /**
- * Renders body contents of the tab view.
- * @param THtmlWriter the writer used for the rendering purpose.
- */
- public function renderContents($writer)
- {
- if(($text=$this->getText())!=='')
- $writer->write($text);
- else if($this->getHasControls())
- parent::renderContents($writer);
- }
-
- /**
- * Renders the tab associated with the tab view.
- * @param THtmlWriter the writer for rendering purpose.
- */
- public function renderTab($writer)
- {
- if($this->getVisible(false) && $this->getPage()->getClientSupportsJavaScript())
- {
- $writer->addAttribute('id',$this->getClientID().'_0');
-
- $style=$this->getActive()?$this->getParent()->getActiveTabStyle():$this->getParent()->getTabStyle();
- $style->addAttributesToRender($writer);
-
- $writer->renderBeginTag($this->getTagName());
-
- $this->renderTabContent($writer);
-
- $writer->renderEndTag();
- }
- }
-
- /**
- * Renders the content in the tab.
- * By default, a hyperlink is displayed.
- * @param THtmlWriter the HTML writer
- */
- protected function renderTabContent($writer)
- {
- if(($url=$this->getNavigateUrl())==='')
- $url='javascript://';
- if(($caption=$this->getCaption())==='')
- $caption='&nbsp;';
- $writer->write("<a href=\"{$url}\">{$caption}</a>");
- }
-}
-
-/**
- * TTabViewCollection class.
- *
- * TTabViewCollection is used to maintain a list of views belong to a {@link TTabPanel}.
- *
- * @author Tomasz Wolny <tomasz.wolny@polecam.to.pl> and Qiang Xue <qiang.xue@gmail.com>
- * @version $Id$
- * @package System.Web.UI.WebControls
- * @since 3.1.1
- */
-class TTabViewCollection extends TControlCollection
-{
- /**
- * Inserts an item at the specified position.
- * This overrides the parent implementation by performing sanity check on the type of new item.
- * @param integer the speicified position.
- * @param mixed new item
- * @throws TInvalidDataTypeException if the item to be inserted is not a {@link TTabView} object.
- */
- public function insertAt($index,$item)
- {
- if($item instanceof TTabView)
- parent::insertAt($index,$item);
- else
- throw new TInvalidDataTypeException('tabviewcollection_tabview_required');
- }
-
- /**
- * Finds the index of the tab view whose ID is the same as the one being looked for.
- * @param string the explicit ID of the tab view to be looked for
- * @return integer the index of the tab view found, -1 if not found.
- */
- public function findIndexByID($id)
- {
- foreach($this as $index=>$view)
- {
- if($view->getID(false)===$id)
- return $index;
- }
- return -1;
- }
-}
-
-?>
+<?php
+/**
+ * TTabPanel class file.
+ *
+ * @author Tomasz Wolny <tomasz.wolny@polecam.to.pl> and Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005-2011 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @package System.Web.UI.WebControls
+ * @since 3.1.1
+ */
+
+/**
+ * Class TTabPanel.
+ *
+ * TTabPanel displays a tabbed panel. Users can click on the tab bar to switching among
+ * different tab views. Each tab view is an independent panel that can contain arbitrary content.
+ *
+ * If the {@link setAutoSwitch AutoSwitch} property is enabled, the user will be able to switch the active view
+ * to another one just hovering its corresponding tab caption.
+ *
+ * A TTabPanel control consists of one or several {@link TTabView} controls representing the possible
+ * tab views. At any time, only one tab view is visible (active), which is specified by any of
+ * the following properties:
+ * - {@link setActiveViewIndex ActiveViewIndex} - the zero-based integer index of the view in the view collection.
+ * - {@link setActiveViewID ActiveViewID} - the text ID of the visible view.
+ * - {@link setActiveView ActiveView} - the visible view instance.
+ * If both {@link setActiveViewIndex ActiveViewIndex} and {@link setActiveViewID ActiveViewID}
+ * are set, the latter takes precedence.
+ *
+ * TTabPanel uses CSS to specify the appearance of the tab bar and panel. By default,
+ * an embedded CSS file will be published which contains the default CSS for TTabPanel.
+ * You may also use your own CSS file by specifying the {@link setCssUrl CssUrl} property.
+ * The following properties specify the CSS classes used for elements in a TTabPanel:
+ * - {@link setCssClass CssClass} - the CSS class name for the outer-most div element (defaults to 'tab-panel');
+ * - {@link setTabCssClass TabCssClass} - the CSS class name for nonactive tab div elements (defaults to 'tab-normal');
+ * - {@link setActiveTabCssClass ActiveTabCssClass} - the CSS class name for the active tab div element (defaults to 'tab-active');
+ * - {@link setViewCssClass ViewCssClass} - the CSS class for the div element enclosing view content (defaults to 'tab-view');
+ *
+ * To use TTabPanel, write a template like following:
+ * <code>
+ * <com:TTabPanel>
+ * <com:TTabView Caption="View 1">
+ * content for view 1
+ * </com:TTabView>
+ * <com:TTabView Caption="View 2">
+ * content for view 2
+ * </com:TTabView>
+ * <com:TTabView Caption="View 3">
+ * content for view 3
+ * </com:TTabView>
+ * </com:TTabPanel>
+ * </code>
+ *
+ * @author Tomasz Wolny <tomasz.wolny@polecam.to.pl> and Qiang Xue <qiang.xue@gmail.com>
+ * @version $Id$
+ * @package System.Web.UI.WebControls
+ * @since 3.1.1
+ */
+class TTabPanel extends TWebControl implements IPostBackDataHandler
+{
+ private $_dataChanged=false;
+
+ /**
+ * @return string tag name for the control
+ */
+ protected function getTagName()
+ {
+ return 'div';
+ }
+
+ /**
+ * Adds object parsed from template to the control.
+ * This method adds only {@link TTabView} objects into the {@link getViews Views} collection.
+ * All other objects are ignored.
+ * @param mixed object parsed from template
+ */
+ public function addParsedObject($object)
+ {
+ if($object instanceof TTabView)
+ $this->getControls()->add($object);
+ }
+
+ /**
+ * Returns the index of the active tab view.
+ * Note, this property may not return the correct index.
+ * To ensure the correctness, call {@link getActiveView()} first.
+ * @return integer the zero-based index of the active tab view. If -1, it means no active tab view. Default is 0 (the first view is active).
+ */
+ public function getActiveViewIndex()
+ {
+ return $this->getViewState('ActiveViewIndex',0);
+ }
+
+ /**
+ * @param integer the zero-based index of the current view in the view collection. -1 if no active view.
+ * @throws TInvalidDataValueException if the view index is invalid
+ */
+ public function setActiveViewIndex($value)
+ {
+ $this->setViewState('ActiveViewIndex',TPropertyValue::ensureInteger($value),0);
+ }
+
+ /**
+ * Returns the ID of the active tab view.
+ * Note, this property may not return the correct ID.
+ * To ensure the correctness, call {@link getActiveView()} first.
+ * @return string The ID of the active tab view. Defaults to '', meaning not set.
+ */
+ public function getActiveViewID()
+ {
+ return $this->getViewState('ActiveViewID','');
+ }
+
+ /**
+ * @param string The ID of the active tab view.
+ */
+ public function setActiveViewID($value)
+ {
+ $this->setViewState('ActiveViewID',$value,'');
+ }
+
+ /**
+ * Returns the currently active view.
+ * This method will examin the ActiveViewID, ActiveViewIndex and Views collection to
+ * determine which view is currently active. It will update ActiveViewID and ActiveViewIndex accordingly.
+ * @return TTabView the currently active view, null if no active view
+ * @throws TInvalidDataValueException if the active view ID or index set previously is invalid
+ */
+ public function getActiveView()
+ {
+ $activeView=null;
+ $views=$this->getViews();
+ if(($id=$this->getActiveViewID())!=='')
+ {
+ if(($index=$views->findIndexByID($id))>=0)
+ $activeView=$views->itemAt($index);
+ else
+ throw new TInvalidDataValueException('tabpanel_activeviewid_invalid',$id);
+ }
+ else if(($index=$this->getActiveViewIndex())>=0)
+ {
+ if($index<$views->getCount())
+ $activeView=$views->itemAt($index);
+ else
+ throw new TInvalidDataValueException('tabpanel_activeviewindex_invalid',$index);
+ }
+ else
+ {
+ foreach($views as $index=>$view)
+ {
+ if($view->getActive())
+ {
+ $activeView=$view;
+ break;
+ }
+ }
+ }
+ if($activeView!==null)
+ $this->activateView($activeView);
+ return $activeView;
+ }
+
+ /**
+ * @param TTabView the view to be activated
+ * @throws TInvalidOperationException if the view is not in the view collection
+ */
+ public function setActiveView($view)
+ {
+ if($this->getViews()->indexOf($view)>=0)
+ $this->activateView($view);
+ else
+ throw new TInvalidOperationException('tabpanel_view_inexistent');
+ }
+
+ /**
+ * @return bool status of automatic tab switch on hover
+ */
+ public function getAutoSwitch()
+ {
+ return TPropertyValue::ensureBoolean($this->getViewState('AutoSwitch'));
+ }
+
+ /**
+ * @param bool whether to enable automatic tab switch on hover
+ */
+ public function setAutoSwitch($value)
+ {
+ $this->setViewState('AutoSwitch',TPropertyValue::ensureBoolean($value));
+ }
+
+
+ /**
+ * @return string URL for the CSS file including all relevant CSS class definitions. Defaults to ''.
+ */
+ public function getCssUrl()
+ {
+ return $this->getViewState('CssUrl','default');
+ }
+
+ /**
+ * @param string URL for the CSS file including all relevant CSS class definitions.
+ */
+ public function setCssUrl($value)
+ {
+ $this->setViewState('CssUrl',TPropertyValue::ensureString($value),'');
+ }
+
+ /**
+ * @return string CSS class for the whole tab control div. Defaults to 'tab-panel'.
+ */
+ public function getCssClass()
+ {
+ $cssClass=parent::getCssClass();
+ return $cssClass===''?'tab-panel':$cssClass;
+ }
+
+ /**
+ * @return string CSS class for the currently displayed view div. Defaults to 'tab-view'.
+ */
+ public function getViewCssClass()
+ {
+ return $this->getViewStyle()->getCssClass();
+ }
+
+ /**
+ * @param string CSS class for the currently displayed view div.
+ */
+ public function setViewCssClass($value)
+ {
+ $this->getViewStyle()->setCssClass($value);
+ }
+
+ /**
+ * @return TStyle the style for all the view div
+ */
+ public function getViewStyle()
+ {
+ if(($style=$this->getViewState('ViewStyle',null))===null)
+ {
+ $style=new TStyle;
+ $style->setCssClass('tab-view');
+ $this->setViewState('ViewStyle',$style,null);
+ }
+ return $style;
+ }
+
+ /**
+ * @return string CSS class for non-active tabs. Defaults to 'tab-normal'.
+ */
+ public function getTabCssClass()
+ {
+ return $this->getTabStyle()->getCssClass();
+ }
+
+ /**
+ * @param string CSS class for non-active tabs.
+ */
+ public function setTabCssClass($value)
+ {
+ $this->getTabStyle()->setCssClass($value);
+ }
+
+ /**
+ * @return TStyle the style for all the inactive tab div
+ */
+ public function getTabStyle()
+ {
+ if(($style=$this->getViewState('TabStyle',null))===null)
+ {
+ $style=new TStyle;
+ $style->setCssClass('tab-normal');
+ $this->setViewState('TabStyle',$style,null);
+ }
+ return $style;
+ }
+
+ /**
+ * @return string CSS class for the active tab. Defaults to 'tab-active'.
+ */
+ public function getActiveTabCssClass()
+ {
+ return $this->getActiveTabStyle()->getCssClass();
+ }
+
+ /**
+ * @param string CSS class for the active tab.
+ */
+ public function setActiveTabCssClass($value)
+ {
+ $this->getActiveTabStyle()->setCssClass($value);
+ }
+
+ /**
+ * @return TStyle the style for the active tab div
+ */
+ public function getActiveTabStyle()
+ {
+ if(($style=$this->getViewState('ActiveTabStyle',null))===null)
+ {
+ $style=new TStyle;
+ $style->setCssClass('tab-active');
+ $this->setViewState('ActiveTabStyle',$style,null);
+ }
+ return $style;
+ }
+
+ /**
+ * Activates the specified view.
+ * If there is any other view currently active, it will be deactivated.
+ * @param TTabView the view to be activated. If null, all views will be deactivated.
+ */
+ protected function activateView($view)
+ {
+ $this->setActiveViewIndex(-1);
+ $this->setActiveViewID('');
+ foreach($this->getViews() as $index=>$v)
+ {
+ if($view===$v)
+ {
+ $this->setActiveViewIndex($index);
+ $this->setActiveViewID($view->getID(false));
+ $view->setActive(true);
+ }
+ else
+ $v->setActive(false);
+ }
+ }
+
+ /**
+ * Loads user input data.
+ * This method is primarly used by framework developers.
+ * @param string the key that can be used to retrieve data from the input data collection
+ * @param array the input data collection
+ * @return boolean whether the data of the control has been changed
+ */
+ public function loadPostData($key,$values)
+ {
+ if(($index=$values[$this->getClientID().'_1'])!==null)
+ {
+ $index=(int)$index;
+ $currentIndex=$this->getActiveViewIndex();
+ if($currentIndex!==$index)
+ {
+ $this->setActiveViewID(''); // clear up view ID
+ $this->setActiveViewIndex($index);
+ return $this->_dataChanged=true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Raises postdata changed event.
+ * This method is required by {@link IPostBackDataHandler} interface.
+ * It is invoked by the framework when {@link getActiveViewIndex ActiveViewIndex} property
+ * is changed on postback.
+ * This method is primarly used by framework developers.
+ */
+ public function raisePostDataChangedEvent()
+ {
+ // do nothing
+ }
+
+ /**
+ * Returns a value indicating whether postback has caused the control data change.
+ * This method is required by the IPostBackDataHandler interface.
+ * @return boolean whether postback has caused the control data change. False if the page is not in postback mode.
+ */
+ public function getDataChanged()
+ {
+ return $this->_dataChanged;
+ }
+
+ /**
+ * Adds attributes to renderer.
+ * @param THtmlWriter the renderer
+ */
+ protected function addAttributesToRender($writer)
+ {
+ $writer->addAttribute('id',$this->getClientID());
+ $this->setCssClass($this->getCssClass());
+ parent::addAttributesToRender($writer);
+ }
+
+ /**
+ * Registers CSS and JS.
+ * This method is invoked right before the control rendering, if the control is visible.
+ * @param mixed event parameter
+ */
+ public function onPreRender($param)
+ {
+ parent::onPreRender($param);
+ $this->getActiveView(); // determine the active view
+ $this->registerStyleSheet();
+ }
+
+ /**
+ * Registers the CSS relevant to the TTabControl.
+ * It will register the CSS file specified by {@link getCssUrl CssUrl}.
+ * If that is not set, it will use the default CSS.
+ */
+ protected function registerStyleSheet()
+ {
+ $url = $this->getCssUrl();
+
+ if($url === '') {
+ return;
+ }
+
+ if($url === 'default') {
+ $url = $this->getApplication()->getAssetManager()->publishFilePath(dirname(__FILE__).DIRECTORY_SEPARATOR.'assets'.DIRECTORY_SEPARATOR.'tabpanel.css');
+ }
+
+ if($url !== '') {
+ $this->getPage()->getClientScript()->registerStyleSheetFile($url, $url);
+ }
+ }
+
+ /**
+ * Registers the relevant JavaScript.
+ */
+ protected function registerClientScript()
+ {
+ $id=$this->getClientID();
+ $options=TJavaScript::encode($this->getClientOptions());
+ $className=$this->getClientClassName();
+ $page=$this->getPage();
+ $cs=$page->getClientScript();
+ $cs->registerPradoScript('tabpanel');
+ $code="new $className($options);";
+ $cs->registerEndScript("prado:$id", $code);
+ // ensure an item is always active and visible
+ $index = $this->getActiveViewIndex();
+ if(!$this->getViews()->itemAt($index)->Visible)
+ $index=0;
+ $cs->registerHiddenField($id.'_1', $index);
+ $page->registerRequiresPostData($this);
+ $page->registerRequiresPostData($id."_1");
+ }
+
+ /**
+ * Gets the name of the javascript class responsible for performing postback for this control.
+ * This method overrides the parent implementation.
+ * @return string the javascript class name
+ */
+ protected function getClientClassName()
+ {
+ return 'Prado.WebUI.TTabPanel';
+ }
+
+ /**
+ * @return array the options for JavaScript
+ */
+ protected function getClientOptions()
+ {
+ $options['ID'] = $this->getClientID();
+ $options['ActiveCssClass'] = $this->getActiveTabCssClass();
+ $options['NormalCssClass'] = $this->getTabCssClass();
+ $viewIDs = array();
+ $viewVis = array();
+ foreach($this->getViews() as $view)
+ {
+ $viewIDs[] = $view->getClientID();
+ $viewVis[] = $view->getVisible();
+ }
+ $options['Views'] = $viewIDs;
+ $options['ViewsVis'] = $viewVis;
+ $options['AutoSwitch'] = $this->getAutoSwitch();
+
+ return $options;
+ }
+
+ /**
+ * Creates a control collection object that is to be used to hold child controls
+ * @return TTabViewCollection control collection
+ */
+ protected function createControlCollection()
+ {
+ return new TTabViewCollection($this);
+ }
+
+ /**
+ * @return TTabViewCollection list of {@link TTabView} controls
+ */
+ public function getViews()
+ {
+ return $this->getControls();
+ }
+
+ public function render($writer)
+ {
+ $this->registerClientScript();
+ parent::render($writer);
+ }
+
+ /**
+ * Renders body contents of the tab control.
+ * @param THtmlWriter the writer used for the rendering purpose.
+ */
+ public function renderContents($writer)
+ {
+ $views=$this->getViews();
+ if($views->getCount()>0)
+ {
+ $writer->writeLine();
+ // render tab bar
+ foreach($views as $view)
+ {
+ $view->renderTab($writer);
+ $writer->writeLine();
+ }
+ // render tab views
+ foreach($views as $view)
+ {
+ $view->renderControl($writer);
+ $writer->writeLine();
+ }
+ }
+ }
+}
+
+/**
+ * TTabView class.
+ *
+ * TTabView represents a view in a {@link TTabPanel} control.
+ *
+ * The content in a TTabView can be specified by the {@link setText Text} property
+ * or its child controls. In template syntax, the latter means enclosing the content
+ * within the TTabView component element. If both are set, {@link getText Text} takes precedence.
+ *
+ * Each TTabView is associated with a tab in the tab bar of the TTabPanel control.
+ * The tab caption is specified by {@link setCaption Caption}. If {@link setNavigateUrl NavigateUrl}
+ * is set, the tab will contain a hyperlink pointing to the specified URL. In this case,
+ * clicking on the tab will redirect the browser to the specified URL.
+ *
+ * TTabView may be toggled between visible (active) and invisible (inactive) by
+ * setting the {@link setActive Active} property.
+ *
+ * @author Tomasz Wolny <tomasz.wolny@polecam.to.pl> and Qiang Xue <qiang.xue@gmail.com>
+ * @version $Id$
+ * @package System.Web.UI.WebControls
+ * @since 3.1.1
+ */
+class TTabView extends TWebControl
+{
+ private $_active=false;
+
+ /**
+ * @return the tag name for the view element
+ */
+ protected function getTagName()
+ {
+ return 'div';
+ }
+
+ /**
+ * Adds attributes to renderer.
+ * @param THtmlWriter the renderer
+ */
+ protected function addAttributesToRender($writer)
+ {
+ if(!$this->getActive() && $this->getPage()->getClientSupportsJavaScript())
+ $this->getStyle()->setStyleField('display','none');
+
+ $this->getStyle()->mergeWith($this->getParent()->getViewStyle());
+
+ parent::addAttributesToRender($writer);
+
+ $writer->addAttribute('id',$this->getClientID());
+ }
+
+ /**
+ * @return string the caption displayed on this tab. Defaults to ''.
+ */
+ public function getCaption()
+ {
+ return $this->getViewState('Caption','');
+ }
+
+ /**
+ * @param string the caption displayed on this tab
+ */
+ public function setCaption($value)
+ {
+ $this->setViewState('Caption',TPropertyValue::ensureString($value),'');
+ }
+
+ /**
+ * @return string the URL of the target page. Defaults to ''.
+ */
+ public function getNavigateUrl()
+ {
+ return $this->getViewState('NavigateUrl','');
+ }
+
+ /**
+ * Sets the URL of the target page.
+ * If not empty, clicking on this tab will redirect the browser to the specified URL.
+ * @param string the URL of the target page.
+ */
+ public function setNavigateUrl($value)
+ {
+ $this->setViewState('NavigateUrl',TPropertyValue::ensureString($value),'');
+ }
+
+ /**
+ * @return string the text content displayed on this view. Defaults to ''.
+ */
+ public function getText()
+ {
+ return $this->getViewState('Text','');
+ }
+
+ /**
+ * Sets the text content to be displayed on this view.
+ * If this is not empty, the child content of the view will be ignored.
+ * @param string the text content displayed on this view
+ */
+ public function setText($value)
+ {
+ $this->setViewState('Text',TPropertyValue::ensureString($value),'');
+ }
+
+ /**
+ * @return boolean whether this tab view is active. Defaults to false.
+ */
+ public function getActive()
+ {
+ return $this->_active;
+ }
+
+ /**
+ * @param boolean whether this tab view is active.
+ */
+ public function setActive($value)
+ {
+ $this->_active=TPropertyValue::ensureBoolean($value);
+ }
+
+ /**
+ * Renders body contents of the tab view.
+ * @param THtmlWriter the writer used for the rendering purpose.
+ */
+ public function renderContents($writer)
+ {
+ if(($text=$this->getText())!=='')
+ $writer->write($text);
+ else if($this->getHasControls())
+ parent::renderContents($writer);
+ }
+
+ /**
+ * Renders the tab associated with the tab view.
+ * @param THtmlWriter the writer for rendering purpose.
+ */
+ public function renderTab($writer)
+ {
+ if($this->getVisible(false) && $this->getPage()->getClientSupportsJavaScript())
+ {
+ $writer->addAttribute('id',$this->getClientID().'_0');
+
+ $style=$this->getActive()?$this->getParent()->getActiveTabStyle():$this->getParent()->getTabStyle();
+ $style->addAttributesToRender($writer);
+
+ $writer->renderBeginTag($this->getTagName());
+
+ $this->renderTabContent($writer);
+
+ $writer->renderEndTag();
+ }
+ }
+
+ /**
+ * Renders the content in the tab.
+ * By default, a hyperlink is displayed.
+ * @param THtmlWriter the HTML writer
+ */
+ protected function renderTabContent($writer)
+ {
+ if(($url=$this->getNavigateUrl())==='')
+ $url='javascript://';
+ if(($caption=$this->getCaption())==='')
+ $caption='&nbsp;';
+ $writer->write("<a href=\"{$url}\">{$caption}</a>");
+ }
+}
+
+/**
+ * TTabViewCollection class.
+ *
+ * TTabViewCollection is used to maintain a list of views belong to a {@link TTabPanel}.
+ *
+ * @author Tomasz Wolny <tomasz.wolny@polecam.to.pl> and Qiang Xue <qiang.xue@gmail.com>
+ * @version $Id$
+ * @package System.Web.UI.WebControls
+ * @since 3.1.1
+ */
+class TTabViewCollection extends TControlCollection
+{
+ /**
+ * Inserts an item at the specified position.
+ * This overrides the parent implementation by performing sanity check on the type of new item.
+ * @param integer the speicified position.
+ * @param mixed new item
+ * @throws TInvalidDataTypeException if the item to be inserted is not a {@link TTabView} object.
+ */
+ public function insertAt($index,$item)
+ {
+ if($item instanceof TTabView)
+ parent::insertAt($index,$item);
+ else
+ throw new TInvalidDataTypeException('tabviewcollection_tabview_required');
+ }
+
+ /**
+ * Finds the index of the tab view whose ID is the same as the one being looked for.
+ * @param string the explicit ID of the tab view to be looked for
+ * @return integer the index of the tab view found, -1 if not found.
+ */
+ public function findIndexByID($id)
+ {
+ foreach($this as $index=>$view)
+ {
+ if($view->getID(false)===$id)
+ return $index;
+ }
+ return -1;
+ }
+}
diff --git a/framework/Web/UI/WebControls/TTextHighlighter.php b/framework/Web/UI/WebControls/TTextHighlighter.php
index 48fb1d41..92b67846 100644
--- a/framework/Web/UI/WebControls/TTextHighlighter.php
+++ b/framework/Web/UI/WebControls/TTextHighlighter.php
@@ -1,206 +1,213 @@
-<?php
-/**
- * TTextHighlighter class file
- *
- * @author Wei Zhuo<weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright &copy; 2005-2011 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Web.UI.WebControls
- */
-
-Prado::using('System.3rdParty.TextHighlighter.Text.Highlighter',false);
-Prado::using('System.3rdParty.TextHighlighter.Text.Highlighter.Renderer.Html',false);
-Prado::using('System.Web.UI.WebControls.TTextProcessor');
-
-
-/**
- * TTextHighlighter class.
- *
- * TTextHighlighter does syntax highlighting its body content, including
- * static text and rendering results of child controls.
- * You can set {@link setLanguage Language} to specify what kind of syntax
- * the body content is. Currently, TTextHighlighter supports the following
- * languages: ABAP, CPP, CSS, DIFF, DTD, HTML, JAVA, JAVASCRIPT, MYSQL, PERL,
- * PHP, PYTHON, RUBY, SQL, XML and PRADO, where PRADO refers to PRADO template
- * syntax. By setting {@link setShowLineNumbers ShowLineNumbers}
- * to true, the highlighted result may be shown with line numbers.
- *
- * Note, TTextHighlighter requires {@link THead} to be placed on the page template
- * because it needs to insert some CSS styles.
- *
- * @author Wei Zhuo<weizhuo[at]gmail[dot]com>
- * @version $Id$
- * @package System.Web.UI.WebControls
- * @since 3.0
- */
-class TTextHighlighter extends TTextProcessor
-{
- private static $_lineNumberStyle=array(TTextHighlighterLineNumberStyle::Li => HL_NUMBERS_LI, TTextHighlighterLineNumberStyle::Table => HL_NUMBERS_TABLE);
-
- /**
- * @return string tag name of the panel
- */
- protected function getTagName()
- {
- return 'div';
- }
-
- /**
- * @return string language whose syntax is to be used for highlighting. Defaults to 'php'.
- */
- public function getLanguage()
- {
- return $this->getViewState('Language', 'php');
- }
-
- /**
- * @param string language (case-insensitive) whose syntax is to be used for highlighting.
- * Valid values are those file names (without suffix) that are contained
- * in '3rdParty/TextHighlighter/Text/Highlighter'. Currently, the following languages are supported:
- * ABAP, CPP, CSS, DIFF, DTD, HTML, JAVA, JAVASCRIPT,
- * MYSQL, PERL, PHP, PRADO, PYTHON, RUBY, SQL, XML
- * If a language is not supported, it will be displayed as plain text.
- */
- public function setLanguage($value)
- {
- $this->setViewState('Language', $value, 'php');
- }
-
- /**
- * @return boolean whether to show line numbers in the highlighted result.
- */
- public function getShowLineNumbers()
- {
- return $this->getViewState('ShowLineNumbers', false);
- }
-
- /**
- * @param boolean whether to show line numbers in the highlighted result.
- */
- public function setShowLineNumbers($value)
- {
- $this->setViewState('ShowLineNumbers', TPropertyValue::ensureBoolean($value), false);
- }
-
- /**
- * @return boolean true will show "Copy Code" link. Defaults to false.
- */
- public function getEnableCopyCode()
- {
- return $this->getViewState('CopyCode', false);
- }
-
- /**
- * @param boolean true to show the "Copy Code" link.
- */
- public function setEnableCopyCode($value)
- {
- $this->setViewState('CopyCode', TPropertyValue::ensureBoolean($value), false);
- }
-
- /**
- * @return TTextHighlighterLineNumberStyle style of row number, Table by default
- */
- public function getLineNumberStyle()
- {
- return $this->getViewState('LineNumberStyle', TTextHighlighterLineNumberStyle::Table);
- }
-
- /**
- * @param TTextHighlighterLineNumberStyle style of row number
- */
- public function setLineNumberStyle($value)
- {
- $this->setViewState('LineNumberStyle', TPropertyValue::ensureEnum($value,'TTextHighlighterLineNumberStyle'));
- }
-
- /**
- * @return integer tab size. Defaults to 4.
- */
- public function getTabSize()
- {
- return $this->getViewState('TabSize', 4);
- }
-
- /**
- * @param integer tab size
- */
- public function setTabSize($value)
- {
- $this->setViewState('TabSize', TPropertyValue::ensureInteger($value));
- }
-
- /**
- * Registers css style for the highlighted result.
- * This method overrides parent implementation.
- * @param THtmlWriter writer
- */
- public function onPreRender($writer)
- {
- parent::onPreRender($writer);
- $this->registerStyleSheet();
- $this->getPage()->getClientScript()->registerPradoScript('prado');
- }
-
- /**
- * Registers the stylesheet for presentation.
- */
- protected function registerStyleSheet()
- {
- $cs=$this->getPage()->getClientScript();
- $cssFile=Prado::getPathOfNamespace('System.3rdParty.TextHighlighter.highlight','.css');
- $cssKey='prado:TTextHighlighter:'.$cssFile;
- if(!$cs->isStyleSheetFileRegistered($cssKey))
- $cs->registerStyleSheetFile($cssKey, $this->publishFilePath($cssFile));
- }
-
- /**
- * Processes a text string.
- * This method is required by the parent class.
- * @param string text string to be processed
- * @return string the processed text result
- */
- public function processText($text)
- {
- try
- {
- $highlighter=Text_Highlighter::factory($this->getLanguage());
- }
- catch(Exception $e)
- {
- $highlighter=false;
- }
- if($highlighter===false)
- return ('<pre>'.htmlentities(trim($text)).'</pre>');
-
- $options["use_language"]=true;
- $options["tabsize"] = $this->getTabSize();
- if ($this->getShowLineNumbers())
- $options["numbers"] = self::$_lineNumberStyle[$this->getLineNumberStyle()];
- $highlighter->setRenderer(new Text_Highlighter_Renderer_Html($options));
- return $highlighter->highlight(trim($text));
- }
-
- /**
- * @return string header template with "Copy code" link.
- */
- protected function getHeaderTemplate()
- {
- $id = $this->getClientID();
- return TJavaScript::renderScriptBlock("new Prado.WebUI.TTextHighlighter('{$id}');");
- }
-}
-
-/**
- * @author Wei Zhuo<weizhuo[at]gmail[dot]com>
- * @version $Id$
- * @package System.Web.UI.WebControls
- * @since 3.0
- */
-class TTextHighlighterLineNumberStyle extends TEnumerable
-{
- const Li='Li';
- const Table='Table';
-}
+<?php
+/**
+ * TTextHighlighter class file
+ *
+ * @author Wei Zhuo<weizhuo[at]gmail[dot]com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005-2011 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @package System.Web.UI.WebControls
+ */
+
+Prado::using('System.3rdParty.TextHighlighter.Text.Highlighter',false);
+Prado::using('System.3rdParty.TextHighlighter.Text.Highlighter.Renderer.Html',false);
+Prado::using('System.Web.UI.WebControls.TTextProcessor');
+
+
+/**
+ * TTextHighlighter class.
+ *
+ * TTextHighlighter does syntax highlighting its body content, including
+ * static text and rendering results of child controls.
+ * You can set {@link setLanguage Language} to specify what kind of syntax
+ * the body content is. Currently, TTextHighlighter supports the following
+ * languages: ABAP, CPP, CSS, DIFF, DTD, HTML, JAVA, JAVASCRIPT, MYSQL, PERL,
+ * PHP, PYTHON, RUBY, SQL, XML and PRADO, where PRADO refers to PRADO template
+ * syntax. By setting {@link setShowLineNumbers ShowLineNumbers}
+ * to true, the highlighted result may be shown with line numbers.
+ *
+ * Note, TTextHighlighter requires {@link THead} to be placed on the page template
+ * because it needs to insert some CSS styles.
+ *
+ * @author Wei Zhuo<weizhuo[at]gmail[dot]com>
+ * @version $Id$
+ * @package System.Web.UI.WebControls
+ * @since 3.0
+ */
+class TTextHighlighter extends TTextProcessor
+{
+ private static $_lineNumberStyle=array(TTextHighlighterLineNumberStyle::Li => HL_NUMBERS_LI, TTextHighlighterLineNumberStyle::Table => HL_NUMBERS_TABLE);
+
+ /**
+ * @return string tag name of the panel
+ */
+ protected function getTagName()
+ {
+ return 'div';
+ }
+
+ /**
+ * @return string language whose syntax is to be used for highlighting. Defaults to 'php'.
+ */
+ public function getLanguage()
+ {
+ return $this->getViewState('Language', 'php');
+ }
+
+ /**
+ * @param string language (case-insensitive) whose syntax is to be used for highlighting.
+ * Valid values are those file names (without suffix) that are contained
+ * in '3rdParty/TextHighlighter/Text/Highlighter'. Currently, the following languages are supported:
+ * ABAP, CPP, CSS, DIFF, DTD, HTML, JAVA, JAVASCRIPT,
+ * MYSQL, PERL, PHP, PRADO, PYTHON, RUBY, SQL, XML
+ * If a language is not supported, it will be displayed as plain text.
+ */
+ public function setLanguage($value)
+ {
+ $this->setViewState('Language', $value, 'php');
+ }
+
+ /**
+ * @return boolean whether to show line numbers in the highlighted result.
+ */
+ public function getShowLineNumbers()
+ {
+ return $this->getViewState('ShowLineNumbers', false);
+ }
+
+ /**
+ * @param boolean whether to show line numbers in the highlighted result.
+ */
+ public function setShowLineNumbers($value)
+ {
+ $this->setViewState('ShowLineNumbers', TPropertyValue::ensureBoolean($value), false);
+ }
+
+ /**
+ * @return boolean true will show "Copy Code" link. Defaults to false.
+ */
+ public function getEnableCopyCode()
+ {
+ return $this->getViewState('CopyCode', false);
+ }
+
+ /**
+ * @param boolean true to show the "Copy Code" link.
+ */
+ public function setEnableCopyCode($value)
+ {
+ $this->setViewState('CopyCode', TPropertyValue::ensureBoolean($value), false);
+ }
+
+ /**
+ * @return TTextHighlighterLineNumberStyle style of row number, Table by default
+ */
+ public function getLineNumberStyle()
+ {
+ return $this->getViewState('LineNumberStyle', TTextHighlighterLineNumberStyle::Table);
+ }
+
+ /**
+ * @param TTextHighlighterLineNumberStyle style of row number
+ */
+ public function setLineNumberStyle($value)
+ {
+ $this->setViewState('LineNumberStyle', TPropertyValue::ensureEnum($value,'TTextHighlighterLineNumberStyle'));
+ }
+
+ /**
+ * @return integer tab size. Defaults to 4.
+ */
+ public function getTabSize()
+ {
+ return $this->getViewState('TabSize', 4);
+ }
+
+ /**
+ * @param integer tab size
+ */
+ public function setTabSize($value)
+ {
+ $this->setViewState('TabSize', TPropertyValue::ensureInteger($value));
+ }
+
+ /**
+ * Registers css style for the highlighted result.
+ * This method overrides parent implementation.
+ * @param THtmlWriter writer
+ */
+ public function onPreRender($writer)
+ {
+ parent::onPreRender($writer);
+ $this->registerStyleSheet();
+ }
+
+ /**
+ * Registers the stylesheet for presentation.
+ */
+ protected function registerStyleSheet()
+ {
+ $cs=$this->getPage()->getClientScript();
+ $cssFile=Prado::getPathOfNamespace('System.3rdParty.TextHighlighter.highlight','.css');
+ $cssKey='prado:TTextHighlighter:'.$cssFile;
+ if(!$cs->isStyleSheetFileRegistered($cssKey))
+ $cs->registerStyleSheetFile($cssKey, $this->publishFilePath($cssFile));
+ }
+
+ /**
+ * Processes a text string.
+ * This method is required by the parent class.
+ * @param string text string to be processed
+ * @return string the processed text result
+ */
+ public function processText($text)
+ {
+ try
+ {
+ $highlighter=Text_Highlighter::factory($this->getLanguage());
+ }
+ catch(Exception $e)
+ {
+ $highlighter=false;
+ }
+ if($highlighter===false)
+ return ('<pre>'.htmlentities(trim($text)).'</pre>');
+
+ $options["use_language"]=true;
+ $options["tabsize"] = $this->getTabSize();
+ if ($this->getShowLineNumbers())
+ $options["numbers"] = self::$_lineNumberStyle[$this->getLineNumberStyle()];
+ $highlighter->setRenderer(new Text_Highlighter_Renderer_Html($options));
+ return $highlighter->highlight(trim($text));
+ }
+
+ /**
+ * @return string header template with "Copy code" link.
+ */
+ protected function getHeaderTemplate()
+ {
+ $id = $this->getClientID();
+ return TJavaScript::renderScriptBlock("new Prado.WebUI.TTextHighlighter('{$id}');");
+ }
+
+ public function render($writer)
+ {
+ $this->getPage()->getClientScript()->registerPradoScript('prado');
+ parent::render($writer);
+ }
+
+
+}
+
+/**
+ * @author Wei Zhuo<weizhuo[at]gmail[dot]com>
+ * @version $Id$
+ * @package System.Web.UI.WebControls
+ * @since 3.0
+ */
+class TTextHighlighterLineNumberStyle extends TEnumerable
+{
+ const Li='Li';
+ const Table='Table';
+}