PHP Classes

File: src/python/Paginator.py

Recommend this page to a friend!
  Classes of Nikos M.   Alt PHP Paginator   src/python/Paginator.py   Download  
File: src/python/Paginator.py
Role: Auxiliary data
Content type: text/plain
Description: Auxiliary data
Class: Alt PHP Paginator
Generate pagination controls for Web pages
Author: By
Last change:
Date: 2 years ago
Size: 9,397 bytes
 

Contents

Class file image Download
## # Paginator # Simple and versatile Pagination utility class for PHP, Python, Node.js / Browser Javascript # # @version: 1.0.0 # https://github.com/foo123/Paginator # ## import math, re html_esc_re = re.compile(r'[&<>\'"]') def htmlspecialchars_replace( match ): m = match.group(0) if m == '&': return '&amp;' elif m == '<': return '&lt;' elif m == '>': return '&gt;' elif m == '"': return '&quot;' else: return m def htmlspecialchars( s ): global html_esc_re return re.sub(html_esc_re, htmlspecialchars_replace, str(s)) class Paginator: VERSION = '1.0.0' def __init__( self, totalItems=0, itemsPerPage=0, currentPage=1 ): self._maxPagesToShow = 10 self._placeholder = '(:page)' self._urlPattern = '?page=' + self._placeholder self._previousText = '&laquo; Previous' self._nextText = 'Next &raquo;' self._ellipsis = '...' self._view = 'list' self._numPages = 0 self._totalItems = int(totalItems) self._itemsPerPage = int(itemsPerPage) self._currentPage = int(currentPage) self.computeNumPages() def computeNumPages( self ): self._numPages = 0 if 0 >= self._itemsPerPage or 0 >= self._totalItems else math.ceil(self._totalItems/self._itemsPerPage) return self def numPages( self ): return self._numPages def totalItems( self, *args ): if len(args): self._totalItems = int(args[0]) return self.computeNumPages() else: return self._totalItems def itemsPerPage( self, *args ): if len(args): self._itemsPerPage = int(args[0]) return self.computeNumPages() else: return self._itemsPerPage def currentPage( self, *args ): if len(args): self._currentPage = int(args[0]) return self else: return self._currentPage def maxPagesToShow( self, *args ): if len(args): maxPagesToShow = int(args[0]) if maxPagesToShow < 3: raise ValueError('maxPagesToShow cannot be less than 3!') self._maxPagesToShow = maxPagesToShow return self else: return self._maxPagesToShow def urlPattern( self, *args ): if len(args): self._urlPattern = str(args[0]) return self else: return self._urlPattern def placeholder( self, *args ): if len(args): self._placeholder = str(args[0]) return self else: return self._placeholder def previousText( self, *args ): if len(args): self._previousText = str(args[0]) return self else: return self._previousText def nextText( self, *args ): if len(args): self._nextText = str(args[0]) return self else: return self._nextText def ellipsis( self, *args ): if len(args): self._ellipsis = str(args[0]) return self else: return self._ellipsis def view( self, *args ): if len(args): view = str(args[0]).lower() if 'mobile' == view: view = 'selectbox' elif 'selectbox' == view: view = 'selectbox' elif 'select' == view: view = 'selectbox' else: view = 'list' self._view = view return self else: return self._view def pageUrl( self, pageNum ): return self._urlPattern.replace(self._placeholder, str(pageNum)) def prevPage( self ): return self._currentPage-1 if self._currentPage > 1 else None def nextPage( self ): return self._currentPage+1 if self._currentPage < self._numPages else None def prevUrl( self ): return self.pageUrl( self.prevPage( ) ) if self.prevPage( ) else None def nextUrl( self ): return self.pageUrl( self.nextPage( ) ) if self.nextPage( ) else None def currentPageFirstItem( self ): first = (self._currentPage - 1) * self._itemsPerPage + 1 return None if first > self._totalItems else first def currentPageLastItem( self ): first = self.currentPageFirstItem() if first is None: return None last = first + self._itemsPerPage - 1 return self._totalItems if last > self._totalItems else last ## # Get a list of paginated page data. # # Example: # list( # dict ('num' : 1, 'url' : '/example/page/1', 'isCurrent' : false), # dict ('num' : '...', 'url' : NULL, 'isCurrent' : false), # dict ('num' : 3, 'url' : '/example/page/3', 'isCurrent' : false), # dict ('num' : 4, 'url' : '/example/page/4', 'isCurrent' : true ), # dict ('num' : 5, 'url' : '/example/page/5', 'isCurrent' : false), # dict ('num' : '...', 'url' : NULL, 'isCurrent' : false), # dict ('num' : 10, 'url' : '/example/page/10', 'isCurrent' : false), # ) # # @return list # def pages( self ): pages = [] if 1 >= self._numPages: return pages if self._numPages <= self._maxPagesToShow: for i in range(1, self._numPages+1): pages.append(self.createPage(i, i==self._currentPage)) else: # Determine the sliding range, centered around the current page. numAdjacents = math.floor((self._maxPagesToShow - 3) / 2) if self._currentPage + numAdjacents > self._numPages: slidingStart = self._numPages - self._maxPagesToShow + 2 else: slidingStart = self._currentPage - numAdjacents if slidingStart < 2: slidingStart = 2 slidingEnd = slidingStart + self._maxPagesToShow - 3 if slidingEnd >= self._numPages: slidingEnd = self._numPages - 1 # Build the list of pages. # first pages.append(self.createPage(1, 1==self._currentPage)) # ellipsis .. if slidingStart > 2: pages.append(self.createPage(None)) # shown pages for i in range(slidingStart,slidingEnd+1): pages.append(self.createPage(i, i==self._currentPage)) # ellipsis .. if slidingEnd < self._numPages - 1: pages.append(self.createPage(None)) # last pages.append(self.createPage(self._numPages, self._numPages==self._currentPage)) return pages def createPage( self, pageNum, isCurrent=False ): return { 'num' : self._ellipsis, 'url' : None, 'isCurrent' : False } if pageNum is None else { 'num' : pageNum, 'url' : self.pageUrl(pageNum), 'isCurrent' : bool(isCurrent) } def render( self ): if 1 >= self._numPages: return '' if 'selectbox' == self._view: html = '<div class="pagination">' # previous link if self.prevUrl( ): html += '<span class="page-previous"><a href="' + htmlspecialchars(self.prevUrl()) + '">'+ self._previousText +'</a></span>'; html += '<select class="page-select">' # shown pages by number including first and last for page in self.pages(): if page['url']: # actual page with page number html += '<option value="' + htmlspecialchars(page['url']) + '"' + (' selected' if page['isCurrent'] else '') + '>' + str(page['num']) + '</option>' else: # ellipsis, more html += '<option disabled>' + str(page['num']) + '</option>' html += '</select>' # next link if self.nextUrl(): html += '<span class="page-next"><a href="' + htmlspecialchars(self.nextUrl()) + '">'+ self._nextText +'</a></span>'; html += '</div>' else: # possibly should be wrapped around <nav></nav> element when used html = '<ul class="pagination">' # previous link if self.prevUrl( ): html += '<li class="page-previous"><a href="' + htmlspecialchars(self.prevUrl()) + '">'+ self._previousText +'</a></li>'; # shown pages by number including first and last for page in self.pages(): if page['url']: # actual page with page number html += '<li class="page-item' + (' first' if 1==page['num'] else '') + (' last' if self._numPages==page['num'] else '') + (' active' if page['isCurrent'] else '') + '"><a href="' + htmlspecialchars(page['url']) + '">' + str(page['num']) + '</a></li>' else: # ellipsis, more html += '<li class="page-item disabled"><span>' + str(page['num']) + '</span></li>' # next link if self.nextUrl(): html += '<li class="page-next"><a href="' + htmlspecialchars(self.nextUrl()) + '">'+ self._nextText +'</a></li>'; html += '</ul>' return html def __str__( self ): return self.render() __all__ = ['Paginator']