diff --git a/wire/modules/Markup/MarkupPagerNav/MarkupPagerNav.module b/wire/modules/Markup/MarkupPagerNav/MarkupPagerNav.module index 60d14518..61ccba19 100644 --- a/wire/modules/Markup/MarkupPagerNav/MarkupPagerNav.module +++ b/wire/modules/Markup/MarkupPagerNav/MarkupPagerNav.module @@ -1,73 +1,108 @@ find("id>0, limit=10"); // replace id>0 with your selector - * $pager = $modules->get("MarkupPagerNav"); - * echo "
Sorry there were no items found
"; + * } + * ~~~~~ + * Here’s a shortcut alternative that you can use for PageArray types (thanks to the `MarkupPageArray` module). + * Note that in this case, it’s not necessary to load the MarkupPagerNav module yourself: + * ~~~~~ + * $items = $pages->find("id>0, limit=10"); // replace id>0 with your selector + * if($items->count()) { + * echo "Sorry there were no items found
"; + * } + * ~~~~~ + * It’s common to specify different markup and/or classes specific to the need when rendering + * pagination. This is done by providing an `$options` array to the `MarkupPagerNav::render()` call. + * In the example below, we'll specify Uikit markup rather then the default markup: + * ~~~~~ + * // Change options for Uikit "uk-pagination" navigation + * $options = array( + * 'numPageLinks' => 5, + * 'listClass' => 'uk-pagination', + * 'linkMarkup' => "{out}", + * 'currentItemClass' => 'uk-active', + * 'separatorItemLabel' => '…', + * 'separatorItemClass' => 'uk-disabled', + * 'currentLinkMarkup' => "{out}" + * 'nextItemLabel' => '', + * 'previousItemLabel' => '', + * 'nextItemClass' => '', // blank out classes irrelevant to Uikit + * 'previousItemClass' => '', + * 'lastItemClass' => '', + * ); + * + * $items = $pages->find("id>0, limit=10"); // replace id>0 with your selector + * + * if($items->count()) { + * $pager = $modules->get('MarkupPagerNav'); + * echo "Sorry there were no items found
"; + * } + * ~~~~~ + * The full list of options can be seen below. Please note that most options are set automatically since this module can + * determine most of the needed information directly from the WireArray that it’s given. As a result, it’s often + * not necessary to change any of the default options unless you want to change the markup and/or classes used in output. + * #pw-body + * + * @property int $numPageLinks The number of links that the pagination navigation should have (default=10). #pw-group-general-options + * @property array $getVars GET vars that should appear in the pagination, or leave empty and populate $input->whitelist (recommended). #pw-group-general-options + * @property string $baseUrl The base URL from which the navigation item links will start (default=''). #pw-group-general-options + * @property null|Page $page The current Page, or leave NULL to autodetect. #pw-group-general-options + * @property string $listMarkup List container markup. Place {out} where you want the individual items rendered and {class} where you want the list class (default="Sorry there were no items found
"; + * } + * ~~~~~ * - * @param WirePaginatable $items Pages used in the pagination that have had a "limit=n" selector applied when they were loaded. - * @param array $options Any options to override the defaults. For the defaults see MarkupPagerNav::$options + * @param WirePaginatable|PageArray|PaginatedArray $items Items used in the pagination that have had a "limit=n" selector applied when they were loaded. + * @param array $options Any options to override the defaults. See the `MarkupPagerNav` reference for all options. * @return string + * @see MarkupPageArray::renderPager() * */ public function ___render(WirePaginatable $items, $options = array()) { @@ -232,10 +309,7 @@ class MarkupPagerNav extends Wire implements Module { foreach($pager as $key => $item) { if($item->type == 'separator') { - $out .= str_replace( - array('{class}', '{out}'), - array($this->options['separatorItemClass'], $this->options['separatorItemLabel']), - $this->options['itemMarkup']); + $out .= $this->renderItemSeparator(); continue; } @@ -255,24 +329,64 @@ class MarkupPagerNav extends Wire implements Module { $url .= $this->queryString; } - $class = isset($this->options[$item->type . 'ItemClass']) ? $this->options[$item->type . 'ItemClass'] : ''; + $classes = array(); + + if($item->type != 'first' && $item->type != 'last' && isset($this->options[$item->type . 'ItemClass'])) { + $classes[] = $this->options[$item->type . 'ItemClass']; + } - if(!$key) $class .= ' ' . $this->options['firstItemClass']; - else if($key == ($pagerCount-1)) $class .= ' ' . $this->options['lastItemClass']; + if(!$key) { + $classes[] = $this->options['firstItemClass']; + } else if($key == ($pagerCount-1)) { + $classes[] = $this->options['lastItemClass']; + } if($key === $firstNumberKey) { - $class .= ' ' . $this->options['firstNumberItemClass']; + $classes[] = $this->options['firstNumberItemClass']; } else if($key === $lastNumberKey) { - $class .= ' ' . $this->options['lastNumberItemClass']; + $classes[] = $this->options['lastNumberItemClass']; if($item->type == 'current') $this->isLastPage = true; } - $itemCurrentAriaLabel = $item->type == 'current' ? $this->options['itemCurrentAriaLabel'] : ""; - $itemCurrentAriaMarker = $item->type == 'current' ? 'aria-current="true"' : ""; - - $linkMarkup = isset($this->options[$item->type . 'LinkMarkup']) ? $this->options[$item->type . 'LinkMarkup'] : $this->options['linkMarkup']; + $itemExtraAttr = ''; + if($item->type == 'current') { + $itemAriaLabel = $this->options['currentItemAriaLabel']; + $itemExtraAttr = ' ' . $this->options['currentItemExtraAttr']; + } else if($item->type == 'previous') { + $itemAriaLabel = $this->options['previousItemAriaLabel']; + } else if($item->type == 'next') { + $itemAriaLabel = $this->options['nextItemAriaLabel']; + } else if($item->type == 'last') { + $itemAriaLabel = $this->options['lastItemAriaLabel']; + } else { + $itemAriaLabel = $this->options['itemAriaLabel']; + } + $itemAriaLabel = str_replace('{n}', $item->pageNum, $itemAriaLabel); + + if(isset($this->options[$item->type . 'LinkMarkup'])) { + $linkMarkup = $this->options[$item->type . 'LinkMarkup']; + } else { + $linkMarkup = $this->options['linkMarkup']; + } $link = str_replace(array('{url}', '{out}'), array($url, $item->label), $linkMarkup); - $out .= str_replace(array('{class}', '{out}', '{item-aria-label}', '{item-current-aria-marker}'), array(trim($class), $link , $this->options['itemAriaLabel'] . $item->pageNum . $itemCurrentAriaLabel, $itemCurrentAriaMarker), $this->options['itemMarkup']); + + $out .= str_replace( + array( + '{class}', + '{out}', + '{aria-label}', + ' {attr}', + '{attr}' + ), + array( + implode(' ', $classes), + $link, + $itemAriaLabel, + $itemExtraAttr, + $itemExtraAttr + ), + $this->options['itemMarkup'] + ); if($item->type == 'current') { $prevURL = $_url; @@ -286,9 +400,19 @@ class MarkupPagerNav extends Wire implements Module { } if($out) { - $out = str_replace(array(" class=''", ' class=""'), '', $out); - $out = str_replace('{out}', $out, $this->options['listMarkup']); - $out = str_replace('{pager-aria-label}', $this->options['pagerAriaLabel'], $out ); + $out = str_replace(array( + '{class}', + '{aria-label}', + '{out}', + " class=''", + ' class=""' + ), array( + $this->options['listClass'], + $this->options['listAriaLabel'], + $out, + '', + '' + ), $this->options['listMarkup']); if($nextURL) $config->urls->next = $nextURL; if($prevURL) $config->urls->prev = $prevURL; @@ -297,8 +421,42 @@ class MarkupPagerNav extends Wire implements Module { return $out; } + /** + * Render the "..." item separator + * + * @return string + * + */ + protected function renderItemSeparator() { + if($this->options['separatorItemMarkup'] !== null) { + $markup = $this->options['separatorItemMarkup']; + } else { + $markup = $this->options['itemMarkup']; + } + return str_replace( + array( + '{class}', + '{out}', + '{aria-label}', + ' {attr}', // optionally with leading space + '{attr}' + ), + array( + $this->options['separatorItemClass'], + $this->options['separatorItemLabel'], + '', + '', + '' + ), + $markup + ); + } + /** * Retrieve a MarkupPagerNav option as an object property + * + * @param string $property + * @return mixed * */ public function __get($property) { @@ -309,63 +467,21 @@ class MarkupPagerNav extends Wire implements Module { /** * Set a MarkupPagerNav option as an object property + * + * @param string $property + * @param mixed $value * */ public function __set($property, $value) { if(isset($this->options[$property])) $this->options[$property] = $value; } - /** - * Set the getVars for this MarkupPagerNav - * - * Generates $this->options['queryString'] automatically. - * - * @param array $vars Array of GET vars indexed as ($key => $value) - * - */ - public function setGetVars(array $vars) { - $this->options['getVars'] = $vars; - $queryString = "?"; - foreach($this->options['getVars'] as $key => $value) { - if(is_array($value)) { - if($this->options['arrayToCSV']) { - $a = $value; - $value = ''; - foreach($a as $k => $v) $value .= "$v,"; - $value = rtrim($value, ", "); - $queryString .= "$key=" . urlencode($value) . "&"; - } else { - foreach($value as $k => $v) $queryString .= "$key%5B%5D=" . urlencode($v) . "&"; - } - - } else { - $queryString .= "$key=" . urlencode($value) . "&"; - } - } - $this->queryString = htmlspecialchars(rtrim($queryString, "?&")); - } - - /* - * All the methods below are optional and typically set automatically, or via the $options param. - * - */ - - public function setPageNum($n) { $this->pageNum = $n; } - public function setItemsPerPage($n) { $this->itemsPerPage = $n; } - public function setTotalItems($n) { $this->totalItems = $n; } - public function setNumPageLinks($n) { $this->numPageLinks = $n; } - public function setQueryString($s) { $this->queryString = $s; } - public function setBaseUrl($url) { $this->baseUrl = $url; } - - public function setLabels($next, $prev) { - $this->options['nextItemLabel'] = $next; - $this->options['previousItemLabel'] = $prev; - } - /** * Returns true when the current pagination is the last one * * Only set after a render() call. Prior to that it is null. + * + * #pw-internal * * @return bool|null * @@ -374,7 +490,149 @@ class MarkupPagerNav extends Wire implements Module { return $this->isLastPage; } + /** + * Get all options or set options + * + * - See the main `MarkupPagerNav` documentation for a list of all available options. + * - When used to set options this method should be called before the `MarkupPagerNav::render()` method. + * - Options can also be set as a 2nd argument to the `MarkupPagerNav::render()` method. + * + * ~~~~~ + * // Getting options + * echo "" . print_r($pager->options(), true) . ""; + * + * // Setting options + * $pager->options([ 'numPageLinks' => 5 ]); + * echo $pager->render($items); + * + * // Alternative that does the same as above + * echo $pager->render($items, [ 'numPageLinks' => 5 ]); + * ~~~~~ + * + * @param array $options Associative array of options you want to set, or omit to just return all available/current options. + * @return array Returns associative array if options with all current values. + * @since 3.0.44 + * + */ + public function options(array $options = array()) { + if(!empty($options)) { + $this->options = array_merge($this->options, $options); + } + return $this->options; + } + /************************************************************************************************* + * All the methods below are optional and typically set automatically, or via the $options param. + * + */ + + /** + * Set the getVars for this MarkupPagerNav + * + * Generates $this->options['queryString'] automatically. + * + * #pw-group-method-options + * + * @param array $vars Array of GET vars indexed as ($key => $value) + * + */ + public function setGetVars(array $vars) { + $this->options['getVars'] = $vars; + $queryString = "?"; + foreach($this->options['getVars'] as $key => $value) { + if(is_array($value)) { + if($this->options['arrayToCSV']) { + $a = $value; + $value = ''; + foreach($a as $k => $v) $value .= "$v,"; + $value = rtrim($value, ", "); + $queryString .= "$key=" . urlencode($value) . "&"; + } else { + foreach($value as $k => $v) $queryString .= "$key%5B%5D=" . urlencode($v) . "&"; + } + + } else { + $queryString .= "$key=" . urlencode($value) . "&"; + } + } + $this->queryString = htmlspecialchars(rtrim($queryString, "?&")); + } + + + /** + * Set the current page number + * + * #pw-group-method-options + * + * @param int $n + * + */ + public function setPageNum($n) { $this->pageNum = $n; } + + /** + * Set the number of items shown per page + * + * #pw-group-method-options + * + * @param int $n + * + */ + public function setItemsPerPage($n) { $this->itemsPerPage = $n; } + + /** + * Set the total number of items + * + * #pw-group-method-options + * + * @param int $n + * + */ + public function setTotalItems($n) { $this->totalItems = $n; } + + /** + * Set the number of pagination links to use + * + * #pw-group-method-options + * + * @param int $n + * + */ + public function setNumPageLinks($n) { $this->numPageLinks = $n; } + + /** + * Set the query string + * + * #pw-group-method-options + * + * @param string $s Already-sanitized/validated query string + * + */ + public function setQueryString($s) { $this->queryString = $s; } + + /** + * Set the base URL for pagination + * + * #pw-group-method-options + * + * @param string $url + * + */ + public function setBaseUrl($url) { $this->baseUrl = $url; } + + /** + * Set the "next" and "prev" labels + * + * #pw-group-method-options + * + * @param string $next + * @param string $prev + * + */ + public function setLabels($next, $prev) { + $this->options['nextItemLabel'] = $next; + $this->options['previousItemLabel'] = $prev; + } + /* * The following methods are specific to the Module interface *