From f575382c8a572e39fcef13f90fc50a86529609d3 Mon Sep 17 00:00:00 2001 From: xue <> Date: Wed, 11 Jan 2006 02:18:11 +0000 Subject: --- framework/Web/UI/WebControls/TRepeater.php | 510 +++++++++++++++++++++++++++++ 1 file changed, 510 insertions(+) create mode 100644 framework/Web/UI/WebControls/TRepeater.php (limited to 'framework/Web') diff --git a/framework/Web/UI/WebControls/TRepeater.php b/framework/Web/UI/WebControls/TRepeater.php new file mode 100644 index 00000000..af82dfe9 --- /dev/null +++ b/framework/Web/UI/WebControls/TRepeater.php @@ -0,0 +1,510 @@ + + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Revision: $ $Date: $ + * @package System.Web.UI.WebControls + */ + +Prado::using('System.Web.UI.WebControls.TDataBoundControl'); + +/** + * TRepeater class + * + * TRepeater displays its content defined in templates repeatedly based on + * the DataSource property. The DataSource property only accepts + * objects that implement Iterator or IteratorAggregate interface. For convenience, + * it also accepts an array. + * + * The HeaderTemplate property specifies the content template + * that will be displayed at the beginning, while FooterTemplate at the last. + * If present, these two templates will only be rendered when DataSource is set (not null). + * If the DataSource contains item data, then for each item, + * the content defined by ItemTemplate will be generated and displayed once. + * If AlternatingItemTemplate is not empty, then the corresponding content will + * be displayed alternatively with that in ItemTemplate. The content in + * SeparatorTemplate, if not empty, will be displayed between two items. + * These templates can contain static text, controls and special tags. + * + * Note, the templates are only parsed and instantiated upon OnDataBinding + * event which is raised by calling TControl::dataBind() method. You may + * call this method during OnInit or OnLoad life cycles. + * + * You can retrive the repeated contents by Items. + * The number of repeated items is given by ItemCount. + * + * @author Qiang Xue + * @version $Revision: $ $Date: $ + * @package System.Web.UI.WebControls + * @since 3.0 + */ +class TRepeater extends TDataBoundControl implements INamingContainer +{ + const CACHE_EXPIRY=18000; + private $_itemTemplate=''; + private $_alternatingItemTemplate=''; + private $_headerTemplate=''; + private $_footerTemplate=''; + private $_separatorTemplate=''; + private $_emptyTemplate=''; + private $_items=null; + private $_header=null; + private $_footer=null; + private static $_templates=array(); + + /** + * @return string the template string for the item + */ + public function getItemTemplate() + { + return $this->_itemTemplate; + } + + /** + * Sets the template string for the item + * @param string the item template + */ + public function setItemTemplate($value) + { + $this->_itemTemplate=$value; + } + + /** + * @return string the template string when there are no items + */ + public function getEmptyTemplate() + { + return $this->_emptyTemplate; + } + + /** + * Sets the template string when there are no items + * @param string the empty template + */ + public function setEmptyTemplate($value) + { + $this->_emptyTemplate=$value; + } + /** + * @return string the alternative template string for the item + */ + public function getAlternatingItemTemplate() + { + return $this->_alternatingItemTemplate; + } + + /** + * Sets the alternative template string for the item + * @param string the alternative item template + */ + public function setAlternatingItemTemplate($value) + { + $this->_alternatingItemTemplate=$value; + } + + /** + * @return string the header template string + */ + public function getHeaderTemplate() + { + return $this->_headerTemplate; + } + + /** + * Sets the header template. + * The template will be parsed immediately. + * @param string the header template + */ + public function setHeaderTemplate($value) + { + $this->_headerTemplate=$value; + } + + /** + * @return string the footer template string + */ + public function getFooterTemplate() + { + return $this->_footerTemplate; + } + + /** + * Sets the footer template. + * The template will be parsed immediately. + * @param string the footer template + */ + public function setFooterTemplate($value) + { + $this->_footerTemplate=$value; + } + + /** + * @return string the separator template string + */ + public function getSeparatorTemplate() + { + return $this->_separatorTemplate; + } + + /** + * Sets the separator template string + * @param string the separator template + */ + public function setSeparatorTemplate($value) + { + $this->_separatorTemplate=$value; + } + + /** + * @return TRepeaterItem the header item + */ + public function getHeader() + { + return $this->_header; + } + + /** + * @return TRepeaterItem the footer item + */ + public function getFooter() + { + return $this->_footer; + } + + /** + * @return array list of TRepeaterItem control + */ + public function getItems() + { + if(!$this->_items) + $this->_items=new TList; + return $this->_items; + } + + protected function createItem($itemIndex,$itemType) + { + return new TRepeaterItem($itemIndex,$itemType); + } + + protected function initializeItem($item) + { + $tplContent=''; + switch($item->getItemType()) + { + case 'Header': $tplContent=$this->_headerTemplate; break; + case 'Footer': $tplContent=$this->_footerTemplate; break; + case 'Item': $tplContent=$this->_itemTemplate; break; + case 'Separator': $tplContent=$this->_separatorTemplate; break; + case 'AlternatingItem': $tplContent=$this->_alternatingItemTemplate==='' ? $this->_itemTemplate : $this->_alternatingItemTemplate; break; + case 'SelectedItem': + case 'EditItem': + default: + break; + } + if($tplContent!=='') + { + $key=md5($tplContent); + $contextPath=$this->getTemplateControl()->getTemplate()->getContextPath(); + if(($cache=$this->getApplication()->getCache())!==null) + { + if(($template=$cache->get($key))===null) + { + $template=new TTemplate($tplContent,$contextPath); + $cache->set($key,$template,self::CACHE_EXPIRY); + } + } + else + { + if(isset(self::$_templates[$key])) + $template=self::$_templates[$key]; + else + { + $template=new TTemplate($tplContent,$contextPath); + self::$_templates[$key]=$template; + } + } + $this->getControls()->add($item); + $template->instantiateIn($item); + } + } + + private function createItemInternal($itemIndex,$itemType,$dataBind,$dataItem) + { + $item=$this->createItem($itemIndex,$itemType); + $this->initializeItem($item); + $param=new TRepeaterItemEventParameter($item); + if($dataBind) + { + $item->setDataItem($dataItem); + $this->onItemCreated($param); + $item->dataBind(); + $this->onItemDataBound($param); + $item->setDataItem(null); + } + else + $this->onItemCreated($param); + return $item; + } + + protected function createChildControls() + { + $this->getControls()->clear(); + $items=$this->getItems(); + $items->clear(); + $this->_header=null; + $this->_footer=null; + if(($itemCount=$this->getViewState('ItemCount',null))!==null) + { + if($this->_headerTemplate!=='') + $this->_header=$this->createItemInternal(-1,'Header',false,null); + $hasSeparator=$this->_separatorTemplate!==''; + for($i=0;$i<$itemCount;++$i) + { + if($hasSeparator && $i>0) + $this->createItemInternal($i-1,'Separator',false,null); + $itemType=$i%2==0?'Item':'AlternatingItem'; + $items->add($this->createItemInternal($i,$itemType,false,null)); + } + if($this->_footerTemplate!=='') + $this->_footer=$this->createItemInternal(-1,'Footer',false,null); + } + $this->clearChildState(); + } + + /** + * Performs databinding to populate list items from data source. + * This method is invoked by dataBind(). + * You may override this function to provide your own way of data population. + * @param Traversable the data + */ + protected function performDataBinding($data) + { + $this->getControls()->clear(); + $this->clearChildState(); + $items=$this->getItems(); + $items->clear(); + $itemIndex=0; + if($data!==null) + { + if($this->_headerTemplate!=='') + $this->_header=$this->createItemInternal(-1,'Header',true,null); + $hasSeparator=$this->_separatorTemplate!==''; + foreach($data as $dataItem) + { + if($hasSeparator && $itemIndex>0) + $this->createItemInternal($itemIndex-1,'Separator',true,null); + $itemType=$itemIndex%2==0?'Item':'AlternatingItem'; + $items->add($this->createItemInternal($itemIndex,$itemType,true,$dataItem)); + $itemIndex++; + } + if($this->_footerTemplate!=='') + $this->_footer=$this->createItemInternal(-1,'Footer',true,null); + $this->setViewState('ItemCount',$itemIndex,0); + } + else + $this->setViewState('ItemCount',$itemIndex,-1); + $this->setChildControlsCreated(true); + } + + /** + * Raises OnItemCreated event. + * This method is invoked after a repeater item is created. + * You may override this method to provide customized event handling. + * Be sure to call parent's implementation so that + * event handlers have chance to respond to the event. + * The TRepeaterItem control responsible for the event + * can be determined from the event parameter's item + * field. + * @param TRepeaterItemEventParameter event parameter + */ + protected function onItemCreated($param) + { + $this->raiseEvent('ItemCreated',$this,$param); + } + + /** + * Handles OnBubbleEvent. + * This method overrides parent's implementation to handle + * OnItemCommand event that is bubbled from + * TRepeaterItem child controls. + * This method should only be used by control developers. + * @param TControl the sender of the event + * @param TEventParameter event parameter + * @return boolean whether the event bubbling should stop here. + */ + protected function onBubbleEvent($sender,$param) + { + if($param instanceof TRepeaterCommandEventParameter) + { + $this->onItemCommand($param); + return true; + } + else + return false; + } + + /** + * Raises OnItemCommand event. + * This method is invoked after a button control in + * a template raises OnCommand event. + * You may override this method to provide customized event handling. + * Be sure to call parent's implementation so that + * event handlers have chance to respond to the event. + * The TRepeaterItem control responsible for the event + * can be determined from the event parameter's item + * field. The initial sender of the OnCommand event + * is in source field. The command name and parameter + * are in name and parameter fields, respectively. + * @param TRepeaterCommandEventParameter event parameter + */ + protected function onItemCommand($param) + { + $this->raiseEvent('ItemCommand',$this,$param); + } + + protected function onItemDataBound($param) + { + $this->raiseEvent('ItemDataBound',$this,$param); + } +} + +/** + * TRepeaterItemEventParameter class + * + * TRepeaterItemEventParameter encapsulates the parameter data for OnItemCreated + * event of TRepeater controls. + * + * @author Qiang Xue + * @version v1.0, last update on 2004/08/13 21:44:52 + * @package System.Web.UI.WebControls + */ +class TRepeaterItemEventParameter extends TEventParameter +{ + /** + * The TRepeaterItem control responsible for the event. + * @var TRepeaterItem + */ + public $_item=null; + + public function __construct(TRepeaterItem $item) + { + $this->_item=$item; + } + + public function getItem() + { + return $this->_item; + } +} + +/** + * TRepeaterCommandEventParameter class + * + * TRepeaterCommandEventParameter encapsulates the parameter data for OnItemCommand + * event of TRepeater controls. + * + * @author Qiang Xue + * @version v1.0, last update on 2004/08/13 21:44:52 + * @package System.Web.UI.WebControls + */ +class TRepeaterCommandEventParameter extends TCommandEventParameter +{ + /** + * The TRepeaterItem control responsible for the event. + * @var TRepeaterItem + */ + public $_item=null; + /** + * The control originally raises the Command event. + * @var TControl + */ + public $_source=null; + + public function __construct($item,$source,TCommandEventParameter $param) + { + $this->_item=$item; + $this->_source=$source; + parent::__construct($param->getCommandName(),$param->getCommandParameter()); + } + + public function getItem() + { + return $this->_item; + } + + public function getCommandSource() + { + return $this->_source; + } +} + +class TRepeaterItem extends TControl implements INamingContainer +{ + /** + * index of the data item in the Items collection of repeater + */ + private $_itemIndex=''; + /** + * type of the TRepeaterItem + * @var string + */ + private $_itemType=''; + /** + * value of the data item + * @var mixed + */ + private $_dataItem=null; + + public function __construct($itemIndex,$itemType) + { + $this->_itemIndex=$itemIndex; + $this->_itemType=TPropertyValue::ensureEnum($itemType,'Header','Footer','Item','AlternatingItem','SelectedItem','EditItem','Separator','Pager'); + } + + public function getItemType() + { + return $this->_itemType; + } + + public function getItemIndex() + { + return $this->_itemIndex; + } + + public function getDataItem() + { + return $this->_dataItem; + } + + public function setDataItem($value) + { + $this->_dataItem=$value; + } + + /** + * Handles OnBubbleEvent. + * This method overrides parent's implementation to bubble + * OnItemCommand event if an OnCommand + * event is bubbled from a child control. + * This method should only be used by control developers. + * @param TControl the sender of the event + * @param TEventParameter event parameter + * @return boolean whether the event bubbling should stop here. + */ + protected function onBubbleEvent($sender,$param) + { + if($param instanceof TCommandEventParameter) + { + $this->raiseBubbleEvent($this,new TRepeaterCommandEventParameter($this,$sender,$param)); + return true; + } + else + return false; + } +} + +?> \ No newline at end of file -- cgit v1.2.3