summaryrefslogtreecommitdiff
path: root/framework/Web/UI
diff options
context:
space:
mode:
Diffstat (limited to 'framework/Web/UI')
-rw-r--r--framework/Web/UI/WebControls/TBaseDataList.php9
-rw-r--r--framework/Web/UI/WebControls/TButton.php84
-rw-r--r--framework/Web/UI/WebControls/TDataGrid.php88
-rw-r--r--framework/Web/UI/WebControls/TDataList.php40
-rw-r--r--framework/Web/UI/WebControls/THyperLink.php2
-rw-r--r--framework/Web/UI/WebControls/TRepeater.php34
6 files changed, 184 insertions, 73 deletions
diff --git a/framework/Web/UI/WebControls/TBaseDataList.php b/framework/Web/UI/WebControls/TBaseDataList.php
index 479fb2ef..a8ab8faf 100644
--- a/framework/Web/UI/WebControls/TBaseDataList.php
+++ b/framework/Web/UI/WebControls/TBaseDataList.php
@@ -44,15 +44,6 @@ Prado::using('System.Util.TDataFieldAccessor');
abstract class TBaseDataList extends TDataBoundControl
{
/**
- * No body content should be added to data list control.
- * This method is invoked when body content is parsed and added to this control.
- * @param mixed body content to be added
- */
- public function addParsedObject($object)
- {
- }
-
- /**
* Creates a style object for the control.
* This method creates a {@link TTableStyle} to be used by the data list control.
* @return TTableStyle control style to be used
diff --git a/framework/Web/UI/WebControls/TButton.php b/framework/Web/UI/WebControls/TButton.php
index b77ca111..f1132625 100644
--- a/framework/Web/UI/WebControls/TButton.php
+++ b/framework/Web/UI/WebControls/TButton.php
@@ -13,37 +13,35 @@
/**
* 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.
+ * TButton creates a click button on the page. It is mainly used to submit data to a page.
*
- * 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
+ * TButton raises two server-side events, {@link onClick OnClick} and {@link onCommand OnCommand},
+ * when it is clicked on the client-side. The difference between these two events
+ * is that the event {@link onCommand OnCommand} is bubbled up to the button's ancestor controls.
+ * And within the event parameter for {@link onCommand OnCommand} contains the reference
+ * to the {@link setCommandName CommandName} and {@link setCommandParameter CommandParameter}
+ * property values that are set for the button object. 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}.
+ * with what parameter.
*
- * 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
+ * Clicking on button can also trigger form validation, if
* {@link setCausesValidation CausesValidation} is true.
- * And the validation may be restricted within a certain group of validator
+ * 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.
*
+ * TButton can be one of three {@link setButtonType ButtonType}: Submit, Button and Reset.
+ * By default, it is a Submit button and the form submission uses the browser's
+ * default submission capability. If it is Button or Reset, postback may occur
+ * if one of the following conditions is met:
+ * - an event handler is attached to {@link onClick OnClick} event;
+ * - an event handler is attached to {@link onCommand OnCommand} event;
+ * - the button is in a non-empty validation group.
+ * In addition, clicking on a Reset button will clear up all input fields
+ * if the button does not cause a postback.
+ *
* @author Qiang Xue <qiang.xue@gmail.com>
* @version $Revision: $ $Date: $
* @package System.Web.UI.WebControls
@@ -68,12 +66,15 @@ class TButton extends TWebControl implements IPostBackEventHandler, IButtonContr
{
$page=$this->getPage();
$page->ensureRenderInForm($this);
- $writer->addAttribute('type','submit');
+ $writer->addAttribute('type',strtolower($this->getButtonType()));
if(($uniqueID=$this->getUniqueID())!=='')
$writer->addAttribute('name',$uniqueID);
$writer->addAttribute('value',$this->getText());
- if($this->getEnabled(true) )
- $this->renderClientControlScript($writer);
+ if($this->getEnabled(true))
+ {
+ if($this->needPostBackScript())
+ $this->renderClientControlScript($writer);
+ }
else if($this->getEnabled()) // in this case, parent will not render 'disabled'
$writer->addAttribute('disabled','disabled');
@@ -85,12 +86,8 @@ class TButton extends TWebControl implements IPostBackEventHandler, IButtonContr
*/
protected function renderClientControlScript($writer)
{
- if($this->canCauseValidation())
- {
- $writer->addAttribute('id',$this->getClientID());
- $cs = $this->getPage()->getClientScript();
- $cs->registerPostBackControl($this->getClientClassName(),$this->getPostBackOptions());
- }
+ $writer->addAttribute('id',$this->getClientID());
+ $this->getPage()->getClientScript()->registerPostBackControl($this->getClientClassName(),$this->getPostBackOptions());
}
/**
@@ -118,6 +115,15 @@ class TButton extends TWebControl implements IPostBackEventHandler, IButtonContr
}
/**
+ * @return boolean whether the button needs javascript to do postback
+ */
+ protected function needPostBackScript()
+ {
+ return $this->canCauseValidation() || ($this->getButtonType()!=='Submit' &&
+ ($this->hasEventHandler('OnClick') || $this->hasEventHandler('OnCommand')));
+ }
+
+ /**
* 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.
@@ -262,6 +268,22 @@ class TButton extends TWebControl implements IPostBackEventHandler, IButtonContr
{
$this->setViewState('ValidationGroup',$value,'');
}
+
+ /**
+ * @return string the type of the button. Defaults to 'Submit'.
+ */
+ public function getButtonType()
+ {
+ return $this->getViewState('ButtonType','Submit');
+ }
+
+ /**
+ * @param string the type of the button. Valid values include 'Submit', 'Reset', 'Button'.
+ */
+ public function setButtonType($value)
+ {
+ $this->setViewState('ButtonType',TPropertyValue::ensureEnum($value,'Submit','Reset','Button'),'Submit');
+ }
}
?>
diff --git a/framework/Web/UI/WebControls/TDataGrid.php b/framework/Web/UI/WebControls/TDataGrid.php
index 69798c1a..dae2d2cd 100644
--- a/framework/Web/UI/WebControls/TDataGrid.php
+++ b/framework/Web/UI/WebControls/TDataGrid.php
@@ -186,6 +186,14 @@ class TDataGrid extends TBaseDataList implements INamingContainer
private $_pagedDataSource=null;
private $_topPager=null;
private $_bottomPager=null;
+ /**
+ * @var ITemplate template used when empty data is bounded
+ */
+ private $_emptyTemplate=null;
+ /**
+ * @var boolean whether empty template is effective
+ */
+ private $_useEmptyTemplate=false;
/**
* @return string tag name (table) of the datagrid
@@ -197,13 +205,15 @@ class TDataGrid extends TBaseDataList implements INamingContainer
/**
* Adds objects parsed in template to datagrid.
- * Only datagrid columns are added into {@link getColumns Columns} collection.
+ * Datagrid columns are added into {@link getColumns Columns} collection.
* @param mixed object parsed in template
*/
public function addParsedObject($object)
{
if($object instanceof TDataGridColumn)
$this->getColumns()->add($object);
+ else
+ parent::addParsedObject($object);
}
/**
@@ -683,6 +693,26 @@ class TDataGrid extends TBaseDataList implements INamingContainer
}
/**
+ * @return ITemplate the template applied when no data is bound to the datagrid
+ */
+ public function getEmptyTemplate()
+ {
+ return $this->_emptyTemplate;
+ }
+
+ /**
+ * @param ITemplate the template applied when no data is bound to the datagrid
+ * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
+ */
+ public function setEmptyTemplate($value)
+ {
+ if($value instanceof ITemplate || $value===null)
+ $this->_emptyTemplate=$value;
+ else
+ throw new TInvalidDataTypeException('datagrid_template_required','EmptyTemplate');
+ }
+
+ /**
* This method overrides parent's implementation to handle
* {@link onItemCommand OnItemCommand} event which is bubbled from
* {@link TDataGridItem} child controls.
@@ -953,6 +983,7 @@ class TDataGrid extends TBaseDataList implements INamingContainer
$this->_footer=null;
$this->_topPager=null;
$this->_bottomPager=null;
+ $this->_useEmptyTemplate=false;
}
/**
@@ -968,6 +999,17 @@ class TDataGrid extends TBaseDataList implements INamingContainer
$ds->setDataSource(new TDummyDataSource($itemCount));
else
$ds->setDataSource(new TDummyDataSource($this->getViewState('DataSourceCount',0)));
+
+ if($ds->getCount()===0 && $ds->getCurrentPageIndex()===0 && $this->_emptyTemplate!==null)
+ {
+ $this->_emptyTemplate->instantiateIn($this);
+ $this->_useEmptyTemplate=true;
+ $this->clearViewState('ItemCount');
+ $this->clearViewState('PageCount');
+ $this->clearViewState('DataSourceCount');
+ return;
+ }
+
$columns=new TList($this->getColumns());
$columns->mergeWith($this->_autoColumns);
@@ -1020,9 +1062,21 @@ class TDataGrid extends TBaseDataList implements INamingContainer
$keyField=$this->getDataKeyField();
$this->_pagedDataSource=$ds=$this->createPagedDataSource();
$ds->setDataSource($data);
+
$allowPaging=$ds->getAllowPaging();
if($allowPaging && $ds->getCurrentPageIndex()>=$ds->getPageCount())
throw new TInvalidDataValueException('datagrid_currentpageindex_invalid');
+
+ if($ds->getCount()===0 && $ds->getCurrentPageIndex()===0 && $this->_emptyTemplate!==null)
+ {
+ $this->_emptyTemplate->instantiateIn($this);
+ $this->_useEmptyTemplate=true;
+ $this->clearViewState('ItemCount');
+ $this->clearViewState('PageCount');
+ $this->clearViewState('DataSourceCount');
+ return;
+ }
+
// get all columns
if($this->getAutoGenerateColumns())
{
@@ -1046,7 +1100,7 @@ class TDataGrid extends TBaseDataList implements INamingContainer
$selectedIndex=$this->getSelectedItemIndex();
$editIndex=$this->getEditItemIndex();
$index=0;
- $dsIndex=$ds->getAllowPaging()?$ds->getFirstIndexInPage():0;
+ $dsIndex=$allowPaging?$ds->getFirstIndexInPage():0;
foreach($ds as $key=>$data)
{
if($keyField!=='')
@@ -1502,17 +1556,31 @@ class TDataGrid extends TBaseDataList implements INamingContainer
{
if($this->getHasControls())
{
- $this->applyItemStyles();
- if($this->_topPager)
+ if($this->_useEmptyTemplate)
{
- $this->_topPager->renderControl($writer);
- $writer->writeLine();
+ $control=new TWebControl;
+ $control->setID($this->getClientID());
+ $control->copyBaseAttributes($this);
+ if($this->getHasStyle())
+ $control->getStyle()->copyFrom($this->getStyle());
+ $control->renderBeginTag($writer);
+ $this->renderContents($writer);
+ $control->renderEndTag($writer);
}
- $this->renderTable($writer);
- if($this->_bottomPager)
+ else
{
- $writer->writeLine();
- $this->_bottomPager->renderControl($writer);
+ $this->applyItemStyles();
+ if($this->_topPager)
+ {
+ $this->_topPager->renderControl($writer);
+ $writer->writeLine();
+ }
+ $this->renderTable($writer);
+ if($this->_bottomPager)
+ {
+ $writer->writeLine();
+ $this->_bottomPager->renderControl($writer);
+ }
}
}
}
diff --git a/framework/Web/UI/WebControls/TDataList.php b/framework/Web/UI/WebControls/TDataList.php
index b2bd9229..0dac2be2 100644
--- a/framework/Web/UI/WebControls/TDataList.php
+++ b/framework/Web/UI/WebControls/TDataList.php
@@ -115,6 +115,7 @@ class TDataList extends TBaseDataList implements INamingContainer, IRepeatInfoUs
* @var Itemplate various item templates
*/
private $_itemTemplate=null;
+ private $_emptyTemplate=null;
private $_alternatingItemTemplate=null;
private $_selectedItemTemplate=null;
private $_editItemTemplate=null;
@@ -363,6 +364,26 @@ class TDataList extends TBaseDataList implements INamingContainer, IRepeatInfoUs
}
/**
+ * @return ITemplate the template applied when no data is bound to the datalist
+ */
+ public function getEmptyTemplate()
+ {
+ return $this->_emptyTemplate;
+ }
+
+ /**
+ * @param ITemplate the template applied when no data is bound to the datalist
+ * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
+ */
+ public function setEmptyTemplate($value)
+ {
+ if($value instanceof ITemplate || $value===null)
+ $this->_emptyTemplate=$value;
+ else
+ throw new TInvalidDataTypeException('datalist_template_required','EmptyTemplate');
+ }
+
+ /**
* @return ITemplate the separator template
*/
public function getSeparatorTemplate()
@@ -1109,6 +1130,8 @@ class TDataList extends TBaseDataList implements INamingContainer, IRepeatInfoUs
if($this->_footerTemplate!==null)
$this->_footer=$this->createItemInternal(-1,'Footer',false,null);
}
+ else if($this->_emptyTemplate!==null)
+ $this->_emptyTemplate->instantiateIn($this);
$this->clearChildState();
}
@@ -1150,6 +1173,8 @@ class TDataList extends TBaseDataList implements INamingContainer, IRepeatInfoUs
}
if($itemIndex>0 && $this->_footerTemplate!==null)
$this->_footer=$this->createItemInternal(-1,'Footer',true,null);
+ if($itemIndex===0 && $this->_emptyTemplate!==null)
+ $this->_emptyTemplate->instantiateIn($this);
$this->setViewState('ItemCount',$itemIndex,0);
}
@@ -1162,9 +1187,14 @@ class TDataList extends TBaseDataList implements INamingContainer, IRepeatInfoUs
{
if($this->getHasControls())
{
- $this->applyItemStyles();
- $repeatInfo=$this->getRepeatInfo();
- $repeatInfo->renderRepeater($writer,$this);
+ if($this->getItemCount()>0)
+ {
+ $this->applyItemStyles();
+ $repeatInfo=$this->getRepeatInfo();
+ $repeatInfo->renderRepeater($writer,$this);
+ }
+ else if($this->_emptyTemplate!==null)
+ parent::render($writer);
}
}
}
@@ -1317,7 +1347,7 @@ class TDataListItem extends TWebControl implements INamingContainer
}
/**
- * @return string item type, can be 'Header','Footer','Item','AlternatingItem','SelectedItem','EditItem','Separator','Pager'
+ * @return string item type
*/
public function getItemType()
{
@@ -1325,7 +1355,7 @@ class TDataListItem extends TWebControl implements INamingContainer
}
/**
- * @param mixed data to be associated with the item
+ * @param string item type. Valid values include 'Header','Footer','Item','AlternatingItem','SelectedItem','EditItem','Separator','Pager'.
*/
public function setItemType($value)
{
diff --git a/framework/Web/UI/WebControls/THyperLink.php b/framework/Web/UI/WebControls/THyperLink.php
index 5489727c..011ce4db 100644
--- a/framework/Web/UI/WebControls/THyperLink.php
+++ b/framework/Web/UI/WebControls/THyperLink.php
@@ -73,7 +73,7 @@ class THyperLink extends TWebControl
if(($toolTip=$this->getToolTip())!=='')
$image->setToolTip($toolTip);
if(($text=$this->getText())!=='')
- $image->setAlternateText(THttpUtility::htmlEncode($text));
+ $image->setAlternateText($text);
$image->renderControl($writer);
}
}
diff --git a/framework/Web/UI/WebControls/TRepeater.php b/framework/Web/UI/WebControls/TRepeater.php
index 9c1cc4ac..a2fc01d7 100644
--- a/framework/Web/UI/WebControls/TRepeater.php
+++ b/framework/Web/UI/WebControls/TRepeater.php
@@ -62,7 +62,6 @@ class TRepeater extends TDataBoundControl implements INamingContainer
*/
const IT_HEADER='Header';
const IT_FOOTER='Footer';
- const IT_EMPTY='Empty';
const IT_ITEM='Item';
const IT_SEPARATOR='Separator';
const IT_ALTERNATINGITEM='AlternatingItem';
@@ -105,15 +104,6 @@ class TRepeater extends TDataBoundControl implements INamingContainer
private $_footer=null;
/**
- * No body content should be added to repeater.
- * This method is invoked when body content is parsed and added to this control.
- * @param mixed body content to be added
- */
- public function addParsedObject($object)
- {
- }
-
- /**
* @return ITemplate the template for repeater items
*/
public function getItemTemplate()
@@ -343,7 +333,6 @@ class TRepeater extends TDataBoundControl implements INamingContainer
{
case self::IT_HEADER: $template=$this->_headerTemplate; break;
case self::IT_FOOTER: $template=$this->_footerTemplate; break;
- case self::IT_EMPTY : $template=$this->_emptyTemplate; break;
case self::IT_ITEM : $template=$this->_itemTemplate; break;
case self::IT_SEPARATOR : $template=$this->_separatorTemplate; break;
case self::IT_ALTERNATINGITEM : $template=$this->_alternatingItemTemplate===null ? $this->_itemTemplate : $this->_alternatingItemTemplate; break;
@@ -360,7 +349,10 @@ class TRepeater extends TDataBoundControl implements INamingContainer
*/
public function render($writer)
{
- $this->renderContents($writer);
+ if($this->_items && $this->_items->getCount())
+ $this->renderContents($writer);
+ else if($this->_emptyTemplate!==null)
+ parent::render($writer);
}
/**
@@ -422,7 +414,7 @@ class TRepeater extends TDataBoundControl implements INamingContainer
$this->_footer=$this->createItemInternal(-1,self::IT_FOOTER,false,null);
}
else if($this->_emptyTemplate!==null)
- $this->createItemInternal(-1,self::IT_EMPTY,false,null);
+ $this->_emptyTemplate->instantiateIn($this);
$this->clearChildState();
}
@@ -460,7 +452,7 @@ class TRepeater extends TDataBoundControl implements INamingContainer
if($itemIndex>0 && $this->_footerTemplate!==null)
$this->_footer=$this->createItemInternal(-1,self::IT_FOOTER,true,null);
if($itemIndex===0 && $this->_emptyTemplate!==null)
- $this->createItemInternal(-1,self::IT_EMPTY,true,null);
+ $this->_emptyTemplate->instantiateIn($this);
$this->setViewState('ItemCount',$itemIndex,0);
}
@@ -677,16 +669,16 @@ class TRepeaterItem extends TControl implements INamingContainer
/**
* Constructor.
* @param integer zero-based index of the item in the item collection of repeater
- * @param string item type, can be 'Header','Footer','Empty','Item','AlternatingItem','SelectedItem','EditItem','Separator','Pager'.
+ * @param string item type, can be 'Header','Footer','Item','AlternatingItem','SelectedItem','EditItem','Separator','Pager'.
*/
public function __construct($itemIndex,$itemType)
{
$this->_itemIndex=$itemIndex;
- $this->_itemType=$itemType;
+ $this->setItemType($itemType);
}
/**
- * @return string item type, can be 'Header','Footer','Empty','Item','AlternatingItem','SelectedItem','EditItem','Separator','Pager'
+ * @return string item type
*/
public function getItemType()
{
@@ -694,6 +686,14 @@ class TRepeaterItem extends TControl implements INamingContainer
}
/**
+ * @param string item type. Valid values include 'Header','Footer','Item','AlternatingItem','SelectedItem','EditItem','Separator','Pager'.
+ */
+ public function setItemType($value)
+ {
+ $this->_itemType=TPropertyValue::ensureEnum($value,'Header','Footer','Item','AlternatingItem','SelectedItem','EditItem','Separator','Pager');
+ }
+
+ /**
* @return integer zero-based index of the item in the item collection of repeater
*/
public function getItemIndex()