From 6e275c7db5cbbf1bf0331bbaf60f3b3ec612c3a7 Mon Sep 17 00:00:00 2001
From: xue <>
Date: Tue, 13 Jun 2006 02:07:25 +0000
Subject: Fixed #224.

---
 framework/Web/UI/WebControls/TBulletedList.php |  870 +++++++-------
 framework/Web/UI/WebControls/TButton.php       |  524 ++++-----
 framework/Web/UI/WebControls/TCheckBox.php     |  804 ++++++-------
 framework/Web/UI/WebControls/TColorPicker.php  |    9 +
 framework/Web/UI/WebControls/THtmlArea.php     |   10 +
 framework/Web/UI/WebControls/TImageButton.php  |  767 +++++++------
 framework/Web/UI/WebControls/TImageMap.php     | 1464 ++++++++++++------------
 framework/Web/UI/WebControls/TLinkButton.php   |  520 ++++-----
 framework/Web/UI/WebControls/TRadioButton.php  |  374 +++---
 framework/Web/UI/WebControls/TRatingList.php   |   10 +
 framework/Web/UI/WebControls/TTextBox.php      |   12 +-
 11 files changed, 2732 insertions(+), 2632 deletions(-)

(limited to 'framework/Web/UI/WebControls')

diff --git a/framework/Web/UI/WebControls/TBulletedList.php b/framework/Web/UI/WebControls/TBulletedList.php
index a2529940..fd9c1ca2 100644
--- a/framework/Web/UI/WebControls/TBulletedList.php
+++ b/framework/Web/UI/WebControls/TBulletedList.php
@@ -1,435 +1,435 @@
-<?php
-/**
- * TBulletedList class file
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright &copy; 2005 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Revision: $  $Date: $
- * @package System.Web.UI.WebControls
- */
-
-/**
- * Includes TListControl class
- */
-Prado::using('System.Web.UI.WebControls.TListControl');
-
-/**
- * TBulletedList class
- *
- * TBulletedList displays items in a bullet format.
- * The bullet style is specified by {@link setBulletStyle BulletStyle}. When
- * the style is 'CustomImage', the {@link setBackImageUrl BulletImageUrl}
- * specifies the image used as bullets.
- *
- * TBulletedList displays the item texts in three different modes, specified
- * via {@link setDisplayMode DisplayMode}. When the mode is 'Text', the item texts
- * are displayed as static texts; When the mode is 'HyperLink', each item
- * is displayed as a hyperlink whose URL is given by the item value, and the
- * {@link setTarget Target} property can be used to specify the target browser window;
- * When the mode is 'LinkButton', each item is displayed as a link button which
- * posts back to the page if a user clicks on that and the event {@link onClick OnClick}
- * will be raised under such a circumstance.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Revision: $  $Date: $
- * @package System.Web.UI.WebControls
- * @since 3.0
- */
-class TBulletedList extends TListControl implements IPostBackEventHandler
-{
-	/**
-	 * @var boolean cached property value of Enabled
-	 */
-	private $_isEnabled;
-	/**
-	 * @var TPostBackOptions postback options
-	 */
-	private $_postBackOptions;
-
-	private $_currentRenderItemIndex;
-
-	/**
-	 * Raises the postback event.
-	 * This method is required by {@link IPostBackEventHandler} interface.
-	 * If {@link getCausesValidation CausesValidation} is true, it will
-	 * invoke the page's {@link TPage::validate validate} method first.
-	 * It will raise {@link onClick OnClick} events.
-	 * This method is mainly used by framework and control developers.
-	 * @param TEventParameter the event parameter
-	 */
-	public function raisePostBackEvent($param)
-	{
-		if($this->getCausesValidation())
-			$this->getPage()->validate($this->getValidationGroup());
-		$this->onClick(new TBulletedListEventParameter((int)$param));
-	}
-
-	/**
-	 * @return string tag name of the bulleted list
-	 */
-	protected function getTagName()
-	{
-		switch($this->getBulletStyle())
-		{
-			case 'Numbered':
-			case 'LowerAlpha':
-			case 'UpperAlpha':
-			case 'LowerRoman':
-			case 'UpperRoman':
-				return 'ol';
-		}
-		return 'ul';
-	}
-
-	/**
-	 * 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.TBulletedList';
-	}
-
-	/**
-	 * Adds attribute name-value pairs to renderer.
-	 * This overrides the parent implementation with additional bulleted list specific attributes.
-	 * @param THtmlWriter the writer used for the rendering purpose
-	 */
-	protected function addAttributesToRender($writer)
-	{
-		$needStart=false;
-		switch($this->getBulletStyle())
-		{
-			case 'Numbered':
-				$writer->addStyleAttribute('list-style-type','decimal');
-				$needStart=true;
-				break;
-			case 'LowerAlpha':
-				$writer->addStyleAttribute('list-style-type','lower-alpha');
-				$needStart=true;
-				break;
-			case 'UpperAlpha':
-				$writer->addStyleAttribute('list-style-type','upper-alpha');
-				$needStart=true;
-				break;
-			case 'LowerRoman':
-				$writer->addStyleAttribute('list-style-type','lower-roman');
-				$needStart=true;
-				break;
-			case 'UpperRoman':
-				$writer->addStyleAttribute('list-style-type','upper-roman');
-				$needStart=true;
-				break;
-			case 'Disc':
-				$writer->addStyleAttribute('list-style-type','disc');
-				break;
-			case 'Circle':
-				$writer->addStyleAttribute('list-style-type','circle');
-				break;
-			case 'Square':
-				$writer->addStyleAttribute('list-style-type','square');
-				break;
-			case 'CustomImage':
-				$url=$this->getBulletImageUrl();
-				$writer->addStyleAttribute('list-style-image',"url($url)");
-				break;
-		}
-		if($needStart && ($start=$this->getFirstBulletNumber())!=1)
-			$writer->addAttribute('start',"$start");
-		parent::addAttributesToRender($writer);
-	}
-
-	/**
-	 * @return string image URL used for bullets when {@link getBulletStyle BulletStyle} is 'CustomImage'.
-	 */
-	public function getBulletImageUrl()
-	{
-		return $this->getViewState('BulletImageUrl','');
-	}
-
-	/**
-	 * @param string image URL used for bullets when {@link getBulletStyle BulletStyle} is 'CustomImage'.
-	 */
-	public function setBulletImageUrl($value)
-	{
-		$this->setViewState('BulletImageUrl',$value,'');
-	}
-
-	/**
-	 * @return string style of bullets. Defaults to 'NotSet'.
-	 */
-	public function getBulletStyle()
-	{
-		return $this->getViewState('BulletStyle','NotSet');
-	}
-
-	/**
-	 * @return string style of bullets. Valid values include
-	 * 'NotSet','Numbered','LowerAlpha','UpperAlpha','LowerRoman','UpperRoman','Disc','Circle','Square','CustomImage'
-	 */
-	public function setBulletStyle($value)
-	{
-		$this->setViewState('BulletStyle',TPropertyValue::ensureEnum($value,'NotSet','Numbered','LowerAlpha','UpperAlpha','LowerRoman','UpperRoman','Disc','Circle','Square','CustomImage'),'NotSet');
-	}
-
-	/**
-	 * @param string display mode of the list. Defaults to 'Text'.
-	 */
-	public function getDisplayMode()
-	{
-		return $this->getViewState('DisplayMode','Text');
-	}
-
-	/**
-	 * @return string display mode of the list. Valid values include
-	 * 'Text', 'HyperLink', 'LinkButton'.
-	 */
-	public function setDisplayMode($value)
-	{
-		$this->setViewState('DisplayMode',TPropertyValue::ensureEnum($value,'Text','HyperLink','LinkButton'),'Text');
-	}
-
-	/**
-	 * @return integer starting index when {@link getBulletStyle BulletStyle} is one of
-	 * the following: 'Numbered', 'LowerAlpha', 'UpperAlpha', 'LowerRoman', 'UpperRoman'.
-	 * Defaults to 1.
-	 */
-	public function getFirstBulletNumber()
-	{
-		return $this->getViewState('FirstBulletNumber',1);
-	}
-
-	/**
-	 * @param integer starting index when {@link getBulletStyle BulletStyle} is one of
-	 * the following: 'Numbered', 'LowerAlpha', 'UpperAlpha', 'LowerRoman', 'UpperRoman'.
-	 */
-	public function setFirstBulletNumber($value)
-	{
-		$this->setViewState('FirstBulletNumber',TPropertyValue::ensureInteger($value),1);
-	}
-
-	/**
-	 * Raises 'OnClick' event.
-	 * This method is invoked when the {@link getDisplayMode DisplayMode} is 'LinkButton'
-	 * and end-users click on one of the buttons.
-	 * @param TBulletedListEventParameter event parameter.
-	 */
-	public function onClick($param)
-	{
-		$this->raiseEvent('OnClick',$this,$param);
-	}
-
-	/**
-	 * @return string the target window or frame to display the Web page content
-	 * linked to when {@link getDisplayMode DisplayMode} is 'HyperLink' and one of
-	 * the hyperlinks is clicked.
-	 */
-	public function getTarget()
-	{
-		return $this->getViewState('Target','');
-	}
-
-	/**
-	 * @param string the target window or frame to display the Web page content
-	 * linked to when {@link getDisplayMode DisplayMode} is 'HyperLink' and one of
-	 * the hyperlinks is clicked.
-	 */
-	public function setTarget($value)
-	{
-		$this->setViewState('Target',$value,'');
-	}
-
-	/**
-	 * Renders the control.
-	 * @param THtmlWriter the writer for the rendering purpose.
-	 */
-	public function render($writer)
-	{
-		if($this->getHasItems())
-			parent::render($writer);
-	}
-
-	/**
-	 * Renders the body contents.
-	 * @param THtmlWriter the writer for the rendering purpose.
-	 */
-	public function renderContents($writer)
-	{
-		$this->_isEnabled=$this->getEnabled(true);
-		$this->_postBackOptions=$this->getPostBackOptions();
-		$writer->writeLine();
-		foreach($this->getItems() as $index=>$item)
-		{
-			if($item->getHasAttributes())
-				$writer->addAttributes($item->getAttributes());
-			$writer->renderBeginTag('li');
-			$this->renderBulletText($writer,$item,$index);
-			$writer->renderEndTag();
-			$writer->writeLine();
-		}
-	}
-
-	/**
-	 * Renders each item
-	 * @param THtmlWriter writer for the rendering purpose
-	 * @param TListItem item to be rendered
-	 * @param integer index of the item being rendered
-	 */
-	protected function renderBulletText($writer,$item,$index)
-	{
-		switch($this->getDisplayMode())
-		{
-			case 'Text':
-				$this->renderTextItem($writer, $item, $index);
-				break;
-			case 'HyperLink':
-				$this->renderHyperLinkItem($writer, $item, $index);
-				break;
-			case 'LinkButton':
-				$this->renderLinkButtonItem($writer, $item, $index);
-				break;
-		}
-	}
-
-	protected function renderTextItem($writer, $item, $index)
-	{
-		if($item->getEnabled())
-			$writer->write(THttpUtility::htmlEncode($item->getText()));
-		else
-		{
-			$writer->addAttribute('disabled','disabled');
-			$writer->renderBeginTag('span');
-			$writer->write(THttpUtility::htmlEncode($item->getText()));
-			$writer->renderEndTag();
-		}
-	}
-
-	protected function renderHyperLinkItem($writer, $item, $index)
-	{
-		if(!$this->_isEnabled || !$item->getEnabled())
-			$writer->addAttribute('disabled','disabled');
-		else
-		{
-			$writer->addAttribute('href',$item->getValue());
-			if(($target=$this->getTarget())!=='')
-				$writer->addAttribute('target',$target);
-		}
-		if(($accesskey=$this->getAccessKey())!=='')
-			$writer->addAttribute('accesskey',$accesskey);
-		$writer->renderBeginTag('a');
-		$writer->write(THttpUtility::htmlEncode($item->getText()));
-		$writer->renderEndTag();
-	}
-
-	protected function renderLinkButtonItem($writer, $item, $index)
-	{
-		if(!$this->_isEnabled || !$item->getEnabled())
-			$writer->addAttribute('disabled','disabled');
-		else
-		{
-			$this->_currentRenderItemIndex = $index;
-			$writer->addAttribute('id', $this->getClientID().$index);
-			$writer->addAttribute('href', "javascript:;//".$this->getClientID().$index);
-			$cs = $this->getPage()->getClientScript();
-			$cs->registerPostBackControl('Prado.WebUI.TBulletedList',$this->getPostBackOptions());
-		}
-		if(($accesskey=$this->getAccessKey())!=='')
-			$writer->addAttribute('accesskey',$accesskey);
-		$writer->renderBeginTag('a');
-		$writer->write(THttpUtility::htmlEncode($item->getText()));
-		$writer->renderEndTag();
-	}
-
-	/**
-	 * @return array postback options used for linkbuttons.
-	 */
-	protected function getPostBackOptions()
-	{
-		$options['ValidationGroup'] = $this->getValidationGroup();
-		$options['CausesValidation'] = $this->getCausesValidation();
-		$options['EventTarget'] = $this->getUniqueID();
-		$options['EventParameter'] = $this->_currentRenderItemIndex;
-		$options['ID'] = $this->getClientID().$this->_currentRenderItemIndex;
-		$options['StopEvent'] = true;
-		return $options;
-	}
-
-	protected function canCauseValidation()
-	{
-		$group = $this->getValidationGroup();
-		$hasValidators = $this->getPage()->getValidators($group)->getCount()>0;
-		return $this->getCausesValidation() && $hasValidators;
-	}
-
-	/**
-	 * @throws TNotSupportedException if this method is invoked
-	 */
-	public function setAutoPostBack($value)
-	{
-		throw new TNotSupportedException('bulletedlist_autopostback_unsupported');
-	}
-
-	/**
-	 * @throws TNotSupportedException if this method is invoked
-	 */
-	public function setSelectedIndex($index)
-	{
-		throw new TNotSupportedException('bulletedlist_selectedindex_unsupported');
-	}
-
-	/**
-	 * @throws TNotSupportedException if this method is invoked
-	 */
-	public function setSelectedIndices($indices)
-	{
-		throw new TNotSupportedException('bulletedlist_selectedindices_unsupported');
-	}
-
-	/**
-	 * @throws TNotSupportedException if this method is invoked
-	 */
-	public function setSelectedValue($value)
-	{
-		throw new TNotSupportedException('bulletedlist_selectedvalue_unsupported');
-	}
-}
-
-/**
- * TBulletedListEventParameter
- * Event parameter for {@link TBulletedList::onClick Click} event of the
- * bulleted list. The {@link getIndex Index} gives the zero-based index
- * of the item that is currently being clicked.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Revision: $  $Date: $
- * @package System.Web.UI.WebControls
- * @since 3.0
- */
-class TBulletedListEventParameter extends TEventParameter
-{
-	/**
-	 * @var integer index of the item clicked
-	 */
-	private $_index;
-
-	/**
-	 * Constructor.
-	 * @param integer index of the item clicked
-	 */
-	public function __construct($index)
-	{
-		$this->_index=$index;
-	}
-
-	/**
-	 * @return integer zero-based index of the item (rendered as a link button) that is clicked
-	 */
-	public function getIndex()
-	{
-		return $this->_index;
-	}
-}
-?>
\ No newline at end of file
+<?php
+/**
+ * TBulletedList class file
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Revision: $  $Date: $
+ * @package System.Web.UI.WebControls
+ */
+
+/**
+ * Includes TListControl class
+ */
+Prado::using('System.Web.UI.WebControls.TListControl');
+
+/**
+ * TBulletedList class
+ *
+ * TBulletedList displays items in a bullet format.
+ * The bullet style is specified by {@link setBulletStyle BulletStyle}. When
+ * the style is 'CustomImage', the {@link setBackImageUrl BulletImageUrl}
+ * specifies the image used as bullets.
+ *
+ * TBulletedList displays the item texts in three different modes, specified
+ * via {@link setDisplayMode DisplayMode}. When the mode is 'Text', the item texts
+ * are displayed as static texts; When the mode is 'HyperLink', each item
+ * is displayed as a hyperlink whose URL is given by the item value, and the
+ * {@link setTarget Target} property can be used to specify the target browser window;
+ * When the mode is 'LinkButton', each item is displayed as a link button which
+ * posts back to the page if a user clicks on that and the event {@link onClick OnClick}
+ * will be raised under such a circumstance.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Revision: $  $Date: $
+ * @package System.Web.UI.WebControls
+ * @since 3.0
+ */
+class TBulletedList extends TListControl implements IPostBackEventHandler
+{
+	/**
+	 * @var boolean cached property value of Enabled
+	 */
+	private $_isEnabled;
+	/**
+	 * @var TPostBackOptions postback options
+	 */
+	private $_postBackOptions;
+
+	private $_currentRenderItemIndex;
+
+	/**
+	 * Raises the postback event.
+	 * This method is required by {@link IPostBackEventHandler} interface.
+	 * If {@link getCausesValidation CausesValidation} is true, it will
+	 * invoke the page's {@link TPage::validate validate} method first.
+	 * It will raise {@link onClick OnClick} events.
+	 * This method is mainly used by framework and control developers.
+	 * @param TEventParameter the event parameter
+	 */
+	public function raisePostBackEvent($param)
+	{
+		if($this->getCausesValidation())
+			$this->getPage()->validate($this->getValidationGroup());
+		$this->onClick(new TBulletedListEventParameter((int)$param));
+	}
+
+	/**
+	 * @return string tag name of the bulleted list
+	 */
+	protected function getTagName()
+	{
+		switch($this->getBulletStyle())
+		{
+			case 'Numbered':
+			case 'LowerAlpha':
+			case 'UpperAlpha':
+			case 'LowerRoman':
+			case 'UpperRoman':
+				return 'ol';
+		}
+		return 'ul';
+	}
+
+	/**
+	 * 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.TBulletedList';
+	}
+
+	/**
+	 * Adds attribute name-value pairs to renderer.
+	 * This overrides the parent implementation with additional bulleted list specific attributes.
+	 * @param THtmlWriter the writer used for the rendering purpose
+	 */
+	protected function addAttributesToRender($writer)
+	{
+		$needStart=false;
+		switch($this->getBulletStyle())
+		{
+			case 'Numbered':
+				$writer->addStyleAttribute('list-style-type','decimal');
+				$needStart=true;
+				break;
+			case 'LowerAlpha':
+				$writer->addStyleAttribute('list-style-type','lower-alpha');
+				$needStart=true;
+				break;
+			case 'UpperAlpha':
+				$writer->addStyleAttribute('list-style-type','upper-alpha');
+				$needStart=true;
+				break;
+			case 'LowerRoman':
+				$writer->addStyleAttribute('list-style-type','lower-roman');
+				$needStart=true;
+				break;
+			case 'UpperRoman':
+				$writer->addStyleAttribute('list-style-type','upper-roman');
+				$needStart=true;
+				break;
+			case 'Disc':
+				$writer->addStyleAttribute('list-style-type','disc');
+				break;
+			case 'Circle':
+				$writer->addStyleAttribute('list-style-type','circle');
+				break;
+			case 'Square':
+				$writer->addStyleAttribute('list-style-type','square');
+				break;
+			case 'CustomImage':
+				$url=$this->getBulletImageUrl();
+				$writer->addStyleAttribute('list-style-image',"url($url)");
+				break;
+		}
+		if($needStart && ($start=$this->getFirstBulletNumber())!=1)
+			$writer->addAttribute('start',"$start");
+		parent::addAttributesToRender($writer);
+	}
+
+	/**
+	 * @return string image URL used for bullets when {@link getBulletStyle BulletStyle} is 'CustomImage'.
+	 */
+	public function getBulletImageUrl()
+	{
+		return $this->getViewState('BulletImageUrl','');
+	}
+
+	/**
+	 * @param string image URL used for bullets when {@link getBulletStyle BulletStyle} is 'CustomImage'.
+	 */
+	public function setBulletImageUrl($value)
+	{
+		$this->setViewState('BulletImageUrl',$value,'');
+	}
+
+	/**
+	 * @return string style of bullets. Defaults to 'NotSet'.
+	 */
+	public function getBulletStyle()
+	{
+		return $this->getViewState('BulletStyle','NotSet');
+	}
+
+	/**
+	 * @return string style of bullets. Valid values include
+	 * 'NotSet','Numbered','LowerAlpha','UpperAlpha','LowerRoman','UpperRoman','Disc','Circle','Square','CustomImage'
+	 */
+	public function setBulletStyle($value)
+	{
+		$this->setViewState('BulletStyle',TPropertyValue::ensureEnum($value,'NotSet','Numbered','LowerAlpha','UpperAlpha','LowerRoman','UpperRoman','Disc','Circle','Square','CustomImage'),'NotSet');
+	}
+
+	/**
+	 * @param string display mode of the list. Defaults to 'Text'.
+	 */
+	public function getDisplayMode()
+	{
+		return $this->getViewState('DisplayMode','Text');
+	}
+
+	/**
+	 * @return string display mode of the list. Valid values include
+	 * 'Text', 'HyperLink', 'LinkButton'.
+	 */
+	public function setDisplayMode($value)
+	{
+		$this->setViewState('DisplayMode',TPropertyValue::ensureEnum($value,'Text','HyperLink','LinkButton'),'Text');
+	}
+
+	/**
+	 * @return integer starting index when {@link getBulletStyle BulletStyle} is one of
+	 * the following: 'Numbered', 'LowerAlpha', 'UpperAlpha', 'LowerRoman', 'UpperRoman'.
+	 * Defaults to 1.
+	 */
+	public function getFirstBulletNumber()
+	{
+		return $this->getViewState('FirstBulletNumber',1);
+	}
+
+	/**
+	 * @param integer starting index when {@link getBulletStyle BulletStyle} is one of
+	 * the following: 'Numbered', 'LowerAlpha', 'UpperAlpha', 'LowerRoman', 'UpperRoman'.
+	 */
+	public function setFirstBulletNumber($value)
+	{
+		$this->setViewState('FirstBulletNumber',TPropertyValue::ensureInteger($value),1);
+	}
+
+	/**
+	 * Raises 'OnClick' event.
+	 * This method is invoked when the {@link getDisplayMode DisplayMode} is 'LinkButton'
+	 * and end-users click on one of the buttons.
+	 * @param TBulletedListEventParameter event parameter.
+	 */
+	public function onClick($param)
+	{
+		$this->raiseEvent('OnClick',$this,$param);
+	}
+
+	/**
+	 * @return string the target window or frame to display the Web page content
+	 * linked to when {@link getDisplayMode DisplayMode} is 'HyperLink' and one of
+	 * the hyperlinks is clicked.
+	 */
+	public function getTarget()
+	{
+		return $this->getViewState('Target','');
+	}
+
+	/**
+	 * @param string the target window or frame to display the Web page content
+	 * linked to when {@link getDisplayMode DisplayMode} is 'HyperLink' and one of
+	 * the hyperlinks is clicked.
+	 */
+	public function setTarget($value)
+	{
+		$this->setViewState('Target',$value,'');
+	}
+
+	/**
+	 * Renders the control.
+	 * @param THtmlWriter the writer for the rendering purpose.
+	 */
+	public function render($writer)
+	{
+		if($this->getHasItems())
+			parent::render($writer);
+	}
+
+	/**
+	 * Renders the body contents.
+	 * @param THtmlWriter the writer for the rendering purpose.
+	 */
+	public function renderContents($writer)
+	{
+		$this->_isEnabled=$this->getEnabled(true);
+		$this->_postBackOptions=$this->getPostBackOptions();
+		$writer->writeLine();
+		foreach($this->getItems() as $index=>$item)
+		{
+			if($item->getHasAttributes())
+				$writer->addAttributes($item->getAttributes());
+			$writer->renderBeginTag('li');
+			$this->renderBulletText($writer,$item,$index);
+			$writer->renderEndTag();
+			$writer->writeLine();
+		}
+	}
+
+	/**
+	 * Renders each item
+	 * @param THtmlWriter writer for the rendering purpose
+	 * @param TListItem item to be rendered
+	 * @param integer index of the item being rendered
+	 */
+	protected function renderBulletText($writer,$item,$index)
+	{
+		switch($this->getDisplayMode())
+		{
+			case 'Text':
+				$this->renderTextItem($writer, $item, $index);
+				break;
+			case 'HyperLink':
+				$this->renderHyperLinkItem($writer, $item, $index);
+				break;
+			case 'LinkButton':
+				$this->renderLinkButtonItem($writer, $item, $index);
+				break;
+		}
+	}
+
+	protected function renderTextItem($writer, $item, $index)
+	{
+		if($item->getEnabled())
+			$writer->write(THttpUtility::htmlEncode($item->getText()));
+		else
+		{
+			$writer->addAttribute('disabled','disabled');
+			$writer->renderBeginTag('span');
+			$writer->write(THttpUtility::htmlEncode($item->getText()));
+			$writer->renderEndTag();
+		}
+	}
+
+	protected function renderHyperLinkItem($writer, $item, $index)
+	{
+		if(!$this->_isEnabled || !$item->getEnabled())
+			$writer->addAttribute('disabled','disabled');
+		else
+		{
+			$writer->addAttribute('href',$item->getValue());
+			if(($target=$this->getTarget())!=='')
+				$writer->addAttribute('target',$target);
+		}
+		if(($accesskey=$this->getAccessKey())!=='')
+			$writer->addAttribute('accesskey',$accesskey);
+		$writer->renderBeginTag('a');
+		$writer->write(THttpUtility::htmlEncode($item->getText()));
+		$writer->renderEndTag();
+	}
+
+	protected function renderLinkButtonItem($writer, $item, $index)
+	{
+		if(!$this->_isEnabled || !$item->getEnabled())
+			$writer->addAttribute('disabled','disabled');
+		else
+		{
+			$this->_currentRenderItemIndex = $index;
+			$writer->addAttribute('id', $this->getClientID().$index);
+			$writer->addAttribute('href', "javascript:;//".$this->getClientID().$index);
+			$cs = $this->getPage()->getClientScript();
+			$cs->registerPostBackControl($this->getClientClassName(),$this->getPostBackOptions());
+		}
+		if(($accesskey=$this->getAccessKey())!=='')
+			$writer->addAttribute('accesskey',$accesskey);
+		$writer->renderBeginTag('a');
+		$writer->write(THttpUtility::htmlEncode($item->getText()));
+		$writer->renderEndTag();
+	}
+
+	/**
+	 * @return array postback options used for linkbuttons.
+	 */
+	protected function getPostBackOptions()
+	{
+		$options['ValidationGroup'] = $this->getValidationGroup();
+		$options['CausesValidation'] = $this->getCausesValidation();
+		$options['EventTarget'] = $this->getUniqueID();
+		$options['EventParameter'] = $this->_currentRenderItemIndex;
+		$options['ID'] = $this->getClientID().$this->_currentRenderItemIndex;
+		$options['StopEvent'] = true;
+		return $options;
+	}
+
+	protected function canCauseValidation()
+	{
+		$group = $this->getValidationGroup();
+		$hasValidators = $this->getPage()->getValidators($group)->getCount()>0;
+		return $this->getCausesValidation() && $hasValidators;
+	}
+
+	/**
+	 * @throws TNotSupportedException if this method is invoked
+	 */
+	public function setAutoPostBack($value)
+	{
+		throw new TNotSupportedException('bulletedlist_autopostback_unsupported');
+	}
+
+	/**
+	 * @throws TNotSupportedException if this method is invoked
+	 */
+	public function setSelectedIndex($index)
+	{
+		throw new TNotSupportedException('bulletedlist_selectedindex_unsupported');
+	}
+
+	/**
+	 * @throws TNotSupportedException if this method is invoked
+	 */
+	public function setSelectedIndices($indices)
+	{
+		throw new TNotSupportedException('bulletedlist_selectedindices_unsupported');
+	}
+
+	/**
+	 * @throws TNotSupportedException if this method is invoked
+	 */
+	public function setSelectedValue($value)
+	{
+		throw new TNotSupportedException('bulletedlist_selectedvalue_unsupported');
+	}
+}
+
+/**
+ * TBulletedListEventParameter
+ * Event parameter for {@link TBulletedList::onClick Click} event of the
+ * bulleted list. The {@link getIndex Index} gives the zero-based index
+ * of the item that is currently being clicked.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Revision: $  $Date: $
+ * @package System.Web.UI.WebControls
+ * @since 3.0
+ */
+class TBulletedListEventParameter extends TEventParameter
+{
+	/**
+	 * @var integer index of the item clicked
+	 */
+	private $_index;
+
+	/**
+	 * Constructor.
+	 * @param integer index of the item clicked
+	 */
+	public function __construct($index)
+	{
+		$this->_index=$index;
+	}
+
+	/**
+	 * @return integer zero-based index of the item (rendered as a link button) that is clicked
+	 */
+	public function getIndex()
+	{
+		return $this->_index;
+	}
+}
+?>
diff --git a/framework/Web/UI/WebControls/TButton.php b/framework/Web/UI/WebControls/TButton.php
index 3bc11c3c..b77ca111 100644
--- a/framework/Web/UI/WebControls/TButton.php
+++ b/framework/Web/UI/WebControls/TButton.php
@@ -1,257 +1,267 @@
-<?php
-/**
- * TButton class file.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright &copy; 2005 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Revision: $  $Date: $
- * @package System.Web.UI.WebControls
- */
-
-/**
- * TButton class
- *
- * TButton creates a click button on the page. It is used to submit data to a page.
- * You can create either a <b>submit</b> button or a <b>command</b> button.
- *
- * A <b>command</b> button has a command name (specified by
- * the {@link setCommandName CommandName} property) and and a command parameter
- * (specified by {@link setCommandParameter CommandParameter} property)
- * associated with the button. This allows you to create multiple TButton
- * components on a Web page and programmatically determine which one is clicked
- * with what parameter. You can provide an event handler for
- * {@link onCommand OnCommand} event to programmatically control the actions performed
- * when the command button is clicked. In the event handler, you can determine
- * the {@link setCommandName CommandName} property value and
- * the {@link setCommandParameter CommandParameter} property value
- * through the {@link TCommandParameter::getName Name} and
- * {@link TCommandParameter::getParameter Parameter} properties of the event
- * parameter which is of type {@link TCommandEventParameter}.
- *
- * A <b>submit</b> button does not have a command name associated with the button
- * and clicking on it simply posts the Web page back to the server.
- * By default, a TButton component is a submit button.
- * You can provide an event handler for the {@link onClick OnClick} event
- * to programmatically control the actions performed when the submit button is clicked.
- *
- * Clicking on button can trigger form validation, if
- * {@link setCausesValidation CausesValidation} is true.
- * And the validation may be restricted within a certain group of validator
- * controls by setting {@link setValidationGroup ValidationGroup} property.
- * If validation is successful, the data will be post back to the same page.
- *
- * TButton displays the {@link setText Text} property as the button caption.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Revision: $  $Date: $
- * @package System.Web.UI.WebControls
- * @since 3.0
- */
-class TButton extends TWebControl implements IPostBackEventHandler, IButtonControl
-{
-	/**
-	 * @return string tag name of the button
-	 */
-	protected function getTagName()
-	{
-		return 'input';
-	}
-
-	/**
-	 * Adds attribute name-value pairs to renderer.
-	 * This overrides the parent implementation with additional button specific attributes.
-	 * @param THtmlWriter the writer used for the rendering purpose
-	 */
-	protected function addAttributesToRender($writer)
-	{
-		$page=$this->getPage();
-		$page->ensureRenderInForm($this);
-		$writer->addAttribute('type','submit');
-		if(($uniqueID=$this->getUniqueID())!=='')
-			$writer->addAttribute('name',$uniqueID);
-		$writer->addAttribute('value',$this->getText());
-		if($this->getEnabled(true) )
-			$this->renderClientControlScript($writer);
-		else if($this->getEnabled()) // in this case, parent will not render 'disabled'
-			$writer->addAttribute('disabled','disabled');
-
-		parent::addAttributesToRender($writer);
-	}
-
-	/**
-	 * Renders the client-script code.
-	 */
-	protected function renderClientControlScript($writer)
-	{
-		if($this->canCauseValidation())
-		{
-			$writer->addAttribute('id',$this->getClientID());
-			$cs = $this->getPage()->getClientScript();
-			$cs->registerPostBackControl('Prado.WebUI.TButton',$this->getPostBackOptions());
-		}
-	}
-
-	/**
-	 * @return boolean whether to perform validation if the button is clicked
-	 */
-	protected function canCauseValidation()
-	{
-		if($this->getCausesValidation())
-		{
-			$group=$this->getValidationGroup();
-			return $this->getPage()->getValidators($group)->getCount()>0;
-		}
-		else
-			return false;
-	}
-
-	/**
-	 * Returns postback specifications for the button.
-	 * This method is used by framework and control developers.
-	 * @return array parameters about how the button defines its postback behavior.
-	 */
-	protected function getPostBackOptions()
-	{
-		$options['ID']=$this->getClientID();
-		$options['CausesValidation']=$this->getCausesValidation();
-		$options['EventTarget'] = $this->getUniqueID();
-		$options['ValidationGroup']=$this->getValidationGroup();
-
-		return $options;
-	}
-
-	/**
-	 * Renders the body content enclosed between the control tag.
-	 * This overrides the parent implementation with nothing to be rendered.
-	 * @param THtmlWriter the writer used for the rendering purpose
-	 */
-	public function renderContents($writer)
-	{
-	}
-
-	/**
-	 * This method is invoked when the button is clicked.
-	 * The method raises 'OnClick' event to fire up the event handlers.
-	 * If you override this method, be sure to call the parent implementation
-	 * so that the event handler can be invoked.
-	 * @param TEventParameter event parameter to be passed to the event handlers
-	 */
-	public function onClick($param)
-	{
-		$this->raiseEvent('OnClick',$this,$param);
-	}
-
-	/**
-	 * This method is invoked when the button is clicked.
-	 * The method raises 'OnCommand' event to fire up the event handlers.
-	 * If you override this method, be sure to call the parent implementation
-	 * so that the event handlers can be invoked.
-	 * @param TCommandEventParameter event parameter to be passed to the event handlers
-	 */
-	public function onCommand($param)
-	{
-		$this->raiseEvent('OnCommand',$this,$param);
-		$this->raiseBubbleEvent($this,$param);
-	}
-
-	/**
-	 * Raises the postback event.
-	 * This method is required by {@link IPostBackEventHandler} interface.
-	 * If {@link getCausesValidation CausesValidation} is true, it will
-	 * invoke the page's {@link TPage::validate validate} method first.
-	 * It will raise {@link onClick OnClick} and {@link onCommand OnCommand} events.
-	 * This method is mainly used by framework and control developers.
-	 * @param TEventParameter the event parameter
-	 */
-	public function raisePostBackEvent($param)
-	{
-		if($this->getCausesValidation())
-			$this->getPage()->validate($this->getValidationGroup());
-		$this->onClick(null);
-		$this->onCommand(new TCommandEventParameter($this->getCommandName(),$this->getCommandParameter()));
-	}
-
-	/**
-	 * @return string caption of the button
-	 */
-	public function getText()
-	{
-		return $this->getViewState('Text','');
-	}
-
-	/**
-	 * @param string caption of the button
-	 */
-	public function setText($value)
-	{
-		$this->setViewState('Text',$value,'');
-	}
-
-	/**
-	 * @return boolean whether postback event trigger by this button will cause input validation, default is true
-	 */
-	public function getCausesValidation()
-	{
-		return $this->getViewState('CausesValidation',true);
-	}
-
-	/**
-	 * @param boolean whether postback event trigger by this button will cause input validation
-	 */
-	public function setCausesValidation($value)
-	{
-		$this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true);
-	}
-
-	/**
-	 * @return string the command name associated with the {@link onCommand OnCommand} event.
-	 */
-	public function getCommandName()
-	{
-		return $this->getViewState('CommandName','');
-	}
-
-	/**
-	 * @param string the command name associated with the {@link onCommand OnCommand} event.
-	 */
-	public function setCommandName($value)
-	{
-		$this->setViewState('CommandName',$value,'');
-	}
-
-	/**
-	 * @return string the parameter associated with the {@link onCommand OnCommand} event
-	 */
-	public function getCommandParameter()
-	{
-		return $this->getViewState('CommandParameter','');
-	}
-
-	/**
-	 * @param string the parameter associated with the {@link onCommand OnCommand} event.
-	 */
-	public function setCommandParameter($value)
-	{
-		$this->setViewState('CommandParameter',$value,'');
-	}
-
-	/**
-	 * @return string the group of validators which the button causes validation upon postback
-	 */
-	public function getValidationGroup()
-	{
-		return $this->getViewState('ValidationGroup','');
-	}
-
-	/**
-	 * @param string the group of validators which the button causes validation upon postback
-	 */
-	public function setValidationGroup($value)
-	{
-		$this->setViewState('ValidationGroup',$value,'');
-	}
-}
-
-?>
\ No newline at end of file
+<?php
+/**
+ * TButton class file.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Revision: $  $Date: $
+ * @package System.Web.UI.WebControls
+ */
+
+/**
+ * TButton class
+ *
+ * TButton creates a click button on the page. It is used to submit data to a page.
+ * You can create either a <b>submit</b> button or a <b>command</b> button.
+ *
+ * A <b>command</b> button has a command name (specified by
+ * the {@link setCommandName CommandName} property) and and a command parameter
+ * (specified by {@link setCommandParameter CommandParameter} property)
+ * associated with the button. This allows you to create multiple TButton
+ * components on a Web page and programmatically determine which one is clicked
+ * with what parameter. You can provide an event handler for
+ * {@link onCommand OnCommand} event to programmatically control the actions performed
+ * when the command button is clicked. In the event handler, you can determine
+ * the {@link setCommandName CommandName} property value and
+ * the {@link setCommandParameter CommandParameter} property value
+ * through the {@link TCommandParameter::getName Name} and
+ * {@link TCommandParameter::getParameter Parameter} properties of the event
+ * parameter which is of type {@link TCommandEventParameter}.
+ *
+ * A <b>submit</b> button does not have a command name associated with the button
+ * and clicking on it simply posts the Web page back to the server.
+ * By default, a TButton component is a submit button.
+ * You can provide an event handler for the {@link onClick OnClick} event
+ * to programmatically control the actions performed when the submit button is clicked.
+ *
+ * Clicking on button can trigger form validation, if
+ * {@link setCausesValidation CausesValidation} is true.
+ * And the validation may be restricted within a certain group of validator
+ * controls by setting {@link setValidationGroup ValidationGroup} property.
+ * If validation is successful, the data will be post back to the same page.
+ *
+ * TButton displays the {@link setText Text} property as the button caption.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Revision: $  $Date: $
+ * @package System.Web.UI.WebControls
+ * @since 3.0
+ */
+class TButton extends TWebControl implements IPostBackEventHandler, IButtonControl
+{
+	/**
+	 * @return string tag name of the button
+	 */
+	protected function getTagName()
+	{
+		return 'input';
+	}
+
+	/**
+	 * Adds attribute name-value pairs to renderer.
+	 * This overrides the parent implementation with additional button specific attributes.
+	 * @param THtmlWriter the writer used for the rendering purpose
+	 */
+	protected function addAttributesToRender($writer)
+	{
+		$page=$this->getPage();
+		$page->ensureRenderInForm($this);
+		$writer->addAttribute('type','submit');
+		if(($uniqueID=$this->getUniqueID())!=='')
+			$writer->addAttribute('name',$uniqueID);
+		$writer->addAttribute('value',$this->getText());
+		if($this->getEnabled(true) )
+			$this->renderClientControlScript($writer);
+		else if($this->getEnabled()) // in this case, parent will not render 'disabled'
+			$writer->addAttribute('disabled','disabled');
+
+		parent::addAttributesToRender($writer);
+	}
+
+	/**
+	 * Renders the client-script code.
+	 */
+	protected function renderClientControlScript($writer)
+	{
+		if($this->canCauseValidation())
+		{
+			$writer->addAttribute('id',$this->getClientID());
+			$cs = $this->getPage()->getClientScript();
+			$cs->registerPostBackControl($this->getClientClassName(),$this->getPostBackOptions());
+		}
+	}
+
+	/**
+	 * 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.TButton';
+	}
+
+	/**
+	 * @return boolean whether to perform validation if the button is clicked
+	 */
+	protected function canCauseValidation()
+	{
+		if($this->getCausesValidation())
+		{
+			$group=$this->getValidationGroup();
+			return $this->getPage()->getValidators($group)->getCount()>0;
+		}
+		else
+			return false;
+	}
+
+	/**
+	 * Returns postback specifications for the button.
+	 * This method is used by framework and control developers.
+	 * @return array parameters about how the button defines its postback behavior.
+	 */
+	protected function getPostBackOptions()
+	{
+		$options['ID']=$this->getClientID();
+		$options['CausesValidation']=$this->getCausesValidation();
+		$options['EventTarget'] = $this->getUniqueID();
+		$options['ValidationGroup']=$this->getValidationGroup();
+
+		return $options;
+	}
+
+	/**
+	 * Renders the body content enclosed between the control tag.
+	 * This overrides the parent implementation with nothing to be rendered.
+	 * @param THtmlWriter the writer used for the rendering purpose
+	 */
+	public function renderContents($writer)
+	{
+	}
+
+	/**
+	 * This method is invoked when the button is clicked.
+	 * The method raises 'OnClick' event to fire up the event handlers.
+	 * If you override this method, be sure to call the parent implementation
+	 * so that the event handler can be invoked.
+	 * @param TEventParameter event parameter to be passed to the event handlers
+	 */
+	public function onClick($param)
+	{
+		$this->raiseEvent('OnClick',$this,$param);
+	}
+
+	/**
+	 * This method is invoked when the button is clicked.
+	 * The method raises 'OnCommand' event to fire up the event handlers.
+	 * If you override this method, be sure to call the parent implementation
+	 * so that the event handlers can be invoked.
+	 * @param TCommandEventParameter event parameter to be passed to the event handlers
+	 */
+	public function onCommand($param)
+	{
+		$this->raiseEvent('OnCommand',$this,$param);
+		$this->raiseBubbleEvent($this,$param);
+	}
+
+	/**
+	 * Raises the postback event.
+	 * This method is required by {@link IPostBackEventHandler} interface.
+	 * If {@link getCausesValidation CausesValidation} is true, it will
+	 * invoke the page's {@link TPage::validate validate} method first.
+	 * It will raise {@link onClick OnClick} and {@link onCommand OnCommand} events.
+	 * This method is mainly used by framework and control developers.
+	 * @param TEventParameter the event parameter
+	 */
+	public function raisePostBackEvent($param)
+	{
+		if($this->getCausesValidation())
+			$this->getPage()->validate($this->getValidationGroup());
+		$this->onClick(null);
+		$this->onCommand(new TCommandEventParameter($this->getCommandName(),$this->getCommandParameter()));
+	}
+
+	/**
+	 * @return string caption of the button
+	 */
+	public function getText()
+	{
+		return $this->getViewState('Text','');
+	}
+
+	/**
+	 * @param string caption of the button
+	 */
+	public function setText($value)
+	{
+		$this->setViewState('Text',$value,'');
+	}
+
+	/**
+	 * @return boolean whether postback event trigger by this button will cause input validation, default is true
+	 */
+	public function getCausesValidation()
+	{
+		return $this->getViewState('CausesValidation',true);
+	}
+
+	/**
+	 * @param boolean whether postback event trigger by this button will cause input validation
+	 */
+	public function setCausesValidation($value)
+	{
+		$this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true);
+	}
+
+	/**
+	 * @return string the command name associated with the {@link onCommand OnCommand} event.
+	 */
+	public function getCommandName()
+	{
+		return $this->getViewState('CommandName','');
+	}
+
+	/**
+	 * @param string the command name associated with the {@link onCommand OnCommand} event.
+	 */
+	public function setCommandName($value)
+	{
+		$this->setViewState('CommandName',$value,'');
+	}
+
+	/**
+	 * @return string the parameter associated with the {@link onCommand OnCommand} event
+	 */
+	public function getCommandParameter()
+	{
+		return $this->getViewState('CommandParameter','');
+	}
+
+	/**
+	 * @param string the parameter associated with the {@link onCommand OnCommand} event.
+	 */
+	public function setCommandParameter($value)
+	{
+		$this->setViewState('CommandParameter',$value,'');
+	}
+
+	/**
+	 * @return string the group of validators which the button causes validation upon postback
+	 */
+	public function getValidationGroup()
+	{
+		return $this->getViewState('ValidationGroup','');
+	}
+
+	/**
+	 * @param string the group of validators which the button causes validation upon postback
+	 */
+	public function setValidationGroup($value)
+	{
+		$this->setViewState('ValidationGroup',$value,'');
+	}
+}
+
+?>
diff --git a/framework/Web/UI/WebControls/TCheckBox.php b/framework/Web/UI/WebControls/TCheckBox.php
index 8a8ace7a..9f26b02c 100644
--- a/framework/Web/UI/WebControls/TCheckBox.php
+++ b/framework/Web/UI/WebControls/TCheckBox.php
@@ -1,397 +1,407 @@
-<?php
-/**
- * TCheckBox class file
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright &copy; 2005 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Revision: $  $Date: $
- * @package System.Web.UI.WebControls
- */
-
-/**
- * TCheckBox class
- *
- * TCheckBox displays a check box on the page.
- * You can specify the caption to display beside the check box by setting
- * the {@link setText Text} property.  The caption can appear either on the right
- * or left of the check box, which is determined by the {@link setTextAlign TextAlign}
- * property.
- *
- * To determine whether the TCheckBox component is checked, test the {@link getChecked Checked}
- * property. The {@link onCheckedChanged OnCheckedChanged} event is raised when
- * the {@link getChecked Checked} state of the TCheckBox component changes
- * between posts to the server. You can provide an event handler for
- * the {@link onCheckedChanged OnCheckedChanged} event to  to programmatically
- * control the actions performed when the state of the TCheckBox component changes
- * between posts to the server.
- *
- * If {@link setAutoPostBack AutoPostBack} is set true, changing the check box state
- * will cause postback action. And if {@link setCausesValidation CausesValidation}
- * is true, validation will also be processed, which can be further restricted within
- * a {@link setValidationGroup ValidationGroup}.
- *
- * Note, {@link setText Text} is rendered as is. Make sure it does not contain unwanted characters
- * that may bring security vulnerabilities.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Revision: $  $Date: $
- * @package System.Web.UI.WebControls
- * @since 3.0
- */
-class TCheckBox extends TWebControl implements IPostBackDataHandler, IValidatable
-{
-	/**
-	 * @return string tag name of the button
-	 */
-	protected function getTagName()
-	{
-		return 'input';
-	}
-
-	/**
-	 * 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)
-	{
-		$checked=$this->getChecked();
-		if(isset($values[$key])!=$checked)
-		{
-			$this->setChecked(!$checked);
-			return true;
-		}
-		else
-			return false;
-	}
-
-	/**
-	 * Raises postdata changed event.
-	 * This method raises {@link onCheckedChanged OnCheckedChanged} event.
-	 * This method is primarly used by framework developers.
-	 */
-	public function raisePostDataChangedEvent()
-	{
-		if($this->getAutoPostBack() && $this->getCausesValidation())
-			$this->getPage()->validate($this->getValidationGroup());
-		$this->onCheckedChanged(null);
-	}
-
-	/**
-	 * Raises <b>OnCheckedChanged</b> event when {@link getChecked Checked} changes value during postback.
-	 * If you override this method, be sure to call the parent implementation
-	 * so that the event delegates can be invoked.
-	 * @param TEventParameter event parameter to be passed to the event handlers
-	 */
-	public function onCheckedChanged($param)
-	{
-		$this->raiseEvent('OnCheckedChanged',$this,$param);
-	}
-
-	/**
-	 * Registers the checkbox to receive postback data during postback.
-	 * This is necessary because a checkbox if unchecked, when postback,
-	 * does not have direct mapping between post data and the checkbox name.
-	 *
-	 * This method overrides the parent implementation and is invoked before render.
-	 * @param mixed event parameter
-	 */
-	public function onPreRender($param)
-	{
-		parent::onPreRender($param);
-		if($this->getEnabled(true))
-			$this->getPage()->registerRequiresPostData($this);
-	}
-
-	/**
-	 * Returns the value of the property that needs validation.
-	 * @return mixed the property value to be validated
-	 */
-	public function getValidationPropertyValue()
-	{
-		return $this->getChecked();
-	}
-
-	/**
-	 * @return string the text caption of the checkbox
-	 */
-	public function getText()
-	{
-		return $this->getViewState('Text','');
-	}
-
-	/**
-	 * Sets the text caption of the checkbox.
-	 * @param string the text caption to be set
-	 */
-	public function setText($value)
-	{
-		$this->setViewState('Text',$value,'');
-	}
-
-	/**
-	 * @return string the alignment (Left or Right) of the text caption, defaults to Right.
-	 */
-	public function getTextAlign()
-	{
-		return $this->getViewState('TextAlign','Right');
-	}
-
-	/**
-	 * @param string the alignment of the text caption. Valid values include Left and Right.
-	 */
-	public function setTextAlign($value)
-	{
-		$this->setViewState('TextAlign',TPropertyValue::ensureEnum($value,array('Left','Right')),'Right');
-	}
-
-	/**
-	 * @return boolean whether the checkbox is checked
-	 */
-	public function getChecked()
-	{
-		return $this->getViewState('Checked',false);
-	}
-
-	/**
-	 * Sets a value indicating whether the checkbox is to be checked or not.
-	 * @param boolean whether the checkbox is to be checked or not.
-	 */
-	public function setChecked($value)
-	{
-		$this->setViewState('Checked',TPropertyValue::ensureBoolean($value),false);
-	}
-
-	/**
-	 * @return boolean whether clicking on the checkbox will post the page.
-	 */
-	public function getAutoPostBack()
-	{
-		return $this->getViewState('AutoPostBack',false);
-	}
-
-	/**
-	 * Sets a value indicating whether clicking on the checkbox will post the page.
-	 * @param boolean whether clicking on the checkbox will post the page.
-	 */
-	public function setAutoPostBack($value)
-	{
-		$this->setViewState('AutoPostBack',TPropertyValue::ensureBoolean($value),false);
-	}
-
-	/**
-	 * @return boolean whether postback event triggered by this checkbox will cause input validation, default is true.
-	 */
-	public function getCausesValidation()
-	{
-		return $this->getViewState('CausesValidation',true);
-	}
-
-	/**
-	 * Sets the value indicating whether postback event trigger by this checkbox will cause input validation.
-	 * @param boolean whether postback event trigger by this checkbox will cause input validation.
-	 */
-	public function setCausesValidation($value)
-	{
-		$this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true);
-	}
-
-	/**
-	 * @return string the group of validators which the checkbox causes validation upon postback
-	 */
-	public function getValidationGroup()
-	{
-		return $this->getViewState('ValidationGroup','');
-	}
-
-	/**
-	 * @param string the group of validators which the checkbox causes validation upon postback
-	 */
-	public function setValidationGroup($value)
-	{
-		$this->setViewState('ValidationGroup',$value,'');
-	}
-
-	/**
-	 * Renders the checkbox control.
-	 * This method overrides the parent implementation by rendering a checkbox input element
-	 * and a span element if needed.
-	 * @param THtmlWriter the writer used for the rendering purpose
-	 */
-	public function render($writer)
-	{
-		$this->getPage()->ensureRenderInForm($this);
-		$needSpan=false;
-		if($this->getHasStyle())
-		{
-			$this->getStyle()->addAttributesToRender($writer);
-			$needSpan=true;
-		}
-		if(($tooltip=$this->getToolTip())!=='')
-		{
-			$writer->addAttribute('title',$tooltip);
-			$needSpan=true;
-		}
-		if($this->getHasAttributes())
-		{
-			$attributes=$this->getAttributes();
-			$value=$attributes->remove('value');
-			// onclick js should only be added to input tag
-			$onclick=$attributes->remove('onclick');
-			if($attributes->getCount())
-			{
-				$writer->addAttributes($attributes);
-				$needSpan=true;
-			}
-			if($value!==null)
-				$attributes->add('value',$value);
-		}
-		else
-			$onclick='';
-		if($needSpan)
-			$writer->renderBeginTag('span');
-		$clientID=$this->getClientID();
-		if(($text=$this->getText())!=='')
-		{
-			if($this->getTextAlign()==='Left')
-			{
-				$this->renderLabel($writer,$clientID,$text);
-				$this->renderInputTag($writer,$clientID,$onclick);
-			}
-			else
-			{
-				$this->renderInputTag($writer,$clientID,$onclick);
-				$this->renderLabel($writer,$clientID,$text);
-			}
-		}
-		else
-			$this->renderInputTag($writer,$clientID,$onclick);
-		if($needSpan)
-			$writer->renderEndTag();
-	}
-
-	/**
-	 * @return TMap list of attributes to be rendered for label beside the checkbox
-	 */
-	public function getLabelAttributes()
-	{
-		if($attributes=$this->getViewState('LabelAttributes',null))
-			return $attributes;
-		else
-		{
-			$attributes=new TAttributeCollection;
-			$this->setViewState('LabelAttributes',$attributes,null);
-			return $attributes;
-		}
-	}
-
-	/**
-	 * @return TMap list of attributes to be rendered for the checkbox
-	 */
-	public function getInputAttributes()
-	{
-		if($attributes=$this->getViewState('InputAttributes',null))
-			return $attributes;
-		else
-		{
-			$attributes=new TAttributeCollection;
-			$this->setViewState('InputAttributes',$attributes,null);
-			return $attributes;
-		}
-	}
-
-	/**
-	 * @return string the value attribute to be rendered
-	 */
-	protected function getValueAttribute()
-	{
-		$attributes=$this->getViewState('InputAttributes',null);
-		if($attributes && $attributes->contains('value'))
-			return $attributes->itemAt('value');
-		else if($this->hasAttribute('value'))
-			return $this->getAttribute('value');
-		else
-			return '';
-	}
-
-	/**
-	 * Renders a label beside the checkbox.
-	 * @param THtmlWriter the writer for the rendering purpose
-	 * @param string checkbox id
-	 * @param string label text
-	 */
-	protected function renderLabel($writer,$clientID,$text)
-	{
-		$writer->addAttribute('for',$clientID);
-		if($attributes=$this->getViewState('LabelAttributes',null))
-			$writer->addAttributes($attributes);
-		$writer->renderBeginTag('label');
-		$writer->write($text);
-		$writer->renderEndTag();
-	}
-
-	/**
-	 * Renders a checkbox input element.
-	 * @param THtmlWriter the writer for the rendering purpose
-	 * @param string checkbox id
-	 * @param string onclick js
-	 */
-	protected function renderInputTag($writer,$clientID,$onclick)
-	{
-		if($clientID!=='')
-			$writer->addAttribute('id',$clientID);
-		$writer->addAttribute('type','checkbox');
-		if(($value = $this->getValueAttribute()) !== '')
-			$writer->addAttribute('value',$value);
-		if($onclick!=='')
-			$writer->addAttribute('onclick',$onclick);
-		if(($uniqueID=$this->getUniqueID())!=='')
-			$writer->addAttribute('name',$uniqueID);
-		if($this->getChecked())
-			$writer->addAttribute('checked','checked');
-		if(!$this->getEnabled(true))
-			$writer->addAttribute('disabled','disabled');
-
-		$page=$this->getPage();
-		if($this->getEnabled(true) && $this->getAutoPostBack() && $page->getClientSupportsJavaScript())
-			$this->renderClientControlScript($writer);
-
-		if(($accesskey=$this->getAccessKey())!=='')
-			$writer->addAttribute('accesskey',$accesskey);
-		if(($tabindex=$this->getTabIndex())>0)
-			$writer->addAttribute('tabindex',"$tabindex");
-		if($attributes=$this->getViewState('InputAttributes',null))
-			$writer->addAttributes($attributes);
-		$writer->renderBeginTag('input');
-		$writer->renderEndTag();
-	}
-
-	/**
-	 * Renders the client-script code.
-	 */
-	protected function renderClientControlScript($writer)
-	{
-		$cs = $this->getPage()->getClientScript();
-		$cs->registerPostBackControl('Prado.WebUI.TCheckBox',$this->getPostBackOptions());
-	}
-
-	/**
-	 * Gets the post back options for this checkbox.
-	 * @return array
-	 */
-	protected function getPostBackOptions()
-	{
-		$options['ID'] = $this->getClientID();
-		$options['ValidationGroup'] = $this->getValidationGroup();
-		$options['CausesValidation'] = $this->getCausesValidation();
-		$options['EventTarget'] = $this->getUniqueID();
-		return $options;
-	}
-
-}
-
-?>
\ No newline at end of file
+<?php
+/**
+ * TCheckBox class file
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Revision: $  $Date: $
+ * @package System.Web.UI.WebControls
+ */
+
+/**
+ * TCheckBox class
+ *
+ * TCheckBox displays a check box on the page.
+ * You can specify the caption to display beside the check box by setting
+ * the {@link setText Text} property.  The caption can appear either on the right
+ * or left of the check box, which is determined by the {@link setTextAlign TextAlign}
+ * property.
+ *
+ * To determine whether the TCheckBox component is checked, test the {@link getChecked Checked}
+ * property. The {@link onCheckedChanged OnCheckedChanged} event is raised when
+ * the {@link getChecked Checked} state of the TCheckBox component changes
+ * between posts to the server. You can provide an event handler for
+ * the {@link onCheckedChanged OnCheckedChanged} event to  to programmatically
+ * control the actions performed when the state of the TCheckBox component changes
+ * between posts to the server.
+ *
+ * If {@link setAutoPostBack AutoPostBack} is set true, changing the check box state
+ * will cause postback action. And if {@link setCausesValidation CausesValidation}
+ * is true, validation will also be processed, which can be further restricted within
+ * a {@link setValidationGroup ValidationGroup}.
+ *
+ * Note, {@link setText Text} is rendered as is. Make sure it does not contain unwanted characters
+ * that may bring security vulnerabilities.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Revision: $  $Date: $
+ * @package System.Web.UI.WebControls
+ * @since 3.0
+ */
+class TCheckBox extends TWebControl implements IPostBackDataHandler, IValidatable
+{
+	/**
+	 * @return string tag name of the button
+	 */
+	protected function getTagName()
+	{
+		return 'input';
+	}
+
+	/**
+	 * 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)
+	{
+		$checked=$this->getChecked();
+		if(isset($values[$key])!=$checked)
+		{
+			$this->setChecked(!$checked);
+			return true;
+		}
+		else
+			return false;
+	}
+
+	/**
+	 * Raises postdata changed event.
+	 * This method raises {@link onCheckedChanged OnCheckedChanged} event.
+	 * This method is primarly used by framework developers.
+	 */
+	public function raisePostDataChangedEvent()
+	{
+		if($this->getAutoPostBack() && $this->getCausesValidation())
+			$this->getPage()->validate($this->getValidationGroup());
+		$this->onCheckedChanged(null);
+	}
+
+	/**
+	 * Raises <b>OnCheckedChanged</b> event when {@link getChecked Checked} changes value during postback.
+	 * If you override this method, be sure to call the parent implementation
+	 * so that the event delegates can be invoked.
+	 * @param TEventParameter event parameter to be passed to the event handlers
+	 */
+	public function onCheckedChanged($param)
+	{
+		$this->raiseEvent('OnCheckedChanged',$this,$param);
+	}
+
+	/**
+	 * Registers the checkbox to receive postback data during postback.
+	 * This is necessary because a checkbox if unchecked, when postback,
+	 * does not have direct mapping between post data and the checkbox name.
+	 *
+	 * This method overrides the parent implementation and is invoked before render.
+	 * @param mixed event parameter
+	 */
+	public function onPreRender($param)
+	{
+		parent::onPreRender($param);
+		if($this->getEnabled(true))
+			$this->getPage()->registerRequiresPostData($this);
+	}
+
+	/**
+	 * Returns the value of the property that needs validation.
+	 * @return mixed the property value to be validated
+	 */
+	public function getValidationPropertyValue()
+	{
+		return $this->getChecked();
+	}
+
+	/**
+	 * @return string the text caption of the checkbox
+	 */
+	public function getText()
+	{
+		return $this->getViewState('Text','');
+	}
+
+	/**
+	 * Sets the text caption of the checkbox.
+	 * @param string the text caption to be set
+	 */
+	public function setText($value)
+	{
+		$this->setViewState('Text',$value,'');
+	}
+
+	/**
+	 * @return string the alignment (Left or Right) of the text caption, defaults to Right.
+	 */
+	public function getTextAlign()
+	{
+		return $this->getViewState('TextAlign','Right');
+	}
+
+	/**
+	 * @param string the alignment of the text caption. Valid values include Left and Right.
+	 */
+	public function setTextAlign($value)
+	{
+		$this->setViewState('TextAlign',TPropertyValue::ensureEnum($value,array('Left','Right')),'Right');
+	}
+
+	/**
+	 * @return boolean whether the checkbox is checked
+	 */
+	public function getChecked()
+	{
+		return $this->getViewState('Checked',false);
+	}
+
+	/**
+	 * Sets a value indicating whether the checkbox is to be checked or not.
+	 * @param boolean whether the checkbox is to be checked or not.
+	 */
+	public function setChecked($value)
+	{
+		$this->setViewState('Checked',TPropertyValue::ensureBoolean($value),false);
+	}
+
+	/**
+	 * @return boolean whether clicking on the checkbox will post the page.
+	 */
+	public function getAutoPostBack()
+	{
+		return $this->getViewState('AutoPostBack',false);
+	}
+
+	/**
+	 * Sets a value indicating whether clicking on the checkbox will post the page.
+	 * @param boolean whether clicking on the checkbox will post the page.
+	 */
+	public function setAutoPostBack($value)
+	{
+		$this->setViewState('AutoPostBack',TPropertyValue::ensureBoolean($value),false);
+	}
+
+	/**
+	 * @return boolean whether postback event triggered by this checkbox will cause input validation, default is true.
+	 */
+	public function getCausesValidation()
+	{
+		return $this->getViewState('CausesValidation',true);
+	}
+
+	/**
+	 * Sets the value indicating whether postback event trigger by this checkbox will cause input validation.
+	 * @param boolean whether postback event trigger by this checkbox will cause input validation.
+	 */
+	public function setCausesValidation($value)
+	{
+		$this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true);
+	}
+
+	/**
+	 * @return string the group of validators which the checkbox causes validation upon postback
+	 */
+	public function getValidationGroup()
+	{
+		return $this->getViewState('ValidationGroup','');
+	}
+
+	/**
+	 * @param string the group of validators which the checkbox causes validation upon postback
+	 */
+	public function setValidationGroup($value)
+	{
+		$this->setViewState('ValidationGroup',$value,'');
+	}
+
+	/**
+	 * Renders the checkbox control.
+	 * This method overrides the parent implementation by rendering a checkbox input element
+	 * and a span element if needed.
+	 * @param THtmlWriter the writer used for the rendering purpose
+	 */
+	public function render($writer)
+	{
+		$this->getPage()->ensureRenderInForm($this);
+		$needSpan=false;
+		if($this->getHasStyle())
+		{
+			$this->getStyle()->addAttributesToRender($writer);
+			$needSpan=true;
+		}
+		if(($tooltip=$this->getToolTip())!=='')
+		{
+			$writer->addAttribute('title',$tooltip);
+			$needSpan=true;
+		}
+		if($this->getHasAttributes())
+		{
+			$attributes=$this->getAttributes();
+			$value=$attributes->remove('value');
+			// onclick js should only be added to input tag
+			$onclick=$attributes->remove('onclick');
+			if($attributes->getCount())
+			{
+				$writer->addAttributes($attributes);
+				$needSpan=true;
+			}
+			if($value!==null)
+				$attributes->add('value',$value);
+		}
+		else
+			$onclick='';
+		if($needSpan)
+			$writer->renderBeginTag('span');
+		$clientID=$this->getClientID();
+		if(($text=$this->getText())!=='')
+		{
+			if($this->getTextAlign()==='Left')
+			{
+				$this->renderLabel($writer,$clientID,$text);
+				$this->renderInputTag($writer,$clientID,$onclick);
+			}
+			else
+			{
+				$this->renderInputTag($writer,$clientID,$onclick);
+				$this->renderLabel($writer,$clientID,$text);
+			}
+		}
+		else
+			$this->renderInputTag($writer,$clientID,$onclick);
+		if($needSpan)
+			$writer->renderEndTag();
+	}
+
+	/**
+	 * @return TMap list of attributes to be rendered for label beside the checkbox
+	 */
+	public function getLabelAttributes()
+	{
+		if($attributes=$this->getViewState('LabelAttributes',null))
+			return $attributes;
+		else
+		{
+			$attributes=new TAttributeCollection;
+			$this->setViewState('LabelAttributes',$attributes,null);
+			return $attributes;
+		}
+	}
+
+	/**
+	 * @return TMap list of attributes to be rendered for the checkbox
+	 */
+	public function getInputAttributes()
+	{
+		if($attributes=$this->getViewState('InputAttributes',null))
+			return $attributes;
+		else
+		{
+			$attributes=new TAttributeCollection;
+			$this->setViewState('InputAttributes',$attributes,null);
+			return $attributes;
+		}
+	}
+
+	/**
+	 * @return string the value attribute to be rendered
+	 */
+	protected function getValueAttribute()
+	{
+		$attributes=$this->getViewState('InputAttributes',null);
+		if($attributes && $attributes->contains('value'))
+			return $attributes->itemAt('value');
+		else if($this->hasAttribute('value'))
+			return $this->getAttribute('value');
+		else
+			return '';
+	}
+
+	/**
+	 * Renders a label beside the checkbox.
+	 * @param THtmlWriter the writer for the rendering purpose
+	 * @param string checkbox id
+	 * @param string label text
+	 */
+	protected function renderLabel($writer,$clientID,$text)
+	{
+		$writer->addAttribute('for',$clientID);
+		if($attributes=$this->getViewState('LabelAttributes',null))
+			$writer->addAttributes($attributes);
+		$writer->renderBeginTag('label');
+		$writer->write($text);
+		$writer->renderEndTag();
+	}
+
+	/**
+	 * Renders a checkbox input element.
+	 * @param THtmlWriter the writer for the rendering purpose
+	 * @param string checkbox id
+	 * @param string onclick js
+	 */
+	protected function renderInputTag($writer,$clientID,$onclick)
+	{
+		if($clientID!=='')
+			$writer->addAttribute('id',$clientID);
+		$writer->addAttribute('type','checkbox');
+		if(($value = $this->getValueAttribute()) !== '')
+			$writer->addAttribute('value',$value);
+		if($onclick!=='')
+			$writer->addAttribute('onclick',$onclick);
+		if(($uniqueID=$this->getUniqueID())!=='')
+			$writer->addAttribute('name',$uniqueID);
+		if($this->getChecked())
+			$writer->addAttribute('checked','checked');
+		if(!$this->getEnabled(true))
+			$writer->addAttribute('disabled','disabled');
+
+		$page=$this->getPage();
+		if($this->getEnabled(true) && $this->getAutoPostBack() && $page->getClientSupportsJavaScript())
+			$this->renderClientControlScript($writer);
+
+		if(($accesskey=$this->getAccessKey())!=='')
+			$writer->addAttribute('accesskey',$accesskey);
+		if(($tabindex=$this->getTabIndex())>0)
+			$writer->addAttribute('tabindex',"$tabindex");
+		if($attributes=$this->getViewState('InputAttributes',null))
+			$writer->addAttributes($attributes);
+		$writer->renderBeginTag('input');
+		$writer->renderEndTag();
+	}
+
+	/**
+	 * Renders the client-script code.
+	 */
+	protected function renderClientControlScript($writer)
+	{
+		$cs = $this->getPage()->getClientScript();
+		$cs->registerPostBackControl($this->getClientClassName(),$this->getPostBackOptions());
+	}
+
+	/**
+	 * 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.TCheckBox';
+	}
+
+	/**
+	 * Gets the post back options for this checkbox.
+	 * @return array
+	 */
+	protected function getPostBackOptions()
+	{
+		$options['ID'] = $this->getClientID();
+		$options['ValidationGroup'] = $this->getValidationGroup();
+		$options['CausesValidation'] = $this->getCausesValidation();
+		$options['EventTarget'] = $this->getUniqueID();
+		return $options;
+	}
+
+}
+
+?>
diff --git a/framework/Web/UI/WebControls/TColorPicker.php b/framework/Web/UI/WebControls/TColorPicker.php
index 6172722c..7b40f033 100644
--- a/framework/Web/UI/WebControls/TColorPicker.php
+++ b/framework/Web/UI/WebControls/TColorPicker.php
@@ -231,6 +231,15 @@ class TColorPicker extends TTextBox
 		$writer->renderEndTag();
 	}
 
+	/**
+	 * 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.TColorPicker';
+	}
 }
 
 ?>
\ No newline at end of file
diff --git a/framework/Web/UI/WebControls/THtmlArea.php b/framework/Web/UI/WebControls/THtmlArea.php
index 8b214b69..09f8328c 100644
--- a/framework/Web/UI/WebControls/THtmlArea.php
+++ b/framework/Web/UI/WebControls/THtmlArea.php
@@ -325,6 +325,16 @@ class THtmlArea extends TTextBox
 
 		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';
+	}
 }
 
 ?>
\ No newline at end of file
diff --git a/framework/Web/UI/WebControls/TImageButton.php b/framework/Web/UI/WebControls/TImageButton.php
index 690a8eea..669779cd 100644
--- a/framework/Web/UI/WebControls/TImageButton.php
+++ b/framework/Web/UI/WebControls/TImageButton.php
@@ -1,378 +1,389 @@
-<?php
-/**
- * TImageButton class file
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright &copy; 2005 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Revision: $  $Date: $
- * @package System.Web.UI.WebControls
- */
-
-/**
- * Includes TImage class file
- */
-Prado::using('System.Web.UI.WebControls.TImage');
-
-/**
- * TImageButton class
- *
- * TImageButton creates an image button on the page. It is used to submit data to a page.
- * You can create either a <b>submit</b> button or a <b>command</b> button.
- *
- * A <b>command</b> button has a command name (specified by
- * the {@link setCommandName CommandName} property) and and a command parameter
- * (specified by {@link setCommandParameter CommandParameter} property)
- * associated with the button. This allows you to create multiple TLinkButton
- * components on a Web page and programmatically determine which one is clicked
- * with what parameter. You can provide an event handler for
- * {@link onCommand OnCommand} event to programmatically control the actions performed
- * when the command button is clicked. In the event handler, you can determine
- * the {@link setCommandName CommandName} property value and
- * the {@link setCommandParameter CommandParameter} property value
- * through the {@link TCommandParameter::getName Name} and
- * {@link TCommandParameter::getParameter Parameter} properties of the event
- * parameter which is of type {@link TCommandEventParameter}.
- *
- * A <b>submit</b> button does not have a command name associated with the button
- * and clicking on it simply posts the Web page back to the server.
- * By default, a TImageButton control is a submit button.
- * You can provide an event handler for the {@link onClick OnClick} event
- * to programmatically control the actions performed when the submit button is clicked.
- * The coordinates of the clicking point can be obtained from the {@link onClick OnClick}
- * event parameter, which is of type {@link TImageClickEventParameter}.
- *
- * Clicking on button can trigger form validation, if
- * {@link setCausesValidation CausesValidation} is true.
- * And the validation may be restricted within a certain group of validator
- * controls by setting {@link setValidationGroup ValidationGroup} property.
- * If validation is successful, the data will be post back to the same page.
- *
- * TImageButton displays the {@link setText Text} property as the hint text to the displayed image.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Revision: $  $Date: $
- * @package System.Web.UI.WebControls
- * @since 3.0
- */
-class TImageButton extends TImage implements IPostBackDataHandler, IPostBackEventHandler, IButtonControl
-{
-	/**
-	 * @var integer x coordinate that the image is being clicked at
-	 */
-	private $_x=0;
-	/**
-	 * @var integer y coordinate that the image is being clicked at
-	 */
-	private $_y=0;
-
-	/**
-	 * @return string tag name of the button
-	 */
-	protected function getTagName()
-	{
-		return 'input';
-	}
-
-	/**
-	 * Adds attribute name-value pairs to renderer.
-	 * This overrides the parent implementation with additional button specific attributes.
-	 * @param THtmlWriter the writer used for the rendering purpose
-	 */
-	protected function addAttributesToRender($writer)
-	{
-		$page=$this->getPage();
-		$page->ensureRenderInForm($this);
-		$writer->addAttribute('type','image');
-		if(($uniqueID=$this->getUniqueID())!=='')
-			$writer->addAttribute('name',$uniqueID);
-		if($this->getEnabled(true))
-			$this->renderClientControlScript($writer);
-		else if($this->getEnabled()) // in this case, parent will not render 'disabled'
-			$writer->addAttribute('disabled','disabled');
-		parent::addAttributesToRender($writer);
-	}
-
-	/**
-	 * Renders the client-script code.
-	 */
-	protected function renderClientControlScript($writer)
-	{
-		if($this->canCauseValidation())
-		{
-			$writer->addAttribute('id',$this->getClientID());
-			$cs = $this->getPage()->getClientScript();
-			$cs->registerPostBackControl('Prado.WebUI.TImageButton',$this->getPostBackOptions());
-		}
-	}
-	/**
-	 * @return boolean whether to perform validation if the button is clicked
-	 */
-	protected function canCauseValidation()
-	{
-		if($this->getCausesValidation())
-		{
-			$group=$this->getValidationGroup();
-			return $this->getPage()->getValidators($group)->getCount()>0;
-		}
-		else
-			return false;
-	}
-
-	/**
-	 * Returns postback specifications for the button.
-	 * This method is used by framework and control developers.
-	 * @return array parameters about how the button defines its postback behavior.
-	 */
-	protected function getPostBackOptions()
-	{
-		$options['ID'] = $this->getClientID();
-		$options['CausesValidation'] = $this->getCausesValidation();
-		$options['ValidationGroup'] = $this->getValidationGroup();
-		$options['EventTarget'] = $this->getUniqueID();
-
-		return $options;
-	}
-
-	/**
-	 * This method checks if the TImageButton is clicked and loads the coordinates of the clicking position.
-	 * 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 component has been changed
-	 */
-	public function loadPostData($key,$values)
-	{
-		$uid=$this->getUniqueID();
-		if(isset($values["{$uid}_x"]) && isset($values["{$uid}_y"]))
-		{
-			$this->_x=intval($values["{$uid}_x"]);
-			$this->_y=intval($values["{$uid}_y"]);
-			$this->getPage()->setPostBackEventTarget($this);
-		}
-		return false;
-	}
-
-	/**
-	 * A dummy implementation for the IPostBackDataHandler interface.
-	 */
-	public function raisePostDataChangedEvent()
-	{
-		// no post data to handle
-	}
-
-	/**
-	 * This method is invoked when the button is clicked.
-	 * The method raises 'OnClick' event to fire up the event handlers.
-	 * If you override this method, be sure to call the parent implementation
-	 * so that the event handler can be invoked.
-	 * @param TImageClickEventParameter event parameter to be passed to the event handlers
-	 */
-	public function onClick($param)
-	{
-		$this->raiseEvent('OnClick',$this,$param);
-	}
-
-	/**
-	 * This method is invoked when the button is clicked.
-	 * The method raises 'OnCommand' event to fire up the event handlers.
-	 * If you override this method, be sure to call the parent implementation
-	 * so that the event handlers can be invoked.
-	 * @param TCommandEventParameter event parameter to be passed to the event handlers
-	 */
-	public function onCommand($param)
-	{
-		$this->raiseEvent('OnCommand',$this,$param);
-		$this->raiseBubbleEvent($this,$param);
-	}
-
-	/**
-	 * Raises the postback event.
-	 * This method is required by {@link IPostBackEventHandler} interface.
-	 * If {@link getCausesValidation CausesValidation} is true, it will
-	 * invoke the page's {@link TPage::validate validate} method first.
-	 * It will raise {@link onClick OnClick} and {@link onCommand OnCommand} events.
-	 * This method is mainly used by framework and control developers.
-	 * @param TEventParameter the event parameter
-	 */
-	public function raisePostBackEvent($param)
-	{
-		if($this->getCausesValidation())
-			$this->getPage()->validate($this->getValidationGroup());
-		$this->onClick(new TImageClickEventParameter($this->_x,$this->_y));
-		$this->onCommand(new TCommandEventParameter($this->getCommandName(),$this->getCommandParameter()));
-	}
-
-	/**
-	 * @return boolean whether postback event trigger by this button will cause input validation, default is true
-	 */
-	public function getCausesValidation()
-	{
-		return $this->getViewState('CausesValidation',true);
-	}
-
-	/**
-	 * @param boolean whether postback event trigger by this button will cause input validation
-	 */
-	public function setCausesValidation($value)
-	{
-		$this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true);
-	}
-
-	/**
-	 * @return string the command name associated with the {@link onCommand OnCommand} event.
-	 */
-	public function getCommandName()
-	{
-		return $this->getViewState('CommandName','');
-	}
-
-	/**
-	 * @param string the command name associated with the {@link onCommand OnCommand} event.
-	 */
-	public function setCommandName($value)
-	{
-		$this->setViewState('CommandName',$value,'');
-	}
-
-	/**
-	 * @return string the parameter associated with the {@link onCommand OnCommand} event
-	 */
-	public function getCommandParameter()
-	{
-		return $this->getViewState('CommandParameter','');
-	}
-
-	/**
-	 * @param string the parameter associated with the {@link onCommand OnCommand} event.
-	 */
-	public function setCommandParameter($value)
-	{
-		$this->setViewState('CommandParameter',$value,'');
-	}
-
-	/**
-	 * @return string the group of validators which the button causes validation upon postback
-	 */
-	public function getValidationGroup()
-	{
-		return $this->getViewState('ValidationGroup','');
-	}
-
-	/**
-	 * @param string the group of validators which the button causes validation upon postback
-	 */
-	public function setValidationGroup($value)
-	{
-		$this->setViewState('ValidationGroup',$value,'');
-	}
-
-	/**
-	 * @return string caption of the button
-	 */
-	public function getText()
-	{
-		return $this->getAlternateText();
-	}
-
-	/**
-	 * @param string caption of the button
-	 */
-	public function setText($value)
-	{
-		$this->setAlternateText($value);
-	}
-
-	/**
-	 * Registers the image button to receive postback data during postback.
-	 * This is necessary because an image button, when postback, does not have
-	 * direct mapping between post data and the image button name.
-	 * This method overrides the parent implementation and is invoked before render.
-	 * @param mixed event parameter
-	 */
-	public function onPreRender($param)
-	{
-		parent::onPreRender($param);
-		$this->getPage()->registerRequiresPostData($this);
-	}
-
-	/**
-	 * Renders the body content enclosed between the control tag.
-	 * This overrides the parent implementation with nothing to be rendered.
-	 * @param THtmlWriter the writer used for the rendering purpose
-	 */
-	public function renderContents($writer)
-	{
-	}
-}
-
-/**
- * TImageClickEventParameter class
- *
- * TImageClickEventParameter encapsulates the parameter data for
- * {@link TImageButton::onClick Click} event of {@link TImageButton} controls.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Revision: $  $Date: $
- * @package System.Web.UI.WebControls
- * @since 3.0
- */
-class TImageClickEventParameter extends TEventParameter
-{
-	/**
-	 * the X coordinate of the clicking point
-	 * @var integer
-	 */
-	public $_x=0;
-	/**
-	 * the Y coordinate of the clicking point
-	 * @var integer
-	 */
-	public $_y=0;
-
-	/**
-	 * Constructor.
-	 * @param integer X coordinate of the clicking point
-	 * @param integer Y coordinate of the clicking point
-	 */
-	public function __construct($x,$y)
-	{
-		$this->_x=$x;
-		$this->_y=$y;
-	}
-
-	/**
-	 * @return integer X coordinate of the clicking point, defaults to 0
-	 */
-	public function getX()
-	{
-		return $this->_x;
-	}
-
-	/**
-	 * @param integer X coordinate of the clicking point
-	 */
-	public function setX($value)
-	{
-		$this->_x=TPropertyValue::ensureInteger($value);
-	}
-
-	/**
-	 * @return integer Y coordinate of the clicking point, defaults to 0
-	 */
-	public function getY()
-	{
-		return $this->_y;
-	}
-
-	/**
-	 * @param integer Y coordinate of the clicking point
-	 */
-	public function setY($value)
-	{
-		$this->_y=TPropertyValue::ensureInteger($value);
-	}
-}
-
-?>
\ No newline at end of file
+<?php
+/**
+ * TImageButton class file
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Revision: $  $Date: $
+ * @package System.Web.UI.WebControls
+ */
+
+/**
+ * Includes TImage class file
+ */
+Prado::using('System.Web.UI.WebControls.TImage');
+
+/**
+ * TImageButton class
+ *
+ * TImageButton creates an image button on the page. It is used to submit data to a page.
+ * You can create either a <b>submit</b> button or a <b>command</b> button.
+ *
+ * A <b>command</b> button has a command name (specified by
+ * the {@link setCommandName CommandName} property) and and a command parameter
+ * (specified by {@link setCommandParameter CommandParameter} property)
+ * associated with the button. This allows you to create multiple TLinkButton
+ * components on a Web page and programmatically determine which one is clicked
+ * with what parameter. You can provide an event handler for
+ * {@link onCommand OnCommand} event to programmatically control the actions performed
+ * when the command button is clicked. In the event handler, you can determine
+ * the {@link setCommandName CommandName} property value and
+ * the {@link setCommandParameter CommandParameter} property value
+ * through the {@link TCommandParameter::getName Name} and
+ * {@link TCommandParameter::getParameter Parameter} properties of the event
+ * parameter which is of type {@link TCommandEventParameter}.
+ *
+ * A <b>submit</b> button does not have a command name associated with the button
+ * and clicking on it simply posts the Web page back to the server.
+ * By default, a TImageButton control is a submit button.
+ * You can provide an event handler for the {@link onClick OnClick} event
+ * to programmatically control the actions performed when the submit button is clicked.
+ * The coordinates of the clicking point can be obtained from the {@link onClick OnClick}
+ * event parameter, which is of type {@link TImageClickEventParameter}.
+ *
+ * Clicking on button can trigger form validation, if
+ * {@link setCausesValidation CausesValidation} is true.
+ * And the validation may be restricted within a certain group of validator
+ * controls by setting {@link setValidationGroup ValidationGroup} property.
+ * If validation is successful, the data will be post back to the same page.
+ *
+ * TImageButton displays the {@link setText Text} property as the hint text to the displayed image.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Revision: $  $Date: $
+ * @package System.Web.UI.WebControls
+ * @since 3.0
+ */
+class TImageButton extends TImage implements IPostBackDataHandler, IPostBackEventHandler, IButtonControl
+{
+	/**
+	 * @var integer x coordinate that the image is being clicked at
+	 */
+	private $_x=0;
+	/**
+	 * @var integer y coordinate that the image is being clicked at
+	 */
+	private $_y=0;
+
+	/**
+	 * @return string tag name of the button
+	 */
+	protected function getTagName()
+	{
+		return 'input';
+	}
+
+	/**
+	 * Adds attribute name-value pairs to renderer.
+	 * This overrides the parent implementation with additional button specific attributes.
+	 * @param THtmlWriter the writer used for the rendering purpose
+	 */
+	protected function addAttributesToRender($writer)
+	{
+		$page=$this->getPage();
+		$page->ensureRenderInForm($this);
+		$writer->addAttribute('type','image');
+		if(($uniqueID=$this->getUniqueID())!=='')
+			$writer->addAttribute('name',$uniqueID);
+		if($this->getEnabled(true))
+			$this->renderClientControlScript($writer);
+		else if($this->getEnabled()) // in this case, parent will not render 'disabled'
+			$writer->addAttribute('disabled','disabled');
+		parent::addAttributesToRender($writer);
+	}
+
+	/**
+	 * Renders the client-script code.
+	 */
+	protected function renderClientControlScript($writer)
+	{
+		if($this->canCauseValidation())
+		{
+			$writer->addAttribute('id',$this->getClientID());
+			$cs = $this->getPage()->getClientScript();
+			$cs->registerPostBackControl($this->getClientClassName(),$this->getPostBackOptions());
+		}
+	}
+
+	/**
+	 * 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.TImageButton';
+	}
+
+	/**
+	 * @return boolean whether to perform validation if the button is clicked
+	 */
+	protected function canCauseValidation()
+	{
+		if($this->getCausesValidation())
+		{
+			$group=$this->getValidationGroup();
+			return $this->getPage()->getValidators($group)->getCount()>0;
+		}
+		else
+			return false;
+	}
+
+	/**
+	 * Returns postback specifications for the button.
+	 * This method is used by framework and control developers.
+	 * @return array parameters about how the button defines its postback behavior.
+	 */
+	protected function getPostBackOptions()
+	{
+		$options['ID'] = $this->getClientID();
+		$options['CausesValidation'] = $this->getCausesValidation();
+		$options['ValidationGroup'] = $this->getValidationGroup();
+		$options['EventTarget'] = $this->getUniqueID();
+
+		return $options;
+	}
+
+	/**
+	 * This method checks if the TImageButton is clicked and loads the coordinates of the clicking position.
+	 * 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 component has been changed
+	 */
+	public function loadPostData($key,$values)
+	{
+		$uid=$this->getUniqueID();
+		if(isset($values["{$uid}_x"]) && isset($values["{$uid}_y"]))
+		{
+			$this->_x=intval($values["{$uid}_x"]);
+			$this->_y=intval($values["{$uid}_y"]);
+			$this->getPage()->setPostBackEventTarget($this);
+		}
+		return false;
+	}
+
+	/**
+	 * A dummy implementation for the IPostBackDataHandler interface.
+	 */
+	public function raisePostDataChangedEvent()
+	{
+		// no post data to handle
+	}
+
+	/**
+	 * This method is invoked when the button is clicked.
+	 * The method raises 'OnClick' event to fire up the event handlers.
+	 * If you override this method, be sure to call the parent implementation
+	 * so that the event handler can be invoked.
+	 * @param TImageClickEventParameter event parameter to be passed to the event handlers
+	 */
+	public function onClick($param)
+	{
+		$this->raiseEvent('OnClick',$this,$param);
+	}
+
+	/**
+	 * This method is invoked when the button is clicked.
+	 * The method raises 'OnCommand' event to fire up the event handlers.
+	 * If you override this method, be sure to call the parent implementation
+	 * so that the event handlers can be invoked.
+	 * @param TCommandEventParameter event parameter to be passed to the event handlers
+	 */
+	public function onCommand($param)
+	{
+		$this->raiseEvent('OnCommand',$this,$param);
+		$this->raiseBubbleEvent($this,$param);
+	}
+
+	/**
+	 * Raises the postback event.
+	 * This method is required by {@link IPostBackEventHandler} interface.
+	 * If {@link getCausesValidation CausesValidation} is true, it will
+	 * invoke the page's {@link TPage::validate validate} method first.
+	 * It will raise {@link onClick OnClick} and {@link onCommand OnCommand} events.
+	 * This method is mainly used by framework and control developers.
+	 * @param TEventParameter the event parameter
+	 */
+	public function raisePostBackEvent($param)
+	{
+		if($this->getCausesValidation())
+			$this->getPage()->validate($this->getValidationGroup());
+		$this->onClick(new TImageClickEventParameter($this->_x,$this->_y));
+		$this->onCommand(new TCommandEventParameter($this->getCommandName(),$this->getCommandParameter()));
+	}
+
+	/**
+	 * @return boolean whether postback event trigger by this button will cause input validation, default is true
+	 */
+	public function getCausesValidation()
+	{
+		return $this->getViewState('CausesValidation',true);
+	}
+
+	/**
+	 * @param boolean whether postback event trigger by this button will cause input validation
+	 */
+	public function setCausesValidation($value)
+	{
+		$this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true);
+	}
+
+	/**
+	 * @return string the command name associated with the {@link onCommand OnCommand} event.
+	 */
+	public function getCommandName()
+	{
+		return $this->getViewState('CommandName','');
+	}
+
+	/**
+	 * @param string the command name associated with the {@link onCommand OnCommand} event.
+	 */
+	public function setCommandName($value)
+	{
+		$this->setViewState('CommandName',$value,'');
+	}
+
+	/**
+	 * @return string the parameter associated with the {@link onCommand OnCommand} event
+	 */
+	public function getCommandParameter()
+	{
+		return $this->getViewState('CommandParameter','');
+	}
+
+	/**
+	 * @param string the parameter associated with the {@link onCommand OnCommand} event.
+	 */
+	public function setCommandParameter($value)
+	{
+		$this->setViewState('CommandParameter',$value,'');
+	}
+
+	/**
+	 * @return string the group of validators which the button causes validation upon postback
+	 */
+	public function getValidationGroup()
+	{
+		return $this->getViewState('ValidationGroup','');
+	}
+
+	/**
+	 * @param string the group of validators which the button causes validation upon postback
+	 */
+	public function setValidationGroup($value)
+	{
+		$this->setViewState('ValidationGroup',$value,'');
+	}
+
+	/**
+	 * @return string caption of the button
+	 */
+	public function getText()
+	{
+		return $this->getAlternateText();
+	}
+
+	/**
+	 * @param string caption of the button
+	 */
+	public function setText($value)
+	{
+		$this->setAlternateText($value);
+	}
+
+	/**
+	 * Registers the image button to receive postback data during postback.
+	 * This is necessary because an image button, when postback, does not have
+	 * direct mapping between post data and the image button name.
+	 * This method overrides the parent implementation and is invoked before render.
+	 * @param mixed event parameter
+	 */
+	public function onPreRender($param)
+	{
+		parent::onPreRender($param);
+		$this->getPage()->registerRequiresPostData($this);
+	}
+
+	/**
+	 * Renders the body content enclosed between the control tag.
+	 * This overrides the parent implementation with nothing to be rendered.
+	 * @param THtmlWriter the writer used for the rendering purpose
+	 */
+	public function renderContents($writer)
+	{
+	}
+}
+
+/**
+ * TImageClickEventParameter class
+ *
+ * TImageClickEventParameter encapsulates the parameter data for
+ * {@link TImageButton::onClick Click} event of {@link TImageButton} controls.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Revision: $  $Date: $
+ * @package System.Web.UI.WebControls
+ * @since 3.0
+ */
+class TImageClickEventParameter extends TEventParameter
+{
+	/**
+	 * the X coordinate of the clicking point
+	 * @var integer
+	 */
+	public $_x=0;
+	/**
+	 * the Y coordinate of the clicking point
+	 * @var integer
+	 */
+	public $_y=0;
+
+	/**
+	 * Constructor.
+	 * @param integer X coordinate of the clicking point
+	 * @param integer Y coordinate of the clicking point
+	 */
+	public function __construct($x,$y)
+	{
+		$this->_x=$x;
+		$this->_y=$y;
+	}
+
+	/**
+	 * @return integer X coordinate of the clicking point, defaults to 0
+	 */
+	public function getX()
+	{
+		return $this->_x;
+	}
+
+	/**
+	 * @param integer X coordinate of the clicking point
+	 */
+	public function setX($value)
+	{
+		$this->_x=TPropertyValue::ensureInteger($value);
+	}
+
+	/**
+	 * @return integer Y coordinate of the clicking point, defaults to 0
+	 */
+	public function getY()
+	{
+		return $this->_y;
+	}
+
+	/**
+	 * @param integer Y coordinate of the clicking point
+	 */
+	public function setY($value)
+	{
+		$this->_y=TPropertyValue::ensureInteger($value);
+	}
+}
+
+?>
diff --git a/framework/Web/UI/WebControls/TImageMap.php b/framework/Web/UI/WebControls/TImageMap.php
index b2d5f55e..78216a35 100644
--- a/framework/Web/UI/WebControls/TImageMap.php
+++ b/framework/Web/UI/WebControls/TImageMap.php
@@ -1,727 +1,737 @@
-<?php
-/**
- * TImageMap and related class file.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright &copy; 2005 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Revision: $  $Date: $
- * @package System.Web.UI.WebControls
- */
-
-/**
- * Includes TImage class file
- */
-Prado::using('System.Web.UI.WebControls.TImage');
-
-/**
- * TImageMap class
- *
- * TImageMap represents an image on a page. Hotspot regions can be defined
- * within the image. Depending on the {@link setHotSpotMode HotSpotMode},
- * clicking on the hotspots may trigger a postback or navigate to a specified
- * URL. The hotspots defined may be accessed via {@link getHotSpots HotSpots}.
- * Each hotspot is described as a {@link THotSpot}, which can be a circle,
- * rectangle, polygon, etc. To add hotspot in a template, use the following,
- * <code>
- *  <com:TImageMap>
- *    <com:TCircleHotSpot ... />
- *    <com:TRectangleHotSpot ... />
- *    <com:TPolygonHotSpot ... />
- *  </com:TImageMap>
- * </code>
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Revision: $  $Date: $
- * @package System.Web.UI.WebControls
- * @since 3.0
- */
-class TImageMap extends TImage implements IPostBackEventHandler
-{
-	const MAP_NAME_PREFIX='ImageMap';
-
-	/**
-	 * Processes an object that is created during parsing template.
-	 * This method adds {@link THotSpot} objects into the hotspot collection
-	 * of the imagemap.
-	 * @param string|TComponent text string or component parsed and instantiated in template
-	 */
-	public function addParsedObject($object)
-	{
-		if($object instanceof THotSpot)
-			$this->getHotSpots()->add($object);
-	}
-
-	/**
-	 * Adds attribute name-value pairs to renderer.
-	 * This overrides the parent implementation with additional imagemap specific attributes.
-	 * @param THtmlWriter the writer used for the rendering purpose
-	 */
-	protected function addAttributesToRender($writer)
-	{
-		parent::addAttributesToRender($writer);
-		if($this->getHotSpots()->getCount()>0)
-		{
-			$writer->addAttribute('usemap','#'.self::MAP_NAME_PREFIX.$this->getClientID());
-			$writer->addAttribute('id',$this->getUniqueID());
-		}
-		if($this->getEnabled() && !$this->getEnabled(true))
-			$writer->addAttribute('disabled','disabled');
-	}
-
-	/**
-	 * Renders this imagemap.
-	 * @param THtmlWriter
-	 */
-	public function render($writer)
-	{
-		parent::render($writer);
-
-		$hotspots=$this->getHotSpots();
-
-		if($hotspots->getCount()>0)
-		{
-			$clientID=$this->getClientID();
-			$cs=$this->getPage()->getClientScript();
-			$writer->writeLine();
-			$writer->addAttribute('name',self::MAP_NAME_PREFIX.$clientID);
-			$writer->renderBeginTag('map');
-			$writer->writeLine();
-			if(($mode=$this->getHotSpotMode())==='NotSet')
-				$mode='Navigate';
-			$target=$this->getTarget();
-			$i=0;
-			$options['EventTarget'] = $this->getUniqueID();
-			$options['StopEvent'] = true;
-			$cs=$this->getPage()->getClientScript();
-			foreach($hotspots as $hotspot)
-			{
-				if($hotspot->getHotSpotMode()==='NotSet')
-					$hotspot->setHotSpotMode($mode);
-				if($target!=='' && $hotspot->getTarget()==='')
-					$hotspot->setTarget($target);
-				if($hotspot->getHotSpotMode()==='PostBack')
-				{
-					$id=$clientID.'_'.$i;
-					$writer->addAttribute('id',$id);
-					$writer->addAttribute('href','#'.$id); //create unique no-op url references
-					$options['ID']=$id;
-					$options['EventParameter']="$i";
-					$options['CausesValidation']=$hotspot->getCausesValidation();
-					$options['ValidationGroup']=$hotspot->getValidationGroup();
-					$cs->registerPostBackControl('Prado.WebUI.TImageMap',$options);
-				}
-				$hotspot->render($writer);
-				$writer->writeLine();
-				$i++;
-			}
-			$writer->renderEndTag();
-		}
-	}
-
-	/**
-	 * Raises the postback event.
-	 * This method is required by {@link IPostBackEventHandler} interface.
-	 * This method is mainly used by framework and control developers.
-	 * @param TEventParameter the event parameter
-	 */
-	public function raisePostBackEvent($param)
-	{
-		$postBackValue=null;
-		if($param!=='')
-		{
-			$index=TPropertyValue::ensureInteger($param);
-			$hotspots=$this->getHotSpots();
-			if($index>=0 && $index<$hotspots->getCount())
-			{
-				$hotspot=$hotspots->itemAt($index);
-				if(($mode=$hotspot->getHotSpotMode())==='NotSet')
-					$mode=$this->getHotSpotMode();
-				if($mode==='PostBack')
-				{
-					$postBackValue=$hotspot->getPostBackValue();
-					if($hotspot->getCausesValidation())
-						$this->getPage()->validate($hotspot->getValidationGroup());
-				}
-			}
-		}
-		if($postBackValue!==null)
-			$this->onClick(new TImageMapEventParameter($postBackValue));
-	}
-
-	/**
-	 * @return string the behavior of hotspot regions in this imagemap when they are clicked. Defaults to 'NotSet'.
-	 */
-	public function getHotSpotMode()
-	{
-		return $this->getViewState('HotSpotMode','NotSet');
-	}
-
-	/**
-	 * Sets the behavior of hotspot regions in this imagemap when they are clicked.
-	 * If an individual hotspot has a mode other than 'NotSet', the mode set in this
-	 * imagemap will be ignored. By default, 'NotSet' is equivalent to 'Navigate'.
-	 * @param string the behavior of hotspot regions in this imagemap when they are clicked.
-	 * Valid values include 'NotSet','Navigate','PostBack','Inactive'.
-	 */
-	public function setHotSpotMode($value)
-	{
-		$this->setViewState('HotSpotMode',TPropertyValue::ensureEnum($value,'NotSet','Navigate','PostBack','Inactive'),'NotSet');
-	}
-
-	/**
-	 * @return THotSpotCollection collection of hotspots defined in this imagemap.
-	 */
-	public function getHotSpots()
-	{
-		if(($hotspots=$this->getViewState('HotSpots',null))===null)
-		{
-			$hotspots=new THotSpotCollection;
-			$this->setViewState('HotSpots',$hotspots);
-		}
-		return $hotspots;
-	}
-
-	/**
-	 * @return string  the target window or frame to display the new page when a hotspot region is clicked within the imagemap. Defaults to ''.
-	 */
-	public function getTarget()
-	{
-		return $this->getViewState('Target','');
-	}
-
-	/**
-	 * @param string  the target window or frame to display the new page when a hotspot region is clicked within the imagemap.
-	 */
-	public function setTarget($value)
-	{
-		$this->setViewState('Target',TPropertyValue::ensureString($value),'');
-	}
-
-	/**
-	 * Raises <b>OnClick</b> event.
-	 * This method is invoked when a hotspot region is clicked within the imagemap.
-	 * If you override this method, be sure to call the parent implementation
-	 * so that the event handler can be invoked.
-	 * @param TImageMapEventParameter event parameter to be passed to the event handlers
-	 */
-	public function onClick($param)
-	{
-		$this->raiseEvent('OnClick',$this,$param);
-	}
-}
-
-/**
- * TImageMapEventParameter class.
- *
- * TImageMapEventParameter represents a postback event parameter
- * when a hotspot is clicked and posts back in a {@link TImageMap}.
- * To retrieve the post back value associated with the hotspot being clicked,
- * access {@link getPostBackValue PostBackValue}.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Revision: $  $Date: $
- * @package System.Web.UI.WebControls
- * @since 3.0
- */
-class TImageMapEventParameter extends TEventParameter
-{
-	private $_postBackValue;
-
-	/**
-	 * Constructor.
-	 * @param string post back value associated with the hotspot clicked
-	 */
-	public function __construct($postBackValue)
-	{
-		$this->_postBackValue=$postBackValue;
-	}
-
-	/**
-	 * @return string post back value associated with the hotspot clicked
-	 */
-	public function getPostBackValue()
-	{
-		return $this->_postBackValue;
-	}
-}
-
-/**
- * THotSpotCollection class.
- *
- * THotSpotCollection represents a collection of hotspots in an imagemap.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Revision: $  $Date: $
- * @package System.Web.UI.WebControls
- * @since 3.0
- */
-class THotSpotCollection extends TList
-{
-	/**
-	 * Inserts an item at the specified position.
-	 * This overrides the parent implementation by inserting only {@link THotSpot}.
-	 * @param integer the speicified position.
-	 * @param mixed new item
-	 * @throws TInvalidDataTypeException if the item to be inserted is not a THotSpot.
-	 */
-	public function insertAt($index,$item)
-	{
-		if($item instanceof THotSpot)
-			parent::insertAt($index,$item);
-		else
-			throw new TInvalidDataTypeException('hotspotcollection_hotspot_required');
-	}
-}
-
-
-/**
- * THotSpot class.
- *
- * THotSpot implements the basic functionality common to all hot spot shapes.
- * Derived classes include {@link TCircleHotSpot}, {@link TPolygonHotSpot}
- * and {@link TRectangleHotSpot}.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Revision: $  $Date: $
- * @package System.Web.UI.WebControls
- * @since 3.0
- */
-abstract class THotSpot extends TComponent
-{
-	private $_viewState=array();
-
-	/**
-	 * Returns a viewstate value.
-	 *
-	 * This function is very useful in defining getter functions for component properties
-	 * that must be kept in viewstate.
-	 * @param string the name of the viewstate value to be returned
-	 * @param mixed the default value. If $key is not found in viewstate, $defaultValue will be returned
-	 * @return mixed the viewstate value corresponding to $key
-	 */
-	protected function getViewState($key,$defaultValue=null)
-	{
-		return isset($this->_viewState[$key])?$this->_viewState[$key]:$defaultValue;
-	}
-
-	/**
-	 * Sets a viewstate value.
-	 *
-	 * This function is very useful in defining setter functions for control properties
-	 * that must be kept in viewstate.
-	 * Make sure that the viewstate value must be serializable and unserializable.
-	 * @param string the name of the viewstate value
-	 * @param mixed the viewstate value to be set
-	 * @param mixed default value. If $value===$defaultValue, the item will be cleared from the viewstate.
-	 */
-	protected function setViewState($key,$value,$defaultValue=null)
-	{
-		if($value===$defaultValue)
-			unset($this->_viewState[$key]);
-		else
-			$this->_viewState[$key]=$value;
-	}
-
-	/**
-	 * @return string shape of the hotspot, can be 'circle', 'rect', 'poly', etc.
-	 */
-	abstract public function getShape();
-	/**
-	 * @return string coordinates defining the hotspot shape.
-	 */
-	abstract public function getCoordinates();
-
-	/**
-	 * @return string the access key that allows you to quickly navigate to the HotSpot region. Defaults to ''.
-	 */
-	public function getAccessKey()
-	{
-		return $this->getViewState('AccessKey','');
-	}
-
-	/**
-	 * @param string the access key that allows you to quickly navigate to the HotSpot region.
-	 */
-	public function setAccessKey($value)
-	{
-		$this->setViewState('AccessKey',TPropertyValue::ensureString($value),'');
-	}
-
-	/**
-	 * @return string the alternate text to display for a HotSpot object. Defaults to ''.
-	 */
-	public function getAlternateText()
-	{
-		return $this->getViewState('AlternateText','');
-	}
-
-	/**
-	 * @param string the alternate text to display for a HotSpot object.
-	 */
-	public function setAlternateText($value)
-	{
-		$this->setViewState('AlternateText',TPropertyValue::ensureString($value),'');
-	}
-
-	/**
-	 * @return string the behavior of a HotSpot object when it is clicked. Defaults to 'NotSet'.
-	 */
-	public function getHotSpotMode()
-	{
-		return $this->getViewState('HotSpotMode','NotSet');
-	}
-
-	/**
-	 * @param string the behavior of a HotSpot object when it is clicked.
-	 * Valid values include 'NotSet','Navigate','PostBack','Inactive'.
-	 */
-	public function setHotSpotMode($value)
-	{
-		$this->setViewState('HotSpotMode',TPropertyValue::ensureEnum($value,'NotSet','Navigate','PostBack','Inactive'),'NotSet');
-	}
-
-	/**
-	 * @return string the URL to navigate to when a HotSpot object is clicked. Defaults to ''.
-	 */
-	public function getNavigateUrl()
-	{
-		return $this->getViewState('NavigateUrl','');
-	}
-
-	/**
-	 * @param string the URL to navigate to when a HotSpot object is clicked.
-	 */
-	public function setNavigateUrl($value)
-	{
-		$this->setViewState('NavigateUrl',TPropertyValue::ensureString($value),'');
-	}
-
-	/**
-	 * @return string a value that is post back when the HotSpot is clicked. Defaults to ''.
-	 */
-	public function getPostBackValue()
-	{
-		return $this->getViewState('PostBackValue','');
-	}
-
-	/**
-	 * @param string a value that is post back when the HotSpot is clicked.
-	 */
-	public function setPostBackValue($value)
-	{
-		$this->setViewState('PostBackValue',TPropertyValue::ensureString($value),'');
-	}
-
-	/**
-	 * @return integer the tab index of the HotSpot region. Defaults to 0.
-	 */
-	public function getTabIndex()
-	{
-		return $this->getViewState('TabIndex',0);
-	}
-
-	/**
-	 * @param integer the tab index of the HotSpot region.
-	 */
-	public function setTabIndex($value)
-	{
-		$this->setViewState('TabIndex',TPropertyValue::ensureInteger($value),0);
-	}
-
-	/**
-	 * @return boolean whether postback event trigger by this hotspot will cause input validation, default is true
-	 */
-	public function getCausesValidation()
-	{
-		return $this->getViewState('CausesValidation',true);
-	}
-
-	/**
-	 * @param boolean whether postback event trigger by this hotspot will cause input validation
-	 */
-	public function setCausesValidation($value)
-	{
-		$this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true);
-	}
-
-	/**
-	 * @return string the group of validators which the hotspot causes validation upon postback
-	 */
-	public function getValidationGroup()
-	{
-		return $this->getViewState('ValidationGroup','');
-	}
-
-	/**
-	 * @param string the group of validators which the hotspot causes validation upon postback
-	 */
-	public function setValidationGroup($value)
-	{
-		$this->setViewState('ValidationGroup',$value,'');
-	}
-
-	/**
-	 * @return string  the target window or frame to display the new page when the HotSpot region
-	 * is clicked. Defaults to ''.
-	 */
-	public function getTarget()
-	{
-		return $this->getViewState('Target','');
-	}
-
-	/**
-	 * @param string  the target window or frame to display the new page when the HotSpot region
-	 * is clicked.
-	 */
-	public function setTarget($value)
-	{
-		$this->setViewState('Target',TPropertyValue::ensureString($value),'');
-	}
-
-	/**
-	 * Renders this hotspot.
-	 * @param THtmlWriter
-	 */
-	public function render($writer)
-	{
-		$writer->addAttribute('shape',$this->getShape());
-		$writer->addAttribute('coords',$this->getCoordinates());
-		if(($mode=$this->getHotSpotMode())==='NotSet')
-			$mode='Navigate';
-		if($mode==='Navigate')
-		{
-			$writer->addAttribute('href',$this->getNavigateUrl());
-			if(($target=$this->getTarget())!=='')
-				$writer->addAttribute('target',$target);
-		}
-		else if($mode==='Inactive')
-			$writer->addAttribute('nohref','true');
-		$text=$this->getAlternateText();
-		$writer->addAttribute('title',$text);
-		$writer->addAttribute('alt',$text);
-		if(($accessKey=$this->getAccessKey())!=='')
-			$writer->addAttribute('accesskey',$accessKey);
-		if(($tabIndex=$this->getTabIndex())!==0)
-			$writer->addAttribute('tabindex',"$tabIndex");
-		$writer->renderBeginTag('area');
-		$writer->renderEndTag();
-	}
-}
-
-/**
- * Class TCircleHotSpot.
- *
- * TCircleHotSpot defines a circular hot spot region in a {@link TImageMap}
- * control.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Revision: $  $Date: $
- * @package System.Web.UI.WebControls
- * @since 3.0
- */
-class TCircleHotSpot extends THotSpot
-{
-	/**
-	 * @return string shape of this hotspot.
-	 */
-	public function getShape()
-	{
-		return 'circle';
-	}
-
-	/**
-	 * @return string coordinates defining this hotspot shape
-	 */
-	public function getCoordinates()
-	{
-		return $this->getX().','.$this->getY().','.$this->getRadius();
-	}
-
-	/**
-	 * @return integer radius of the circular HotSpot region. Defaults to 0.
-	 */
-	public function getRadius()
-	{
-		return $this->getViewState('Radius',0);
-	}
-
-	/**
-	 * @param integer radius of the circular HotSpot region.
-	 */
-	public function setRadius($value)
-	{
-		$this->setViewState('Radius',TPropertyValue::ensureInteger($value),0);
-	}
-
-	/**
-	 * @return integer the X coordinate of the center of the circular HotSpot region. Defaults to 0.
-	 */
-	public function getX()
-	{
-		return $this->getViewState('X',0);
-	}
-
-	/**
-	 * @param integer the X coordinate of the center of the circular HotSpot region.
-	 */
-	public function setX($value)
-	{
-		$this->setViewState('X',TPropertyValue::ensureInteger($value),0);
-	}
-
-	/**
-	 * @return integer the Y coordinate of the center of the circular HotSpot region. Defaults to 0.
-	 */
-	public function getY()
-	{
-		return $this->getViewState('Y',0);
-	}
-
-	/**
-	 * @param integer the Y coordinate of the center of the circular HotSpot region.
-	 */
-	public function setY($value)
-	{
-		$this->setViewState('Y',TPropertyValue::ensureInteger($value),0);
-	}
-}
-
-/**
- * Class TRectangleHotSpot.
- *
- * TRectangleHotSpot defines a rectangle hot spot region in a {@link
- * TImageMap} control.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Revision: $  $Date: $
- * @package System.Web.UI.WebControls
- * @since 3.0
- */
-class TRectangleHotSpot extends THotSpot
-{
-	/**
-	 * @return string shape of this hotspot.
-	 */
-	public function getShape()
-	{
-		return 'rect';
-	}
-
-	/**
-	 * @return string coordinates defining this hotspot shape
-	 */
-	public function getCoordinates()
-	{
-		return $this->getLeft().','.$this->getTop().','.$this->getRight().','.$this->getBottom();
-	}
-
-	/**
-	 * @return integer the Y coordinate of the bottom side of the rectangle HotSpot region. Defaults to 0.
-	 */
-	public function getBottom()
-	{
-		return $this->getViewState('Bottom',0);
-	}
-
-	/**
-	 * @param integer the Y coordinate of the bottom side of the rectangle HotSpot region.
-	 */
-	public function setBottom($value)
-	{
-		$this->setViewState('Bottom',TPropertyValue::ensureInteger($value),0);
-	}
-
-	/**
-	 * @return integer the X coordinate of the right side of the rectangle HotSpot region. Defaults to 0.
-	 */
-	public function getLeft()
-	{
-		return $this->getViewState('Left',0);
-	}
-
-	/**
-	 * @param integer the X coordinate of the right side of the rectangle HotSpot region.
-	 */
-	public function setLeft($value)
-	{
-		$this->setViewState('Left',TPropertyValue::ensureInteger($value),0);
-	}
-
-	/**
-	 * @return integer the X coordinate of the right side of the rectangle HotSpot region. Defaults to 0.
-	 */
-	public function getRight()
-	{
-		return $this->getViewState('Right',0);
-	}
-
-	/**
-	 * @param integer the X coordinate of the right side of the rectangle HotSpot region.
-	 */
-	public function setRight($value)
-	{
-		$this->setViewState('Right',TPropertyValue::ensureInteger($value),0);
-	}
-
-	/**
-	 * @return integer the Y coordinate of the top side of the rectangle HotSpot region. Defaults to 0.
-	 */
-	public function getTop()
-	{
-		return $this->getViewState('Top',0);
-	}
-
-	/**
-	 * @param integer the Y coordinate of the top side of the rectangle HotSpot region.
-	 */
-	public function setTop($value)
-	{
-		$this->setViewState('Top',TPropertyValue::ensureInteger($value),0);
-	}
-}
-
-/**
- * Class TPolygonHotSpot.
- *
- * TPolygonHotSpot defines a polygon hot spot region in a {@link
- * TImageMap} control.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Revision: $  $Date: $
- * @package System.Web.UI.WebControls
- * @since 3.0
- */
-class TPolygonHotSpot extends THotSpot
-{
-	/**
-	 * @return string shape of this hotspot.
-	 */
-	public function getShape()
-	{
-		return 'poly';
-	}
-
-	/**
-	 * @return string coordinates of the vertices defining the polygon.
-	 * Coordinates are concatenated together with comma ','. Each pair
-	 * represents (x,y) of a vertex.
-	 */
-	public function getCoordinates()
-	{
-		return $this->getViewState('Coordinates','');
-	}
-
-	/**
-	 * @param string coordinates of the vertices defining the polygon.
-	 * Coordinates are concatenated together with comma ','. Each pair
-	 * represents (x,y) of a vertex.
-	 */
-	public function setCoordinates($value)
-	{
-		$this->setViewState('Coordinates',$value,'');
-	}
-}
-
-?>
\ No newline at end of file
+<?php
+/**
+ * TImageMap and related class file.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Revision: $  $Date: $
+ * @package System.Web.UI.WebControls
+ */
+
+/**
+ * Includes TImage class file
+ */
+Prado::using('System.Web.UI.WebControls.TImage');
+
+/**
+ * TImageMap class
+ *
+ * TImageMap represents an image on a page. Hotspot regions can be defined
+ * within the image. Depending on the {@link setHotSpotMode HotSpotMode},
+ * clicking on the hotspots may trigger a postback or navigate to a specified
+ * URL. The hotspots defined may be accessed via {@link getHotSpots HotSpots}.
+ * Each hotspot is described as a {@link THotSpot}, which can be a circle,
+ * rectangle, polygon, etc. To add hotspot in a template, use the following,
+ * <code>
+ *  <com:TImageMap>
+ *    <com:TCircleHotSpot ... />
+ *    <com:TRectangleHotSpot ... />
+ *    <com:TPolygonHotSpot ... />
+ *  </com:TImageMap>
+ * </code>
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Revision: $  $Date: $
+ * @package System.Web.UI.WebControls
+ * @since 3.0
+ */
+class TImageMap extends TImage implements IPostBackEventHandler
+{
+	const MAP_NAME_PREFIX='ImageMap';
+
+	/**
+	 * Processes an object that is created during parsing template.
+	 * This method adds {@link THotSpot} objects into the hotspot collection
+	 * of the imagemap.
+	 * @param string|TComponent text string or component parsed and instantiated in template
+	 */
+	public function addParsedObject($object)
+	{
+		if($object instanceof THotSpot)
+			$this->getHotSpots()->add($object);
+	}
+
+	/**
+	 * Adds attribute name-value pairs to renderer.
+	 * This overrides the parent implementation with additional imagemap specific attributes.
+	 * @param THtmlWriter the writer used for the rendering purpose
+	 */
+	protected function addAttributesToRender($writer)
+	{
+		parent::addAttributesToRender($writer);
+		if($this->getHotSpots()->getCount()>0)
+		{
+			$writer->addAttribute('usemap','#'.self::MAP_NAME_PREFIX.$this->getClientID());
+			$writer->addAttribute('id',$this->getUniqueID());
+		}
+		if($this->getEnabled() && !$this->getEnabled(true))
+			$writer->addAttribute('disabled','disabled');
+	}
+
+	/**
+	 * Renders this imagemap.
+	 * @param THtmlWriter
+	 */
+	public function render($writer)
+	{
+		parent::render($writer);
+
+		$hotspots=$this->getHotSpots();
+
+		if($hotspots->getCount()>0)
+		{
+			$clientID=$this->getClientID();
+			$cs=$this->getPage()->getClientScript();
+			$writer->writeLine();
+			$writer->addAttribute('name',self::MAP_NAME_PREFIX.$clientID);
+			$writer->renderBeginTag('map');
+			$writer->writeLine();
+			if(($mode=$this->getHotSpotMode())==='NotSet')
+				$mode='Navigate';
+			$target=$this->getTarget();
+			$i=0;
+			$options['EventTarget'] = $this->getUniqueID();
+			$options['StopEvent'] = true;
+			$cs=$this->getPage()->getClientScript();
+			foreach($hotspots as $hotspot)
+			{
+				if($hotspot->getHotSpotMode()==='NotSet')
+					$hotspot->setHotSpotMode($mode);
+				if($target!=='' && $hotspot->getTarget()==='')
+					$hotspot->setTarget($target);
+				if($hotspot->getHotSpotMode()==='PostBack')
+				{
+					$id=$clientID.'_'.$i;
+					$writer->addAttribute('id',$id);
+					$writer->addAttribute('href','#'.$id); //create unique no-op url references
+					$options['ID']=$id;
+					$options['EventParameter']="$i";
+					$options['CausesValidation']=$hotspot->getCausesValidation();
+					$options['ValidationGroup']=$hotspot->getValidationGroup();
+					$cs->registerPostBackControl($this->getClientClassName(),$options);
+				}
+				$hotspot->render($writer);
+				$writer->writeLine();
+				$i++;
+			}
+			$writer->renderEndTag();
+		}
+	}
+
+	/**
+	 * 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.TImageMap';
+	}
+
+	/**
+	 * Raises the postback event.
+	 * This method is required by {@link IPostBackEventHandler} interface.
+	 * This method is mainly used by framework and control developers.
+	 * @param TEventParameter the event parameter
+	 */
+	public function raisePostBackEvent($param)
+	{
+		$postBackValue=null;
+		if($param!=='')
+		{
+			$index=TPropertyValue::ensureInteger($param);
+			$hotspots=$this->getHotSpots();
+			if($index>=0 && $index<$hotspots->getCount())
+			{
+				$hotspot=$hotspots->itemAt($index);
+				if(($mode=$hotspot->getHotSpotMode())==='NotSet')
+					$mode=$this->getHotSpotMode();
+				if($mode==='PostBack')
+				{
+					$postBackValue=$hotspot->getPostBackValue();
+					if($hotspot->getCausesValidation())
+						$this->getPage()->validate($hotspot->getValidationGroup());
+				}
+			}
+		}
+		if($postBackValue!==null)
+			$this->onClick(new TImageMapEventParameter($postBackValue));
+	}
+
+	/**
+	 * @return string the behavior of hotspot regions in this imagemap when they are clicked. Defaults to 'NotSet'.
+	 */
+	public function getHotSpotMode()
+	{
+		return $this->getViewState('HotSpotMode','NotSet');
+	}
+
+	/**
+	 * Sets the behavior of hotspot regions in this imagemap when they are clicked.
+	 * If an individual hotspot has a mode other than 'NotSet', the mode set in this
+	 * imagemap will be ignored. By default, 'NotSet' is equivalent to 'Navigate'.
+	 * @param string the behavior of hotspot regions in this imagemap when they are clicked.
+	 * Valid values include 'NotSet','Navigate','PostBack','Inactive'.
+	 */
+	public function setHotSpotMode($value)
+	{
+		$this->setViewState('HotSpotMode',TPropertyValue::ensureEnum($value,'NotSet','Navigate','PostBack','Inactive'),'NotSet');
+	}
+
+	/**
+	 * @return THotSpotCollection collection of hotspots defined in this imagemap.
+	 */
+	public function getHotSpots()
+	{
+		if(($hotspots=$this->getViewState('HotSpots',null))===null)
+		{
+			$hotspots=new THotSpotCollection;
+			$this->setViewState('HotSpots',$hotspots);
+		}
+		return $hotspots;
+	}
+
+	/**
+	 * @return string  the target window or frame to display the new page when a hotspot region is clicked within the imagemap. Defaults to ''.
+	 */
+	public function getTarget()
+	{
+		return $this->getViewState('Target','');
+	}
+
+	/**
+	 * @param string  the target window or frame to display the new page when a hotspot region is clicked within the imagemap.
+	 */
+	public function setTarget($value)
+	{
+		$this->setViewState('Target',TPropertyValue::ensureString($value),'');
+	}
+
+	/**
+	 * Raises <b>OnClick</b> event.
+	 * This method is invoked when a hotspot region is clicked within the imagemap.
+	 * If you override this method, be sure to call the parent implementation
+	 * so that the event handler can be invoked.
+	 * @param TImageMapEventParameter event parameter to be passed to the event handlers
+	 */
+	public function onClick($param)
+	{
+		$this->raiseEvent('OnClick',$this,$param);
+	}
+}
+
+/**
+ * TImageMapEventParameter class.
+ *
+ * TImageMapEventParameter represents a postback event parameter
+ * when a hotspot is clicked and posts back in a {@link TImageMap}.
+ * To retrieve the post back value associated with the hotspot being clicked,
+ * access {@link getPostBackValue PostBackValue}.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Revision: $  $Date: $
+ * @package System.Web.UI.WebControls
+ * @since 3.0
+ */
+class TImageMapEventParameter extends TEventParameter
+{
+	private $_postBackValue;
+
+	/**
+	 * Constructor.
+	 * @param string post back value associated with the hotspot clicked
+	 */
+	public function __construct($postBackValue)
+	{
+		$this->_postBackValue=$postBackValue;
+	}
+
+	/**
+	 * @return string post back value associated with the hotspot clicked
+	 */
+	public function getPostBackValue()
+	{
+		return $this->_postBackValue;
+	}
+}
+
+/**
+ * THotSpotCollection class.
+ *
+ * THotSpotCollection represents a collection of hotspots in an imagemap.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Revision: $  $Date: $
+ * @package System.Web.UI.WebControls
+ * @since 3.0
+ */
+class THotSpotCollection extends TList
+{
+	/**
+	 * Inserts an item at the specified position.
+	 * This overrides the parent implementation by inserting only {@link THotSpot}.
+	 * @param integer the speicified position.
+	 * @param mixed new item
+	 * @throws TInvalidDataTypeException if the item to be inserted is not a THotSpot.
+	 */
+	public function insertAt($index,$item)
+	{
+		if($item instanceof THotSpot)
+			parent::insertAt($index,$item);
+		else
+			throw new TInvalidDataTypeException('hotspotcollection_hotspot_required');
+	}
+}
+
+
+/**
+ * THotSpot class.
+ *
+ * THotSpot implements the basic functionality common to all hot spot shapes.
+ * Derived classes include {@link TCircleHotSpot}, {@link TPolygonHotSpot}
+ * and {@link TRectangleHotSpot}.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Revision: $  $Date: $
+ * @package System.Web.UI.WebControls
+ * @since 3.0
+ */
+abstract class THotSpot extends TComponent
+{
+	private $_viewState=array();
+
+	/**
+	 * Returns a viewstate value.
+	 *
+	 * This function is very useful in defining getter functions for component properties
+	 * that must be kept in viewstate.
+	 * @param string the name of the viewstate value to be returned
+	 * @param mixed the default value. If $key is not found in viewstate, $defaultValue will be returned
+	 * @return mixed the viewstate value corresponding to $key
+	 */
+	protected function getViewState($key,$defaultValue=null)
+	{
+		return isset($this->_viewState[$key])?$this->_viewState[$key]:$defaultValue;
+	}
+
+	/**
+	 * Sets a viewstate value.
+	 *
+	 * This function is very useful in defining setter functions for control properties
+	 * that must be kept in viewstate.
+	 * Make sure that the viewstate value must be serializable and unserializable.
+	 * @param string the name of the viewstate value
+	 * @param mixed the viewstate value to be set
+	 * @param mixed default value. If $value===$defaultValue, the item will be cleared from the viewstate.
+	 */
+	protected function setViewState($key,$value,$defaultValue=null)
+	{
+		if($value===$defaultValue)
+			unset($this->_viewState[$key]);
+		else
+			$this->_viewState[$key]=$value;
+	}
+
+	/**
+	 * @return string shape of the hotspot, can be 'circle', 'rect', 'poly', etc.
+	 */
+	abstract public function getShape();
+	/**
+	 * @return string coordinates defining the hotspot shape.
+	 */
+	abstract public function getCoordinates();
+
+	/**
+	 * @return string the access key that allows you to quickly navigate to the HotSpot region. Defaults to ''.
+	 */
+	public function getAccessKey()
+	{
+		return $this->getViewState('AccessKey','');
+	}
+
+	/**
+	 * @param string the access key that allows you to quickly navigate to the HotSpot region.
+	 */
+	public function setAccessKey($value)
+	{
+		$this->setViewState('AccessKey',TPropertyValue::ensureString($value),'');
+	}
+
+	/**
+	 * @return string the alternate text to display for a HotSpot object. Defaults to ''.
+	 */
+	public function getAlternateText()
+	{
+		return $this->getViewState('AlternateText','');
+	}
+
+	/**
+	 * @param string the alternate text to display for a HotSpot object.
+	 */
+	public function setAlternateText($value)
+	{
+		$this->setViewState('AlternateText',TPropertyValue::ensureString($value),'');
+	}
+
+	/**
+	 * @return string the behavior of a HotSpot object when it is clicked. Defaults to 'NotSet'.
+	 */
+	public function getHotSpotMode()
+	{
+		return $this->getViewState('HotSpotMode','NotSet');
+	}
+
+	/**
+	 * @param string the behavior of a HotSpot object when it is clicked.
+	 * Valid values include 'NotSet','Navigate','PostBack','Inactive'.
+	 */
+	public function setHotSpotMode($value)
+	{
+		$this->setViewState('HotSpotMode',TPropertyValue::ensureEnum($value,'NotSet','Navigate','PostBack','Inactive'),'NotSet');
+	}
+
+	/**
+	 * @return string the URL to navigate to when a HotSpot object is clicked. Defaults to ''.
+	 */
+	public function getNavigateUrl()
+	{
+		return $this->getViewState('NavigateUrl','');
+	}
+
+	/**
+	 * @param string the URL to navigate to when a HotSpot object is clicked.
+	 */
+	public function setNavigateUrl($value)
+	{
+		$this->setViewState('NavigateUrl',TPropertyValue::ensureString($value),'');
+	}
+
+	/**
+	 * @return string a value that is post back when the HotSpot is clicked. Defaults to ''.
+	 */
+	public function getPostBackValue()
+	{
+		return $this->getViewState('PostBackValue','');
+	}
+
+	/**
+	 * @param string a value that is post back when the HotSpot is clicked.
+	 */
+	public function setPostBackValue($value)
+	{
+		$this->setViewState('PostBackValue',TPropertyValue::ensureString($value),'');
+	}
+
+	/**
+	 * @return integer the tab index of the HotSpot region. Defaults to 0.
+	 */
+	public function getTabIndex()
+	{
+		return $this->getViewState('TabIndex',0);
+	}
+
+	/**
+	 * @param integer the tab index of the HotSpot region.
+	 */
+	public function setTabIndex($value)
+	{
+		$this->setViewState('TabIndex',TPropertyValue::ensureInteger($value),0);
+	}
+
+	/**
+	 * @return boolean whether postback event trigger by this hotspot will cause input validation, default is true
+	 */
+	public function getCausesValidation()
+	{
+		return $this->getViewState('CausesValidation',true);
+	}
+
+	/**
+	 * @param boolean whether postback event trigger by this hotspot will cause input validation
+	 */
+	public function setCausesValidation($value)
+	{
+		$this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true);
+	}
+
+	/**
+	 * @return string the group of validators which the hotspot causes validation upon postback
+	 */
+	public function getValidationGroup()
+	{
+		return $this->getViewState('ValidationGroup','');
+	}
+
+	/**
+	 * @param string the group of validators which the hotspot causes validation upon postback
+	 */
+	public function setValidationGroup($value)
+	{
+		$this->setViewState('ValidationGroup',$value,'');
+	}
+
+	/**
+	 * @return string  the target window or frame to display the new page when the HotSpot region
+	 * is clicked. Defaults to ''.
+	 */
+	public function getTarget()
+	{
+		return $this->getViewState('Target','');
+	}
+
+	/**
+	 * @param string  the target window or frame to display the new page when the HotSpot region
+	 * is clicked.
+	 */
+	public function setTarget($value)
+	{
+		$this->setViewState('Target',TPropertyValue::ensureString($value),'');
+	}
+
+	/**
+	 * Renders this hotspot.
+	 * @param THtmlWriter
+	 */
+	public function render($writer)
+	{
+		$writer->addAttribute('shape',$this->getShape());
+		$writer->addAttribute('coords',$this->getCoordinates());
+		if(($mode=$this->getHotSpotMode())==='NotSet')
+			$mode='Navigate';
+		if($mode==='Navigate')
+		{
+			$writer->addAttribute('href',$this->getNavigateUrl());
+			if(($target=$this->getTarget())!=='')
+				$writer->addAttribute('target',$target);
+		}
+		else if($mode==='Inactive')
+			$writer->addAttribute('nohref','true');
+		$text=$this->getAlternateText();
+		$writer->addAttribute('title',$text);
+		$writer->addAttribute('alt',$text);
+		if(($accessKey=$this->getAccessKey())!=='')
+			$writer->addAttribute('accesskey',$accessKey);
+		if(($tabIndex=$this->getTabIndex())!==0)
+			$writer->addAttribute('tabindex',"$tabIndex");
+		$writer->renderBeginTag('area');
+		$writer->renderEndTag();
+	}
+}
+
+/**
+ * Class TCircleHotSpot.
+ *
+ * TCircleHotSpot defines a circular hot spot region in a {@link TImageMap}
+ * control.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Revision: $  $Date: $
+ * @package System.Web.UI.WebControls
+ * @since 3.0
+ */
+class TCircleHotSpot extends THotSpot
+{
+	/**
+	 * @return string shape of this hotspot.
+	 */
+	public function getShape()
+	{
+		return 'circle';
+	}
+
+	/**
+	 * @return string coordinates defining this hotspot shape
+	 */
+	public function getCoordinates()
+	{
+		return $this->getX().','.$this->getY().','.$this->getRadius();
+	}
+
+	/**
+	 * @return integer radius of the circular HotSpot region. Defaults to 0.
+	 */
+	public function getRadius()
+	{
+		return $this->getViewState('Radius',0);
+	}
+
+	/**
+	 * @param integer radius of the circular HotSpot region.
+	 */
+	public function setRadius($value)
+	{
+		$this->setViewState('Radius',TPropertyValue::ensureInteger($value),0);
+	}
+
+	/**
+	 * @return integer the X coordinate of the center of the circular HotSpot region. Defaults to 0.
+	 */
+	public function getX()
+	{
+		return $this->getViewState('X',0);
+	}
+
+	/**
+	 * @param integer the X coordinate of the center of the circular HotSpot region.
+	 */
+	public function setX($value)
+	{
+		$this->setViewState('X',TPropertyValue::ensureInteger($value),0);
+	}
+
+	/**
+	 * @return integer the Y coordinate of the center of the circular HotSpot region. Defaults to 0.
+	 */
+	public function getY()
+	{
+		return $this->getViewState('Y',0);
+	}
+
+	/**
+	 * @param integer the Y coordinate of the center of the circular HotSpot region.
+	 */
+	public function setY($value)
+	{
+		$this->setViewState('Y',TPropertyValue::ensureInteger($value),0);
+	}
+}
+
+/**
+ * Class TRectangleHotSpot.
+ *
+ * TRectangleHotSpot defines a rectangle hot spot region in a {@link
+ * TImageMap} control.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Revision: $  $Date: $
+ * @package System.Web.UI.WebControls
+ * @since 3.0
+ */
+class TRectangleHotSpot extends THotSpot
+{
+	/**
+	 * @return string shape of this hotspot.
+	 */
+	public function getShape()
+	{
+		return 'rect';
+	}
+
+	/**
+	 * @return string coordinates defining this hotspot shape
+	 */
+	public function getCoordinates()
+	{
+		return $this->getLeft().','.$this->getTop().','.$this->getRight().','.$this->getBottom();
+	}
+
+	/**
+	 * @return integer the Y coordinate of the bottom side of the rectangle HotSpot region. Defaults to 0.
+	 */
+	public function getBottom()
+	{
+		return $this->getViewState('Bottom',0);
+	}
+
+	/**
+	 * @param integer the Y coordinate of the bottom side of the rectangle HotSpot region.
+	 */
+	public function setBottom($value)
+	{
+		$this->setViewState('Bottom',TPropertyValue::ensureInteger($value),0);
+	}
+
+	/**
+	 * @return integer the X coordinate of the right side of the rectangle HotSpot region. Defaults to 0.
+	 */
+	public function getLeft()
+	{
+		return $this->getViewState('Left',0);
+	}
+
+	/**
+	 * @param integer the X coordinate of the right side of the rectangle HotSpot region.
+	 */
+	public function setLeft($value)
+	{
+		$this->setViewState('Left',TPropertyValue::ensureInteger($value),0);
+	}
+
+	/**
+	 * @return integer the X coordinate of the right side of the rectangle HotSpot region. Defaults to 0.
+	 */
+	public function getRight()
+	{
+		return $this->getViewState('Right',0);
+	}
+
+	/**
+	 * @param integer the X coordinate of the right side of the rectangle HotSpot region.
+	 */
+	public function setRight($value)
+	{
+		$this->setViewState('Right',TPropertyValue::ensureInteger($value),0);
+	}
+
+	/**
+	 * @return integer the Y coordinate of the top side of the rectangle HotSpot region. Defaults to 0.
+	 */
+	public function getTop()
+	{
+		return $this->getViewState('Top',0);
+	}
+
+	/**
+	 * @param integer the Y coordinate of the top side of the rectangle HotSpot region.
+	 */
+	public function setTop($value)
+	{
+		$this->setViewState('Top',TPropertyValue::ensureInteger($value),0);
+	}
+}
+
+/**
+ * Class TPolygonHotSpot.
+ *
+ * TPolygonHotSpot defines a polygon hot spot region in a {@link
+ * TImageMap} control.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Revision: $  $Date: $
+ * @package System.Web.UI.WebControls
+ * @since 3.0
+ */
+class TPolygonHotSpot extends THotSpot
+{
+	/**
+	 * @return string shape of this hotspot.
+	 */
+	public function getShape()
+	{
+		return 'poly';
+	}
+
+	/**
+	 * @return string coordinates of the vertices defining the polygon.
+	 * Coordinates are concatenated together with comma ','. Each pair
+	 * represents (x,y) of a vertex.
+	 */
+	public function getCoordinates()
+	{
+		return $this->getViewState('Coordinates','');
+	}
+
+	/**
+	 * @param string coordinates of the vertices defining the polygon.
+	 * Coordinates are concatenated together with comma ','. Each pair
+	 * represents (x,y) of a vertex.
+	 */
+	public function setCoordinates($value)
+	{
+		$this->setViewState('Coordinates',$value,'');
+	}
+}
+
+?>
diff --git a/framework/Web/UI/WebControls/TLinkButton.php b/framework/Web/UI/WebControls/TLinkButton.php
index 84e1d5a4..6c318944 100644
--- a/framework/Web/UI/WebControls/TLinkButton.php
+++ b/framework/Web/UI/WebControls/TLinkButton.php
@@ -1,255 +1,265 @@
-<?php
-/**
- * TLinkButton class file
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright &copy; 2005 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Revision: $  $Date: $
- * @package System.Web.UI.WebControls
- */
-
-/**
- * TLinkButton class
- *
- * TLinkButton creates a hyperlink style button on the page.
- * TLinkButton has the same appearance as a hyperlink. However, it is mainly
- * used to submit data to a page. Like {@link TButton}, you can create either
- * a <b>submit</b> button or a <b>command</b> button.
- *
- * A <b>command</b> button has a command name (specified by
- * the {@link setCommandName CommandName} property) and and a command parameter
- * (specified by {@link setCommandParameter CommandParameter} property)
- * associated with the button. This allows you to create multiple TLinkButton
- * components on a Web page and programmatically determine which one is clicked
- * with what parameter. You can provide an event handler for
- * {@link onCommand OnCommand} event to programmatically control the actions performed
- * when the command button is clicked. In the event handler, you can determine
- * the {@link setCommandName CommandName} property value and
- * the {@link setCommandParameter CommandParameter} property value
- * through the {@link TCommandParameter::getName Name} and
- * {@link TCommandParameter::getParameter Parameter} properties of the event
- * parameter which is of type {@link TCommandEventParameter}.
- *
- * A <b>submit</b> button does not have a command name associated with the button
- * and clicking on it simply posts the Web page back to the server.
- * By default, a TLinkButton component is a submit button.
- * You can provide an event handler for the {@link onClick OnClick} event
- * to programmatically control the actions performed when the submit button is clicked.
- *
- * Clicking on button can trigger form validation, if
- * {@link setCausesValidation CausesValidation} is true.
- * And the validation may be restricted within a certain group of validator
- * controls by setting {@link setValidationGroup ValidationGroup} property.
- * If validation is successful, the data will be post back to the same page.
- *
- * TLinkButton will display the {@link setText Text} property value
- * as the hyperlink text. If {@link setText Text} is empty, the body content
- * of TLinkButton will be displayed. Therefore, you can use TLinkButton
- * as an image button by enclosing an &lt;img&gt; tag as the body of TLinkButton.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Revision: $  $Date: $
- * @package System.Web.UI.WebControls
- * @since 3.0
- */
-class TLinkButton extends TWebControl implements IPostBackEventHandler, IButtonControl
-{
-	/**
-	 * @return string tag name of the button
-	 */
-	protected function getTagName()
-	{
-		return 'a';
-	}
-
-	/**
-	 * Adds attribute name-value pairs to renderer.
-	 * This overrides the parent implementation with additional button specific attributes.
-	 * @param THtmlWriter the writer used for the rendering purpose
-	 */
-	protected function addAttributesToRender($writer)
-	{
-		$page=$this->getPage();
-		$page->ensureRenderInForm($this);
-
-		$writer->addAttribute('id',$this->getClientID());
-
-		// We call parent implementation here because some attributes
-		// may be overwritten in the following
-		parent::addAttributesToRender($writer);
-
-		if($this->getEnabled(true))
-			$this->renderClientControlScript($writer);
-		else if($this->getEnabled()) // in this case, parent will not render 'disabled'
-			$writer->addAttribute('disabled','disabled');
-	}
-
-	/**
-	 * Renders the client-script code.
-	 */
-	protected function renderClientControlScript($writer)
-	{
-		//create unique no-op url references
-		$nop = "javascript:;//".$this->getClientID();
-		$writer->addAttribute('href', $nop);
-		$cs = $this->getPage()->getClientScript();
-		$cs->registerPostBackControl('Prado.WebUI.TLinkButton',$this->getPostBackOptions());
-	}
-
-	/**
-	 * Returns postback specifications for the button.
-	 * This method is used by framework and control developers.
-	 * @return array parameters about how the button defines its postback behavior.
-	 */
-	protected function getPostBackOptions()
-	{
-		$options['ID'] = $this->getClientID();
-		$options['EventTarget'] = $this->getUniqueID();
-		$options['CausesValidation'] = $this->getCausesValidation();
-		$options['ValidationGroup'] = $this->getValidationGroup();
-		$options['StopEvent'] = true;
-
-		return $options;
-	}
-
-	/**
-	 * Renders the body content enclosed between the control tag.
-	 * If {@link getText Text} is not empty, it will be rendered. Otherwise,
-	 * the body content enclosed in the control tag will be rendered.
-	 * @param THtmlWriter the writer used for the rendering purpose
-	 */
-	public function renderContents($writer)
-	{
-		if(($text=$this->getText())==='')
-			parent::renderContents($writer);
-		else
-			$writer->write($text);
-	}
-
-	/**
-	 * @return string the text caption of the button
-	 */
-	public function getText()
-	{
-		return $this->getViewState('Text','');
-	}
-
-	/**
-	 * @param string the text caption to be set
-	 */
-	public function setText($value)
-	{
-		$this->setViewState('Text',$value,'');
-	}
-
-	/**
-	 * @return string the command name associated with the {@link onCommand OnCommand} event.
-	 */
-	public function getCommandName()
-	{
-		return $this->getViewState('CommandName','');
-	}
-
-	/**
-	 * @param string the command name associated with the {@link onCommand OnCommand} event.
-	 */
-	public function setCommandName($value)
-	{
-		$this->setViewState('CommandName',$value,'');
-	}
-
-	/**
-	 * @return string the parameter associated with the {@link onCommand OnCommand} event
-	 */
-	public function getCommandParameter()
-	{
-		return $this->getViewState('CommandParameter','');
-	}
-
-	/**
-	 * @param string the parameter associated with the {@link onCommand OnCommand} event.
-	 */
-	public function setCommandParameter($value)
-	{
-		$this->setViewState('CommandParameter',$value,'');
-	}
-
-	/**
-	 * @return boolean whether postback event trigger by this button will cause input validation
-	 */
-	public function getCausesValidation()
-	{
-		return $this->getViewState('CausesValidation',true);
-	}
-
-	/**
-	 * Sets the value indicating whether postback event trigger by this button will cause input validation.
-	 * @param string the text caption to be set
-	 */
-	public function setCausesValidation($value)
-	{
-		$this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true);
-	}
-
-	/**
-	 * @return string the group of validators which the button causes validation upon postback
-	 */
-	public function getValidationGroup()
-	{
-		return $this->getViewState('ValidationGroup','');
-	}
-
-	/**
-	 * @param string the group of validators which the button causes validation upon postback
-	 */
-	public function setValidationGroup($value)
-	{
-		$this->setViewState('ValidationGroup',$value,'');
-	}
-
-	/**
-	 * Raises the postback event.
-	 * This method is required by {@link IPostBackEventHandler} interface.
-	 * If {@link getCausesValidation CausesValidation} is true, it will
-	 * invoke the page's {@link TPage::validate validate} method first.
-	 * It will raise {@link onClick OnClick} and {@link onCommand OnCommand} events.
-	 * This method is mainly used by framework and control developers.
-	 * @param TEventParameter the event parameter
-	 */
-	public function raisePostBackEvent($param)
-	{
-		if($this->getCausesValidation())
-			$this->getPage()->validate($this->getValidationGroup());
-		$this->onClick(null);
-		$this->onCommand(new TCommandEventParameter($this->getCommandName(),$this->getCommandParameter()));
-	}
-
-	/**
-	 * This method is invoked when the button is clicked.
-	 * The method raises 'OnClick' event to fire up the event handlers.
-	 * If you override this method, be sure to call the parent implementation
-	 * so that the event handler can be invoked.
-	 * @param TEventParameter event parameter to be passed to the event handlers
-	 */
-	public function onClick($param)
-	{
-		$this->raiseEvent('OnClick',$this,$param);
-	}
-
-	/**
-	 * This method is invoked when the button is clicked.
-	 * The method raises 'OnCommand' event to fire up the event handlers.
-	 * If you override this method, be sure to call the parent implementation
-	 * so that the event handlers can be invoked.
-	 * @param TCommandEventParameter event parameter to be passed to the event handlers
-	 */
-	public function onCommand($param)
-	{
-		$this->raiseEvent('OnCommand',$this,$param);
-		$this->raiseBubbleEvent($this,$param);
-	}
-}
-
-?>
+<?php
+/**
+ * TLinkButton class file
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Revision: $  $Date: $
+ * @package System.Web.UI.WebControls
+ */
+
+/**
+ * TLinkButton class
+ *
+ * TLinkButton creates a hyperlink style button on the page.
+ * TLinkButton has the same appearance as a hyperlink. However, it is mainly
+ * used to submit data to a page. Like {@link TButton}, you can create either
+ * a <b>submit</b> button or a <b>command</b> button.
+ *
+ * A <b>command</b> button has a command name (specified by
+ * the {@link setCommandName CommandName} property) and and a command parameter
+ * (specified by {@link setCommandParameter CommandParameter} property)
+ * associated with the button. This allows you to create multiple TLinkButton
+ * components on a Web page and programmatically determine which one is clicked
+ * with what parameter. You can provide an event handler for
+ * {@link onCommand OnCommand} event to programmatically control the actions performed
+ * when the command button is clicked. In the event handler, you can determine
+ * the {@link setCommandName CommandName} property value and
+ * the {@link setCommandParameter CommandParameter} property value
+ * through the {@link TCommandParameter::getName Name} and
+ * {@link TCommandParameter::getParameter Parameter} properties of the event
+ * parameter which is of type {@link TCommandEventParameter}.
+ *
+ * A <b>submit</b> button does not have a command name associated with the button
+ * and clicking on it simply posts the Web page back to the server.
+ * By default, a TLinkButton component is a submit button.
+ * You can provide an event handler for the {@link onClick OnClick} event
+ * to programmatically control the actions performed when the submit button is clicked.
+ *
+ * Clicking on button can trigger form validation, if
+ * {@link setCausesValidation CausesValidation} is true.
+ * And the validation may be restricted within a certain group of validator
+ * controls by setting {@link setValidationGroup ValidationGroup} property.
+ * If validation is successful, the data will be post back to the same page.
+ *
+ * TLinkButton will display the {@link setText Text} property value
+ * as the hyperlink text. If {@link setText Text} is empty, the body content
+ * of TLinkButton will be displayed. Therefore, you can use TLinkButton
+ * as an image button by enclosing an &lt;img&gt; tag as the body of TLinkButton.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Revision: $  $Date: $
+ * @package System.Web.UI.WebControls
+ * @since 3.0
+ */
+class TLinkButton extends TWebControl implements IPostBackEventHandler, IButtonControl
+{
+	/**
+	 * @return string tag name of the button
+	 */
+	protected function getTagName()
+	{
+		return 'a';
+	}
+
+	/**
+	 * Adds attribute name-value pairs to renderer.
+	 * This overrides the parent implementation with additional button specific attributes.
+	 * @param THtmlWriter the writer used for the rendering purpose
+	 */
+	protected function addAttributesToRender($writer)
+	{
+		$page=$this->getPage();
+		$page->ensureRenderInForm($this);
+
+		$writer->addAttribute('id',$this->getClientID());
+
+		// We call parent implementation here because some attributes
+		// may be overwritten in the following
+		parent::addAttributesToRender($writer);
+
+		if($this->getEnabled(true))
+			$this->renderClientControlScript($writer);
+		else if($this->getEnabled()) // in this case, parent will not render 'disabled'
+			$writer->addAttribute('disabled','disabled');
+	}
+
+	/**
+	 * Renders the client-script code.
+	 */
+	protected function renderClientControlScript($writer)
+	{
+		//create unique no-op url references
+		$nop = "javascript:;//".$this->getClientID();
+		$writer->addAttribute('href', $nop);
+		$cs = $this->getPage()->getClientScript();
+		$cs->registerPostBackControl($this->getClientClassName(),$this->getPostBackOptions());
+	}
+
+	/**
+	 * 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.TLinkButton';
+	}
+
+	/**
+	 * Returns postback specifications for the button.
+	 * This method is used by framework and control developers.
+	 * @return array parameters about how the button defines its postback behavior.
+	 */
+	protected function getPostBackOptions()
+	{
+		$options['ID'] = $this->getClientID();
+		$options['EventTarget'] = $this->getUniqueID();
+		$options['CausesValidation'] = $this->getCausesValidation();
+		$options['ValidationGroup'] = $this->getValidationGroup();
+		$options['StopEvent'] = true;
+
+		return $options;
+	}
+
+	/**
+	 * Renders the body content enclosed between the control tag.
+	 * If {@link getText Text} is not empty, it will be rendered. Otherwise,
+	 * the body content enclosed in the control tag will be rendered.
+	 * @param THtmlWriter the writer used for the rendering purpose
+	 */
+	public function renderContents($writer)
+	{
+		if(($text=$this->getText())==='')
+			parent::renderContents($writer);
+		else
+			$writer->write($text);
+	}
+
+	/**
+	 * @return string the text caption of the button
+	 */
+	public function getText()
+	{
+		return $this->getViewState('Text','');
+	}
+
+	/**
+	 * @param string the text caption to be set
+	 */
+	public function setText($value)
+	{
+		$this->setViewState('Text',$value,'');
+	}
+
+	/**
+	 * @return string the command name associated with the {@link onCommand OnCommand} event.
+	 */
+	public function getCommandName()
+	{
+		return $this->getViewState('CommandName','');
+	}
+
+	/**
+	 * @param string the command name associated with the {@link onCommand OnCommand} event.
+	 */
+	public function setCommandName($value)
+	{
+		$this->setViewState('CommandName',$value,'');
+	}
+
+	/**
+	 * @return string the parameter associated with the {@link onCommand OnCommand} event
+	 */
+	public function getCommandParameter()
+	{
+		return $this->getViewState('CommandParameter','');
+	}
+
+	/**
+	 * @param string the parameter associated with the {@link onCommand OnCommand} event.
+	 */
+	public function setCommandParameter($value)
+	{
+		$this->setViewState('CommandParameter',$value,'');
+	}
+
+	/**
+	 * @return boolean whether postback event trigger by this button will cause input validation
+	 */
+	public function getCausesValidation()
+	{
+		return $this->getViewState('CausesValidation',true);
+	}
+
+	/**
+	 * Sets the value indicating whether postback event trigger by this button will cause input validation.
+	 * @param string the text caption to be set
+	 */
+	public function setCausesValidation($value)
+	{
+		$this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true);
+	}
+
+	/**
+	 * @return string the group of validators which the button causes validation upon postback
+	 */
+	public function getValidationGroup()
+	{
+		return $this->getViewState('ValidationGroup','');
+	}
+
+	/**
+	 * @param string the group of validators which the button causes validation upon postback
+	 */
+	public function setValidationGroup($value)
+	{
+		$this->setViewState('ValidationGroup',$value,'');
+	}
+
+	/**
+	 * Raises the postback event.
+	 * This method is required by {@link IPostBackEventHandler} interface.
+	 * If {@link getCausesValidation CausesValidation} is true, it will
+	 * invoke the page's {@link TPage::validate validate} method first.
+	 * It will raise {@link onClick OnClick} and {@link onCommand OnCommand} events.
+	 * This method is mainly used by framework and control developers.
+	 * @param TEventParameter the event parameter
+	 */
+	public function raisePostBackEvent($param)
+	{
+		if($this->getCausesValidation())
+			$this->getPage()->validate($this->getValidationGroup());
+		$this->onClick(null);
+		$this->onCommand(new TCommandEventParameter($this->getCommandName(),$this->getCommandParameter()));
+	}
+
+	/**
+	 * This method is invoked when the button is clicked.
+	 * The method raises 'OnClick' event to fire up the event handlers.
+	 * If you override this method, be sure to call the parent implementation
+	 * so that the event handler can be invoked.
+	 * @param TEventParameter event parameter to be passed to the event handlers
+	 */
+	public function onClick($param)
+	{
+		$this->raiseEvent('OnClick',$this,$param);
+	}
+
+	/**
+	 * This method is invoked when the button is clicked.
+	 * The method raises 'OnCommand' event to fire up the event handlers.
+	 * If you override this method, be sure to call the parent implementation
+	 * so that the event handlers can be invoked.
+	 * @param TCommandEventParameter event parameter to be passed to the event handlers
+	 */
+	public function onCommand($param)
+	{
+		$this->raiseEvent('OnCommand',$this,$param);
+		$this->raiseBubbleEvent($this,$param);
+	}
+}
+
+?>
diff --git a/framework/Web/UI/WebControls/TRadioButton.php b/framework/Web/UI/WebControls/TRadioButton.php
index 64387683..bb3e0658 100644
--- a/framework/Web/UI/WebControls/TRadioButton.php
+++ b/framework/Web/UI/WebControls/TRadioButton.php
@@ -1,182 +1,192 @@
-<?php
-/**
- * TRadioButton class file
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright &copy; 2005 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Revision: $  $Date: $
- * @package System.Web.UI.WebControls
- */
-
-/**
- * Using TCheckBox parent class
- */
-Prado::using('System.Web.UI.WebControls.TCheckBox');
-/**
- * Using TRadioButtonList class
- */
-Prado::using('System.Web.UI.WebControls.TRadioButtonList');
-
-/**
- * TRadioButton class
- *
- * TRadioButton displays a radio button on the page.
- * You can specify the caption to display beside the radio buttonby setting
- * the {@link setText Text} property.  The caption can appear either on the right
- * or left of the radio button, which is determined by the {@link setTextAlign TextAlign}
- * property.
- *
- * To determine whether the TRadioButton component is checked, test the {@link getChecked Checked}
- * property. The {@link onCheckedChanged OnCheckedChanged} event is raised when
- * the {@link getChecked Checked} state of the TRadioButton component changes
- * between posts to the server. You can provide an event handler for
- * the {@link onCheckedChanged OnCheckedChanged} event to  to programmatically
- * control the actions performed when the state of the TRadioButton component changes
- * between posts to the server.
- *
- * TRadioButton uses {@link setGroupName GroupName} to group together a set of radio buttons.
- *
- * If {@link setAutoPostBack AutoPostBack} is set true, changing the radio button state
- * will cause postback action. And if {@link setCausesValidation CausesValidation}
- * is true, validation will also be processed, which can be further restricted within
- * a {@link setValidationGroup ValidationGroup}.
- *
- * Note, {@link setText Text} is rendered as is. Make sure it does not contain unwanted characters
- * that may bring security vulnerabilities.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Revision: $  $Date: $
- * @package System.Web.UI.WebControls
- * @since 3.0
- */
-class TRadioButton extends TCheckBox
-{
-	/**
-	 * @var string the name used to fetch radiobutton post data
-	 */
-	private $_uniqueGroupName=null;
-
-	/**
-	 * 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)
-	{
-		$uniqueGroupName=$this->getUniqueGroupName();
-		$value=isset($values[$uniqueGroupName])?$values[$uniqueGroupName]:null;
-		if($value!==null && $value===$this->getValueAttribute())
-		{
-			if(!$this->getChecked())
-			{
-				$this->setChecked(true);
-				return true;
-			}
-			else
-				return false;
-		}
-		else if($this->getChecked())
-			$this->setChecked(false);
-		return false;
-	}
-
-	/**
-	 * @return string the name of the group that the radio button belongs to. Defaults to empty.
-	 */
-	public function getGroupName()
-	{
-		return $this->getViewState('GroupName','');
-	}
-
-	/**
-	 * Sets the name of the group that the radio button belongs to
-	 * @param string the group name
-	 */
-	public function setGroupName($value)
-	{
-		$this->setViewState('GroupName',$value,'');
-	}
-
-	protected function getValueAttribute()
-	{
-		if(($value=parent::getValueAttribute())==='')
-			return $this->getUniqueID();
-		else
-			return $value;
-	}
-
-	/**
-	 * @return string the name used to fetch radiobutton post data
-	 */
-	private function getUniqueGroupName()
-	{
-		if($this->_uniqueGroupName===null)
-		{
-			$groupName=$this->getGroupName();
-			$uniqueID=$this->getUniqueID();
-			if($uniqueID!=='')
-			{
-				if(($pos=strrpos($uniqueID,TControl::ID_SEPARATOR))!==false)
-				{
-					if($groupName!=='')
-						$groupName=substr($uniqueID,0,$pos+1).$groupName;
-					else if($this->getNamingContainer() instanceof TRadioButtonList)
-						$groupName=substr($uniqueID,0,$pos);
-				}
-				if($groupName==='')
-					$groupName=$uniqueID;
-			}
-			$this->_uniqueGroupName=$groupName;
-		}
-		return $this->_uniqueGroupName;
-	}
-
-	/**
-	 * Renders a radiobutton input element.
-	 * @param THtmlWriter the writer for the rendering purpose
-	 * @param string checkbox id
-	 * @param string onclick js
-	 */
-	protected function renderInputTag($writer,$clientID,$onclick)
-	{
-		if($clientID!=='')
-			$writer->addAttribute('id',$clientID);
-		$writer->addAttribute('type','radio');
-		$writer->addAttribute('name',$this->getUniqueGroupName());
-		$writer->addAttribute('value',$this->getValueAttribute());
-		if($onclick!=='')
-			$writer->addAttribute('onclick',$onclick);
-		if($this->getChecked())
-			$writer->addAttribute('checked','checked');
-		if(!$this->getEnabled(true))
-			$writer->addAttribute('disabled','disabled');
-
-		$page=$this->getPage();
-		if($this->getEnabled(true) && $this->getAutoPostBack() && $page->getClientSupportsJavaScript())
-			$this->renderClientControlScript($writer);
-
-		if(($accesskey=$this->getAccessKey())!=='')
-			$writer->addAttribute('accesskey',$accesskey);
-		if(($tabindex=$this->getTabIndex())>0)
-			$writer->addAttribute('tabindex',"$tabindex");
-		if($attributes=$this->getViewState('InputAttributes',null))
-			$writer->addAttributes($attributes);
-		$writer->renderBeginTag('input');
-		$writer->renderEndTag();
-	}
-
-	/**
-	 * Renders the client-script code.
-	 */
-	protected function renderClientControlScript($writer)
-	{
-		$cs = $this->getPage()->getClientScript();
-		$cs->registerPostBackControl('Prado.WebUI.TRadioButton',$this->getPostBackOptions());
-	}
-}
-
-?>
\ No newline at end of file
+<?php
+/**
+ * TRadioButton class file
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Revision: $  $Date: $
+ * @package System.Web.UI.WebControls
+ */
+
+/**
+ * Using TCheckBox parent class
+ */
+Prado::using('System.Web.UI.WebControls.TCheckBox');
+/**
+ * Using TRadioButtonList class
+ */
+Prado::using('System.Web.UI.WebControls.TRadioButtonList');
+
+/**
+ * TRadioButton class
+ *
+ * TRadioButton displays a radio button on the page.
+ * You can specify the caption to display beside the radio buttonby setting
+ * the {@link setText Text} property.  The caption can appear either on the right
+ * or left of the radio button, which is determined by the {@link setTextAlign TextAlign}
+ * property.
+ *
+ * To determine whether the TRadioButton component is checked, test the {@link getChecked Checked}
+ * property. The {@link onCheckedChanged OnCheckedChanged} event is raised when
+ * the {@link getChecked Checked} state of the TRadioButton component changes
+ * between posts to the server. You can provide an event handler for
+ * the {@link onCheckedChanged OnCheckedChanged} event to  to programmatically
+ * control the actions performed when the state of the TRadioButton component changes
+ * between posts to the server.
+ *
+ * TRadioButton uses {@link setGroupName GroupName} to group together a set of radio buttons.
+ *
+ * If {@link setAutoPostBack AutoPostBack} is set true, changing the radio button state
+ * will cause postback action. And if {@link setCausesValidation CausesValidation}
+ * is true, validation will also be processed, which can be further restricted within
+ * a {@link setValidationGroup ValidationGroup}.
+ *
+ * Note, {@link setText Text} is rendered as is. Make sure it does not contain unwanted characters
+ * that may bring security vulnerabilities.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Revision: $  $Date: $
+ * @package System.Web.UI.WebControls
+ * @since 3.0
+ */
+class TRadioButton extends TCheckBox
+{
+	/**
+	 * @var string the name used to fetch radiobutton post data
+	 */
+	private $_uniqueGroupName=null;
+
+	/**
+	 * 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)
+	{
+		$uniqueGroupName=$this->getUniqueGroupName();
+		$value=isset($values[$uniqueGroupName])?$values[$uniqueGroupName]:null;
+		if($value!==null && $value===$this->getValueAttribute())
+		{
+			if(!$this->getChecked())
+			{
+				$this->setChecked(true);
+				return true;
+			}
+			else
+				return false;
+		}
+		else if($this->getChecked())
+			$this->setChecked(false);
+		return false;
+	}
+
+	/**
+	 * @return string the name of the group that the radio button belongs to. Defaults to empty.
+	 */
+	public function getGroupName()
+	{
+		return $this->getViewState('GroupName','');
+	}
+
+	/**
+	 * Sets the name of the group that the radio button belongs to
+	 * @param string the group name
+	 */
+	public function setGroupName($value)
+	{
+		$this->setViewState('GroupName',$value,'');
+	}
+
+	protected function getValueAttribute()
+	{
+		if(($value=parent::getValueAttribute())==='')
+			return $this->getUniqueID();
+		else
+			return $value;
+	}
+
+	/**
+	 * @return string the name used to fetch radiobutton post data
+	 */
+	private function getUniqueGroupName()
+	{
+		if($this->_uniqueGroupName===null)
+		{
+			$groupName=$this->getGroupName();
+			$uniqueID=$this->getUniqueID();
+			if($uniqueID!=='')
+			{
+				if(($pos=strrpos($uniqueID,TControl::ID_SEPARATOR))!==false)
+				{
+					if($groupName!=='')
+						$groupName=substr($uniqueID,0,$pos+1).$groupName;
+					else if($this->getNamingContainer() instanceof TRadioButtonList)
+						$groupName=substr($uniqueID,0,$pos);
+				}
+				if($groupName==='')
+					$groupName=$uniqueID;
+			}
+			$this->_uniqueGroupName=$groupName;
+		}
+		return $this->_uniqueGroupName;
+	}
+
+	/**
+	 * Renders a radiobutton input element.
+	 * @param THtmlWriter the writer for the rendering purpose
+	 * @param string checkbox id
+	 * @param string onclick js
+	 */
+	protected function renderInputTag($writer,$clientID,$onclick)
+	{
+		if($clientID!=='')
+			$writer->addAttribute('id',$clientID);
+		$writer->addAttribute('type','radio');
+		$writer->addAttribute('name',$this->getUniqueGroupName());
+		$writer->addAttribute('value',$this->getValueAttribute());
+		if($onclick!=='')
+			$writer->addAttribute('onclick',$onclick);
+		if($this->getChecked())
+			$writer->addAttribute('checked','checked');
+		if(!$this->getEnabled(true))
+			$writer->addAttribute('disabled','disabled');
+
+		$page=$this->getPage();
+		if($this->getEnabled(true) && $this->getAutoPostBack() && $page->getClientSupportsJavaScript())
+			$this->renderClientControlScript($writer);
+
+		if(($accesskey=$this->getAccessKey())!=='')
+			$writer->addAttribute('accesskey',$accesskey);
+		if(($tabindex=$this->getTabIndex())>0)
+			$writer->addAttribute('tabindex',"$tabindex");
+		if($attributes=$this->getViewState('InputAttributes',null))
+			$writer->addAttributes($attributes);
+		$writer->renderBeginTag('input');
+		$writer->renderEndTag();
+	}
+
+	/**
+	 * Renders the client-script code.
+	 */
+	protected function renderClientControlScript($writer)
+	{
+		$cs = $this->getPage()->getClientScript();
+		$cs->registerPostBackControl($this->getClientClassName(),$this->getPostBackOptions());
+	}
+
+	/**
+	 * 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.TRadioButton';
+	}
+}
+
+?>
diff --git a/framework/Web/UI/WebControls/TRatingList.php b/framework/Web/UI/WebControls/TRatingList.php
index 6f382d31..05578136 100644
--- a/framework/Web/UI/WebControls/TRatingList.php
+++ b/framework/Web/UI/WebControls/TRatingList.php
@@ -204,6 +204,16 @@ class TRatingList extends TRadioButtonList
 	{
 		return new TStyle;
 	}
+
+	/**
+	 * 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.TRatingList';
+	}
 }
 
 ?>
\ No newline at end of file
diff --git a/framework/Web/UI/WebControls/TTextBox.php b/framework/Web/UI/WebControls/TTextBox.php
index 73b1e9cc..c13f20e7 100644
--- a/framework/Web/UI/WebControls/TTextBox.php
+++ b/framework/Web/UI/WebControls/TTextBox.php
@@ -154,7 +154,17 @@ class TTextBox extends TWebControl implements IPostBackDataHandler, IValidatable
 	{
 		$writer->addAttribute('id',$this->getClientID());
 		$cs = $this->getPage()->getClientScript();
-		$cs->registerPostBackControl('Prado.WebUI.TTextBox',$this->getPostBackOptions());
+		$cs->registerPostBackControl($this->getClientClassName(),$this->getPostBackOptions());
+	}
+
+	/**
+	 * 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.TTextBox';
 	}
 
 	/**
-- 
cgit v1.2.3