From 22ca2922d2cd63730a69ed5f816c51f23fcdcc6a Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Fri, 10 May 2013 22:33:24 -0400 Subject: [PATCH] Fixes issue #50: implemented pager widgets. --- yii/web/Pagination.php | 2 +- yii/widgets/LinkPager.php | 201 ++++++++++++++++++++++++++++++++++++++++++++++ yii/widgets/ListPager.php | 95 ++++++++++++++++++++++ 3 files changed, 297 insertions(+), 1 deletion(-) create mode 100644 yii/widgets/LinkPager.php create mode 100644 yii/widgets/ListPager.php diff --git a/yii/web/Pagination.php b/yii/web/Pagination.php index 764dbb4..3d4e242 100644 --- a/yii/web/Pagination.php +++ b/yii/web/Pagination.php @@ -73,7 +73,7 @@ class Pagination extends \yii\base\Object * @var boolean whether to always have the page parameter in the URL created by [[createUrl()]]. * If false and [[page]] is 0, the page parameter will not be put in the URL. */ - public $forcePageVar = false; + public $forcePageVar = true; /** * @var string the route of the controller action for displaying the paged contents. * If not set, it means using the currently requested route. diff --git a/yii/widgets/LinkPager.php b/yii/widgets/LinkPager.php new file mode 100644 index 0000000..1651246 --- /dev/null +++ b/yii/widgets/LinkPager.php @@ -0,0 +1,201 @@ + + * @since 2.0 + */ +class LinkPager extends Widget +{ + /** + * @var Pagination the pagination object that this pager is associated with. + * You must set this property in order to make LinkPager work. + */ + public $pagination; + /** + * @var array HTML attributes for the pager container tag. + */ + public $options = array('class' => 'pagination'); + /** + * @var string the CSS class for the "first" page button. + */ + public $firstPageCssClass = 'first'; + /** + * @var string the CSS class for the "last" page button. + */ + public $lastPageCssClass = 'last'; + /** + * @var string the CSS class for the "previous" page button. + */ + public $prevPageCssClass = 'prev'; + /** + * @var string the CSS class for the "next" page button. + */ + public $nextPageCssClass = 'next'; + /** + * @var string the CSS class for the active (currently selected) page button. + */ + public $activePageCssClass = 'active'; + /** + * @var string the CSS class for the disabled page buttons. + */ + public $disabledPageCssClass = 'disabled'; + /** + * @var integer maximum number of page buttons that can be displayed. Defaults to 10. + */ + public $maxButtonCount = 10; + /** + * @var string the label for the "next" page button. Note that this will NOT be HTML-encoded. + * If this property is null, the "next" page button will not be displayed. + */ + public $nextPageLabel = '»'; + /** + * @var string the text label for the previous page button. Note that this will NOT be HTML-encoded. + * If this property is null, the "previous" page button will not be displayed. + */ + public $prevPageLabel = '«'; + /** + * @var string the text label for the "first" page button. Note that this will NOT be HTML-encoded. + * If this property is null, the "first" page button will not be displayed. + */ + public $firstPageLabel; + /** + * @var string the text label for the "last" page button. Note that this will NOT be HTML-encoded. + * If this property is null, the "last" page button will not be displayed. + */ + public $lastPageLabel; + /** + * @var string the template used to render the content within the pager container. + * The token "{buttons}" will be replaced with the actual page buttons. + */ + public $template = '{buttons}'; + + + /** + * Initializes the pager. + */ + public function init() + { + if ($this->pagination === null) { + throw new InvalidConfigException('The "pagination" property must be set.'); + } + } + + /** + * Executes the widget. + * This overrides the parent implementation by displaying the generated page buttons. + */ + public function run() + { + $buttons = strtr($this->template, array( + '{buttons}' => Html::tag('ul', implode("\n", $this->createPageButtons())), + )); + echo Html::tag('div', $buttons, $this->options); + } + + /** + * Creates the page buttons. + * @return array a list of page buttons (in HTML code). + */ + protected function createPageButtons() + { + $buttons = array(); + + $pageCount = $this->pagination->pageCount; + $currentPage = $this->pagination->getPage(); + + // first page + if ($this->firstPageLabel !== null) { + $buttons[] = $this->createPageButton($this->firstPageLabel, 0, $this->firstPageCssClass, $currentPage <= 0, false); + } + + // prev page + if ($this->prevPageLabel !== null) { + if (($page = $currentPage - 1) < 0) { + $page = 0; + } + $buttons[] = $this->createPageButton($this->prevPageLabel, $page, $this->prevPageCssClass, $currentPage <= 0, false); + } + + // internal pages + list($beginPage, $endPage) = $this->getPageRange(); + for ($i = $beginPage; $i <= $endPage; ++$i) { + $buttons[] = $this->createPageButton($i + 1, $i, null, false, $i == $currentPage); + } + + // next page + if ($this->nextPageLabel !== null) { + if (($page = $currentPage + 1) >= $pageCount - 1) { + $page = $pageCount - 1; + } + $buttons[] = $this->createPageButton($this->nextPageLabel, $page, $this->nextPageCssClass, $currentPage >= $pageCount - 1, false); + } + + // last page + if ($this->lastPageLabel !== null) { + $buttons[] = $this->createPageButton($this->lastPageLabel, $pageCount - 1, $this->lastPageCssClass, $currentPage >= $pageCount - 1, false); + } + + return $buttons; + } + + /** + * Creates a page button. + * You may override this method to customize the generation of page buttons. + * @param string $label the text label for the button + * @param integer $page the page number + * @param string $class the CSS class for the page button. + * @param boolean $disabled whether this page button is disabled + * @param boolean $active whether this page button is active + * @return string the generated button + */ + protected function createPageButton($label, $page, $class, $disabled, $active) + { + if ($active) { + $class .= ' ' . $this->activePageCssClass; + } + if ($disabled) { + $class .= ' ' . $this->disabledPageCssClass; + } + $class = trim($class); + $options = array('class' => $class === '' ? null : $class); + return Html::tag('li', Html::a($label, $this->pagination->createUrl($page)), $options); + } + + /** + * @return array the begin and end pages that need to be displayed. + */ + protected function getPageRange() + { + $currentPage = $this->pagination->getPage(); + $pageCount = $this->pagination->getPageCount(); + + $beginPage = max(0, $currentPage - (int)($this->maxButtonCount / 2)); + if (($endPage = $beginPage + $this->maxButtonCount - 1) >= $pageCount) { + $endPage = $pageCount - 1; + $beginPage = max(0, $endPage - $this->maxButtonCount + 1); + } + return array($beginPage, $endPage); + } +} \ No newline at end of file diff --git a/yii/widgets/ListPager.php b/yii/widgets/ListPager.php new file mode 100644 index 0000000..1bc2b21 --- /dev/null +++ b/yii/widgets/ListPager.php @@ -0,0 +1,95 @@ + + * @since 2.0 + */ +class ListPager extends Widget +{ + /** + * @var Pagination the pagination object that this pager is associated with. + * You must set this property in order to make ListPager work. + */ + public $pagination; + /** + * @var array HTML attributes for the drop-down list tag. The following options are specially handled: + * + * - prompt: string, a prompt text to be displayed as the first option. + * + * The rest of the options will be rendered as the attributes of the resulting tag. The values will + * be HTML-encoded using [[encode()]]. If a value is null, the corresponding attribute will not be rendered. + */ + public $options = array(); + /** + * @var string the template used to render the label for each list option. + * The token "{page}" will be replaced with the actual page number (1-based). + */ + public $template = '{page}'; + + + /** + * Initializes the pager. + */ + public function init() + { + if ($this->pagination === null) { + throw new InvalidConfigException('The "pagination" property must be set.'); + } + } + + /** + * Executes the widget. + * This overrides the parent implementation by displaying the generated page buttons. + */ + public function run() + { + $pageCount = $this->pagination->pageCount; + $currentPage = $this->pagination->getPage(); + + $pages = array(); + for ($i = 0; $i < $pageCount; ++$i) { + $pages[$this->pagination->createUrl($i)] = $this->generatePageText($i); + } + $selection = $this->pagination->createUrl($currentPage); + + if (!isset($this->options['onchange'])) { + $this->options['onchange'] = "if(this.value!='') {window.location=this.value;};"; + } + + echo Html::dropDownList(null, $selection, $pages, $this->options); + } + + /** + * Generates the label of the list option for the specified page number. + * You may override this method to customize the option display. + * @param integer $page zero-based page number + * @return string the list option for the page number + */ + protected function generatePageText($page) + { + return strtr($this->template, array( + '{page}' => $page + 1, + )); + } + +} \ No newline at end of file