diff options
8 files changed, 456 insertions, 1 deletions
diff --git a/.gitattributes b/.gitattributes index c219cf49..cd8a69d4 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1225,6 +1225,7 @@ demos/quickstart/protected/pages/ActiveControls/ActiveButton.page -text demos/quickstart/protected/pages/ActiveControls/ActiveCheckBox.page -text demos/quickstart/protected/pages/ActiveControls/ActiveCustomValidator.page -text demos/quickstart/protected/pages/ActiveControls/ActiveHyperLink.page -text +demos/quickstart/protected/pages/ActiveControls/ActivePager.page -text demos/quickstart/protected/pages/ActiveControls/Home.page -text demos/quickstart/protected/pages/ActiveControls/Introduction.page -text demos/quickstart/protected/pages/ActiveControls/Samples/TActiveButton/Home.page -text @@ -1236,6 +1237,7 @@ demos/quickstart/protected/pages/ActiveControls/Samples/TActiveCustomValidator/H demos/quickstart/protected/pages/ActiveControls/Samples/TActiveHyperLink/Home.page -text demos/quickstart/protected/pages/ActiveControls/Samples/TActiveHyperLink/Home.php -text demos/quickstart/protected/pages/ActiveControls/Samples/TActiveHyperLink/hello_world.gif -text +demos/quickstart/protected/pages/ActiveControls/Samples/TActivePager/Home.page -text demos/quickstart/protected/pages/ActiveControls/Samples/config.xml -text demos/quickstart/protected/pages/ActiveControls/TActiveButtonClass.png -text demos/quickstart/protected/pages/ActiveControls/TActiveButtonClass.vsd -text @@ -2535,6 +2537,7 @@ framework/Web/UI/ActiveControls/TActiveCustomValidator.php -text framework/Web/UI/ActiveControls/TActiveHiddenField.php -text framework/Web/UI/ActiveControls/TActiveLabel.php -text framework/Web/UI/ActiveControls/TActivePageAdapter.php -text +framework/Web/UI/ActiveControls/TActivePager.php -text framework/Web/UI/ActiveControls/TActivePanel.php -text framework/Web/UI/ActiveControls/TActiveRatingList.php -text framework/Web/UI/ActiveControls/TActiveTextBox.php -text @@ -26,6 +26,7 @@ ENH: Added TAuthManager.switchUser() (Qiang) NEW: Added TDbLogRoute (Qiang) NEW: Added TDataRenderer and TItemDataRenderer (Qiang) NEW: Ticket#544 - Added TXCache (Wei) +NEW: Ticket#729 - Added TActivePager (Christophe) Version 3.1.1 October 1, 2007 ============================= diff --git a/demos/quickstart/protected/pages/ActiveControls/ActivePager.page b/demos/quickstart/protected/pages/ActiveControls/ActivePager.page new file mode 100755 index 00000000..4589f381 --- /dev/null +++ b/demos/quickstart/protected/pages/ActiveControls/ActivePager.page @@ -0,0 +1,41 @@ +<com:TContent ID="body" >
+
+<h1 id="3901">TActivePager</h1>
+<com:DocLink ClassPath="System.Web.UI.WebControls.TPager" />
+
+<p id="450300" class="block-content">
+<tt>TActivePager</tt> creates a pager that provides UI for end-users to interactively specify which page of data to be rendered in a <tt>TDataBoundControl</tt>-derived control, such as <tt>TDataList</tt>, <tt>TRepeater</tt>, <tt>TCheckBoxList</tt>, etc. +The target data-bound control is specified by the <tt>ControlToPaginate</tt> property, which must be the ID path of the target control reaching from the pager's naming container. The target-databound must be enclosed inside a <tt>TActivePanel</tt> in order +to be re-rendered during callback
+</p>
+
+<p id="450301" class="block-content">
+Note, the target data-bound control must have its <tt>AllowPaging</tt> set to true. Otherwise the pager will be invisible. Also, in case when there is only one page of data available, the pager will also be invisible.
+</p>
+
+<p id="450302" class="block-content">
+<tt>TActivePager</tt> can display one of the following three types of user interface, specified via its <tt>Mode</tt> property:
+</p>
+<ul id="u1" class="block-content">
+<li><tt>NextPrev</tt> - a next page and a previous page button are rendered on each page.</li>
+<li><tt>Numeric</tt> - a list of page index buttons are rendered.</li>
+<li><tt>DropDownList</tt> - a dropdown list of page indices is rendered.</li>
+</ul>
+<p id="450303" class="block-content">
+These user interfaces may be further customized by configuring the following properties
+</p>
+<ul id="u2" class="block-content">
+<li><tt>NextPageText</tt> and <tt>PrevPageText</tt> - the label of the next/previous page button. These properties are used when the pager <tt>Mode</tt> is <tt>NextPrev</tt> or <tt>Numeric</tt>.</li>
+<li><tt>FirstPageText</tt> and <tt>LastPageText</tt> - the label of the first/last page button. If empty, the corresponding button will not be displayed. These properties are used when the pager <tt>Mode</tt> is <tt>NextPrev</tt> or <tt>Numeric</tt>.</li>
+<li><tt>PageButtonCount</tt> - the maximum number of page index buttons on a page. This property is used when the pager <tt>Mode</tt> is <tt>Numeric</tt>.</li>
+<li><tt>ButtonType</tt> - type of page buttons, either <tt>PushButton</tt> meaning normal form submission buttons, or <tt>LinkButton</tt> meaning hyperlink buttons.</li>
+</ul>
+
+<p id="450304" class="block-content">
+<tt>TActivePager</tt> raises an <tt>OnPageIndexChanged</tt> event when an end-user interacts with it and specifies a new page (e.g. by clicking on a next page button that would lead to the next page.) Developers may write handlers to respond to this event and obtain the desired new page index from the event parameter's property <tt>NewPageIndex</tt>. Using this new page index, one can feed a new page of data to the associated data-bound control. +Additionnaly, <tt>TActivePager</tt> raises <tt>OnCallback</tt> after the <tt>OnPageIndexChanged</tt>.
+</p>
+
+<com:RunBar PagePath="ActiveControls.Samples.TActivePager.Home" />
+
+<div class="last-modified">$Id: Pager.page 1650 2007-01-24 06:55:32Z wei $</div></com:TContent>
\ No newline at end of file diff --git a/demos/quickstart/protected/pages/ActiveControls/Home.page b/demos/quickstart/protected/pages/ActiveControls/Home.page index a7a0076a..4d0191e0 100644 --- a/demos/quickstart/protected/pages/ActiveControls/Home.page +++ b/demos/quickstart/protected/pages/ActiveControls/Home.page @@ -70,7 +70,13 @@ TActiveButton</a> control. See also the later part of the <a href="?page=Tutoria it is displayed as a <div> element. The panel's contents
can be replaced during a callback request.
</li>
-
+ + <li> + <a href="?page=ActiveControls.ActivePager">TActivePager</a> + generates UI that allows users to interactively specify which page of + data to be displayed in a data-bound control. + </li> +
<li>
* <a href="?page=ActiveControls.ActiveRadioButton">TActiveRadioButton</a>
represents a radiobutton on a Web page.
diff --git a/demos/quickstart/protected/pages/ActiveControls/Samples/TActivePager/Home.page b/demos/quickstart/protected/pages/ActiveControls/Samples/TActivePager/Home.page new file mode 100644 index 00000000..3153088d --- /dev/null +++ b/demos/quickstart/protected/pages/ActiveControls/Samples/TActivePager/Home.page @@ -0,0 +1,103 @@ +<com:TContent ID="body">
+
+<h1>TActivePager Sample</h1>
+<p>
+The following sample displays three different pagers associated with a single TDataList control. The datalist control is enabled with custom paging, which allows it to read only one page of data each time. This is typical in DB-driven applications.
+</p>
+
+<div>
+Go to page:
+<com:TActivePager ID="Pager"
+ ControlToPaginate="DataList"
+ PageButtonCount="3"
+ Mode="Numeric"
+ OnPageIndexChanged="pageChanged"
+ OnCallBack="RenderCallback"
+ >
+ <prop:ClientSide.OnLoading>
+ Element.show('wait')
+ </prop:ClientSide.OnLoading> + <prop:ClientSide.OnComplete> + Element.hide('wait') + </prop:ClientSide.OnComplete>
+</com:TActivePager> +<span id="wait" style="display: none;color: red">Please Wait...</span>
+</div>
+<com:TActivePanel id="TActivePanel" ActiveControl.EnableUpdate="true">
+<com:TDataList
+ ID="DataList"
+ AllowPaging="true"
+ AllowCustomPaging="true"
+ PageSize="2"
+ EnableViewState="true"
+ RepeatColumns="2"
+ RepeatDirection="Vertical"
+ ItemStyle.Font.Italic="true"
+ ItemStyle.BackColor="#BFCFFF"
+ HeaderStyle.BackColor="black"
+ HeaderStyle.ForeColor="white"
+ FooterStyle.BackColor="gray"
+ AlternatingItemStyle.BackColor="#E6ECFF">
+
+<prop:HeaderTemplate>
+<div style="font-weight:bold; text-align:center;">Computer Parts</div>
+</prop:HeaderTemplate>
+
+<prop:FooterTemplate>
+<div style="font-weight:bold; text-align:center;">
+Total <%# $this->Parent->PageCount %> pages.
+</div>
+</prop:FooterTemplate>
+
+<prop:ItemTemplate>
+<table border="0" width="300">
+<tr>
+ <th>ID</th><th>Name</th><th>Quantity</th><th>Price</th>
+</tr>
+<tr>
+ <td align="right"><com:TLiteral Text=<%#$this->DataItem['id'] %> /></td>
+ <td align="right"><com:TLiteral Text=<%#$this->DataItem['name'] %> /></td>
+ <td align="right"><com:TLiteral Text=<%#$this->DataItem['quantity'] %> /></td>
+ <td align="right">$<com:TLiteral Text=<%#$this->DataItem['price'] %> /></td>
+</tr>
+</table>
+</prop:ItemTemplate>
+
+</com:TDataList>
+</com:TActivePanel> +
+<com:TActivePager ID="Pager2"
+ ControlToPaginate="DataList"
+ FirstPageText="9"
+ LastPageText=":"
+ Mode="NextPrev"
+ NextPageText="4"
+ PrevPageText="3"
+ Font.Name="Webdings"
+ OnPageIndexChanged="pageChanged"
+ OnCallBack="RenderCallback"
+> +<prop:ClientSide.OnLoading> + Element.show('wait') + </prop:ClientSide.OnLoading> + <prop:ClientSide.OnComplete> + Element.hide('wait') + </prop:ClientSide.OnComplete> +</com:TActivePager>
+<br/>
+Choose page:
+<com:TActivePager ID="Pager3"
+ ControlToPaginate="DataList"
+ Mode="DropDownList"
+ OnPageIndexChanged="pageChanged"
+ OnCallBack="RenderCallback"
+> +<prop:ClientSide.OnLoading> + Element.show('wait') + </prop:ClientSide.OnLoading> + <prop:ClientSide.OnComplete> + Element.hide('wait') + </prop:ClientSide.OnComplete>
+</com:TActivePager>
+<com:TJavascriptLogger/>
+<div class="last-modified">$Id$</div></com:TContent>
diff --git a/demos/quickstart/protected/pages/ActiveControls/Samples/TActivePager/Home.php b/demos/quickstart/protected/pages/ActiveControls/Samples/TActivePager/Home.php new file mode 100644 index 00000000..40a867b5 --- /dev/null +++ b/demos/quickstart/protected/pages/ActiveControls/Samples/TActivePager/Home.php @@ -0,0 +1,92 @@ +<?php + +class Home extends TPage +{ + + /** + * function to render callback and refresh the TActivePanel content + */ + + public function RenderCallback($sender, $param) + { + $this->TActivePanel->render($param->NewWriter); + } + + /** + * Returns total number of data items. + * In DB-driven applications, this typically requires + * execution of an SQL statement with COUNT function. + * Here we simply return a constant number. + */ + protected function getDataItemCount() + { + return 19; + } + + /** + * Fetches a page of data. + * In DB-driven applications, this can be achieved by executing + * an SQL query with LIMIT clause. + */ + protected function getData($offset,$limit) + { + $data=array( + array('id'=>'ITN001','name'=>'Motherboard','quantity'=>1,'price'=>100.00,'imported'=>true), + array('id'=>'ITN002','name'=>'CPU','quantity'=>1,'price'=>150.00,'imported'=>true), + array('id'=>'ITN003','name'=>'Harddrive','quantity'=>2,'price'=>80.00,'imported'=>true), + array('id'=>'ITN004','name'=>'Sound card','quantity'=>1,'price'=>40.00,'imported'=>false), + array('id'=>'ITN005','name'=>'Video card','quantity'=>1,'price'=>150.00,'imported'=>true), + array('id'=>'ITN006','name'=>'Keyboard','quantity'=>1,'price'=>20.00,'imported'=>false), + array('id'=>'ITN007','name'=>'Monitor','quantity'=>2,'price'=>300.00,'imported'=>true), + array('id'=>'ITN008','name'=>'CDRW drive','quantity'=>1,'price'=>40.00,'imported'=>true), + array('id'=>'ITN009','name'=>'Cooling fan','quantity'=>2,'price'=>10.00,'imported'=>false), + array('id'=>'ITN010','name'=>'Video camera','quantity'=>20,'price'=>30.00,'imported'=>true), + array('id'=>'ITN011','name'=>'Card reader','quantity'=>10,'price'=>24.00,'imported'=>true), + array('id'=>'ITN012','name'=>'Floppy drive','quantity'=>50,'price'=>12.00,'imported'=>false), + array('id'=>'ITN013','name'=>'CD drive','quantity'=>25,'price'=>20.00,'imported'=>true), + array('id'=>'ITN014','name'=>'DVD drive','quantity'=>15,'price'=>80.00,'imported'=>true), + array('id'=>'ITN015','name'=>'Mouse pad','quantity'=>50,'price'=>5.00,'imported'=>false), + array('id'=>'ITN016','name'=>'Network cable','quantity'=>40,'price'=>8.00,'imported'=>true), + array('id'=>'ITN017','name'=>'Case','quantity'=>8,'price'=>65.00,'imported'=>false), + array('id'=>'ITN018','name'=>'Surge protector','quantity'=>45,'price'=>15.00,'imported'=>false), + array('id'=>'ITN019','name'=>'Speaker','quantity'=>35,'price'=>65.00,'imported'=>false), + ); + return array_slice($data,$offset,$limit); + } + + /** + * Determines which page of data to be displayed and + * populates the datalist with the fetched data. + */ + protected function populateData() + { + $offset=$this->DataList->CurrentPageIndex*$this->DataList->PageSize; + $limit=$this->DataList->PageSize; + if($offset+$limit>$this->DataList->VirtualItemCount) + $limit=$this->DataList->VirtualItemCount-$offset; + $data=$this->getData($offset,$limit); + $this->DataList->DataSource=$data; + $this->DataList->dataBind(); + } + + public function onLoad($param) + { + parent::onLoad($param); + if(!$this->IsPostBack) + { + $this->DataList->VirtualItemCount=$this->DataItemCount; + $this->populateData(); + } + } + + /** + * Event handler to the OnPageIndexChanged event of pagers. + */ + public function pageChanged($sender,$param) + { + $this->DataList->CurrentPageIndex=$param->NewPageIndex; + $this->populateData(); + } +} + +?>
\ No newline at end of file diff --git a/demos/quickstart/protected/pages/GettingStarted/NewFeatures.page b/demos/quickstart/protected/pages/GettingStarted/NewFeatures.page index 595bda00..3d9bc155 100644 --- a/demos/quickstart/protected/pages/GettingStarted/NewFeatures.page +++ b/demos/quickstart/protected/pages/GettingStarted/NewFeatures.page @@ -5,6 +5,11 @@ <p id="40005" class="block-content">
This page summarizes the main new features that are introduced in each PRADO release.
</p>
+ +<h2>Version 3.1.2</h2> +<ul> +<li>Added a new active control <a href="?page=ActiveControls.ActivePager">TActivePager</a> that allows to paginate a databound control with an ajax callback.</li> +</ul> <h2>Version 3.1.1</h2>
<ul>
diff --git a/framework/Web/UI/ActiveControls/TActivePager.php b/framework/Web/UI/ActiveControls/TActivePager.php new file mode 100644 index 00000000..b23948e0 --- /dev/null +++ b/framework/Web/UI/ActiveControls/TActivePager.php @@ -0,0 +1,204 @@ +<?php +/** + * TActivePager class file. + * + * @author "gevik" (forum contributor) and Christophe Boulain (Christophe.Boulain@gmail.com) + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2008 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ + * @package System.Web.UI.ActiveControls + */ + +/** + * Load active control adapter. + */ +Prado::using('System.Web.UI.ActiveControls.TActiveControlAdapter'); + +/** + * TActivePager is the active control counter part of TPager. + * + * When a page change is requested, TActivePager raises a callback instead of the + * traditional postback. + * + * The {@link onCallback OnCallback} event is raised during a callback request + * and it is raise <b>after</b> the {@link onPageIndexChanged OnPageIndexChanged} event. + * + * @author "gevik" (forum contributor) and Christophe Boulain (Christophe.Boulain@gmail.com) + * @version $Id$ + * @package System.Web.UI.ActiveControls + * @since 3.1.2 + */ +class TActivePager extends TPager implements IActiveControl, ICallbackEventHandler +{ + /** + * Creates a new callback control, sets the adapter to + * TActiveControlAdapter. If you override this class, be sure to set the + * adapter appropriately by, for example, by calling this constructor. + */ + public function __construct() + { + parent::__construct(); + $this->setAdapter(new TActiveControlAdapter($this)); + } + + /** + * @return TBaseActiveControl standard active control options. + */ + public function getActiveControl() + { + return $this->getAdapter()->getBaseActiveControl(); + } + + + /** + * @return TCallbackClientSide client side request options. + */ + public function getClientSide() + { + return $this->getAdapter()->getBaseActiveControl()->getClientSide(); + } + + /** + * Raises the callback event. This method is required by {@link + * ICallbackEventHandler} interface. + * This method is mainly used by framework and control developers. + * @param TCallbackEventParameter the event parameter + */ + + public function raiseCallbackEvent($param) + { + $this->onCallback($param); + } + + /** + * This method is invoked when a callback is requested. The method raises + * 'OnCallback' 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 TCallbackEventParameter event parameter to be passed to the event handlers + */ + + public function onCallback($param) + { + $this->raiseEvent('OnCallback', $this, $param); + } + + /** + * Builds a dropdown list pager + * Override parent implementation to build Active dropdown lists. + */ + protected function buildListPager() + { + $list=new TActiveDropDownList; + + $list->getAdapter()->getBaseActiveControl()->setClientSide( + $this->getClientSide() + ); + + $this->getControls()->add($list); + $list->setDataSource(range(1,$this->getPageCount())); + $list->dataBind(); + $list->setSelectedIndex($this->getCurrentPageIndex()); + $list->setAutoPostBack(true); + $list->attachEventHandler('OnSelectedIndexChanged',array($this,'listIndexChanged')); + $list->attachEventHandler('OnCallback', array($this, 'handleCallback')); + } + + /** + * Creates a pager button. + * Override parent implementation to create, depending on the button type, a TActiveLinkButton, + * a TActiveButton or a TActiveImageButton may be created. + * + * @param string button type, either LinkButton or PushButton + * @param boolean whether the button should be enabled + * @param string caption of the button + * @param string CommandName corresponding to the OnCommand event of the button + * @param string CommandParameter corresponding to the OnCommand event of the button + * @return mixed the button instance + */ + protected function createPagerButton($buttonType,$enabled,$text,$commandName,$commandParameter) + { + if($buttonType===TPagerButtonType::LinkButton) + { + if($enabled) + $button=new TActiveLinkButton; + else + { + $button=new TLabel; + $button->setText($text); + return $button; + } + } + else if($buttonType===TPagerButtonType::ImageButton) + { + $button = new TActiveImageButton; + $button->setImageUrl($this->getPageImageUrl($text,$commandName)); + if($enabled) + $button->Visible = true; + else + $button->Visible = false; + } + else + { + $button=new TActiveButton; + if(!$enabled) + $button->setEnabled(false); + } + + if($buttonType===TPagerButtonType::ImageButton) + { + $button->ImageUrl = $text; + } + + $button->setText($text); + $button->setCommandName($commandName); + $button->setCommandParameter($commandParameter); + $button->setCausesValidation(false); + + $button->attachEventHandler('OnCallback', array($this, 'handleCallback')); + $button->getAdapter()->getBaseActiveControl()->setClientSide( + $this->getClientSide() + ); + + return $button; + } + + /** + * Event handler to the OnCallback active buttons or active dropdownlist. + * This handler will raise the {@link onCallback OnCallback} event + * + * @param mixed $sender + * @param TCallbackEventParameter $param + */ + public function handleCallback ($sender,$param) + { + // Update all the buttons pagers attached to the same control. + // Dropdown pagers doesn't need to be re-rendered. + $controlToPaginate=$this->getControlToPaginate(); + foreach ($this->getNamingContainer()->findControlsByType('TActivePager') as $control) + { + if ($control->getMode() !== TPagerMode::DropDownList && $control->getControlToPaginate()===$controlToPaginate) + $control->render($param->getNewWriter()); + } + + // Raise callback event + $this->onCallback($param); + } + + public function render ($writer) + { + if($this->getHasPreRendered()) + { + parent::render($writer); + if($this->getActiveControl()->canUpdateClientSide()) + $this->getPage()->getCallbackClient()->replaceContent($this,$writer); + } + else + { + $this->getPage()->getAdapter()->registerControlToRender($this,$writer); + } + } +} + +?>
\ No newline at end of file |