Files
@ 2323e2bb2797
Branch filter:
Location: kallithea/kallithea/lib/page.py
2323e2bb2797
6.9 KiB
text/x-python
page: consistently invoke Page with kwargs instead of explicitly providing a custom url generator
Drop the option of providing an url maker as 'url', and thus also hardcode the
assumption that the page parameter is called page.
Drop the option of providing an url maker as 'url', and thus also hardcode the
assumption that the page parameter is called page.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | # -*- coding: utf-8 -*-
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
Custom paging classes
"""
import logging
import re
from webhelpers2.html import HTML, literal
from webhelpers.paginate import Page as _Page
from kallithea.config.routing import url
log = logging.getLogger(__name__)
class Page(_Page):
"""
Custom pager emitting Bootstrap paginators
"""
def __init__(self, collection,
page=1, items_per_page=20, item_count=None,
**kwargs):
_Page.__init__(self, collection, page=page, items_per_page=items_per_page, item_count=item_count,
url=url.current, **kwargs)
def _get_pos(self, cur_page, max_page, items):
edge = (items / 2) + 1
if (cur_page <= edge):
radius = max(items / 2, items - cur_page)
elif (max_page - cur_page) < edge:
radius = (items - 1) - (max_page - cur_page)
else:
radius = items / 2
left = max(1, (cur_page - (radius)))
right = min(max_page, cur_page + (radius))
return left, cur_page, right
def _range(self, regexp_match):
"""
Return range of linked pages (e.g. '1 2 [3] 4 5 6 7 8').
Arguments:
regexp_match
A "re" (regular expressions) match object containing the
radius of linked pages around the current page in
regexp_match.group(1) as a string
This function is supposed to be called as a callable in
re.sub.
"""
radius = int(regexp_match.group(1))
# Compute the first and last page number within the radius
# e.g. '1 .. 5 6 [7] 8 9 .. 12'
# -> leftmost_page = 5
# -> rightmost_page = 9
leftmost_page, _cur, rightmost_page = self._get_pos(self.page,
self.last_page,
(radius * 2) + 1)
nav_items = []
# Create a link to the first page (unless we are on the first page
# or there would be no need to insert '..' spacers)
if self.page != self.first_page and self.first_page < leftmost_page:
nav_items.append(HTML.li(self._pagerlink(self.first_page, self.first_page)))
# Insert dots if there are pages between the first page
# and the currently displayed page range
if leftmost_page - self.first_page > 1:
# Wrap in a SPAN tag if nolink_attr is set
text_ = '..'
if self.dotdot_attr:
text_ = HTML.span(c=text_, **self.dotdot_attr)
nav_items.append(HTML.li(text_))
for thispage in xrange(leftmost_page, rightmost_page + 1):
# Highlight the current page number and do not use a link
text_ = str(thispage)
if thispage == self.page:
# Wrap in a SPAN tag if nolink_attr is set
if self.curpage_attr:
text_ = HTML.li(HTML.span(c=text_), **self.curpage_attr)
nav_items.append(text_)
# Otherwise create just a link to that page
else:
nav_items.append(HTML.li(self._pagerlink(thispage, text_)))
# Insert dots if there are pages between the displayed
# page numbers and the end of the page range
if self.last_page - rightmost_page > 1:
text_ = '..'
# Wrap in a SPAN tag if nolink_attr is set
if self.dotdot_attr:
text_ = HTML.span(c=text_, **self.dotdot_attr)
nav_items.append(HTML.li(text_))
# Create a link to the very last page (unless we are on the last
# page or there would be no need to insert '..' spacers)
if self.page != self.last_page and rightmost_page < self.last_page:
nav_items.append(HTML.li(self._pagerlink(self.last_page, self.last_page)))
#_page_link = url.current()
#nav_items.append(literal('<link rel="prerender" href="%s?page=%s">' % (_page_link, str(int(self.page)+1))))
#nav_items.append(literal('<link rel="prefetch" href="%s?page=%s">' % (_page_link, str(int(self.page)+1))))
return self.separator.join(nav_items)
def pager(self, format='<ul class="pagination">$link_previous ~2~ $link_next</ul>', page_param='page', partial_param='partial',
show_if_single_page=False, separator=' ', onclick=None,
symbol_first='<<', symbol_last='>>',
symbol_previous='<', symbol_next='>',
link_attr=None,
curpage_attr=None,
dotdot_attr=None, **kwargs
):
self.curpage_attr = curpage_attr or {'class': 'active'}
self.separator = separator
self.pager_kwargs = kwargs
self.page_param = page_param
self.partial_param = partial_param
self.onclick = onclick
self.link_attr = link_attr or {'class': 'pager_link', 'rel': 'prerender'}
self.dotdot_attr = dotdot_attr or {'class': 'pager_dotdot'}
# Don't show navigator if there is no more than one page
if self.page_count == 0 or (self.page_count == 1 and not show_if_single_page):
return ''
from string import Template
# Replace ~...~ in token format by range of pages
result = re.sub(r'~(\d+)~', self._range, format)
# Interpolate '%' variables
result = Template(result).safe_substitute({
'first_page': self.first_page,
'last_page': self.last_page,
'page': self.page,
'page_count': self.page_count,
'items_per_page': self.items_per_page,
'first_item': self.first_item,
'last_item': self.last_item,
'item_count': self.item_count,
'link_first': self.page > self.first_page and
self._pagerlink(self.first_page, symbol_first) or '',
'link_last': self.page < self.last_page and
self._pagerlink(self.last_page, symbol_last) or '',
'link_previous': HTML.li(self.previous_page and
self._pagerlink(self.previous_page, symbol_previous)
or HTML.a(symbol_previous)),
'link_next': HTML.li(self.next_page and
self._pagerlink(self.next_page, symbol_next)
or HTML.a(symbol_next)),
})
return literal(result)
|