Copyright 2019 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

package frontend

import (
	
	
	

	
)
pagination holds information related to paginated display. It is intended to be part of a view model struct. Given a sequence of results with offsets 0, 1, 2 ... (typically from a database query), we paginate it by dividing it into numbered pages 1, 2, 3, .... Each page except possibly the last has the same number of results.
type pagination struct {
	baseURL     *url.URL // URL common to all pages
	limit       int      // the maximum number of results on a page
	ResultCount int      // number of results on this page
	TotalCount  int      // total number of results
	Approximate bool     // whether or not the total count is approximate
	Page        int      // number of the current page
	PrevPage    int      //   "    "   "  previous page, usually Page-1 but zero if Page == 1
	NextPage    int      //   "    "   "  next page, usually Page+1, but zero on the last page
	Offset      int      // offset of the first item on the current page
	Pages       []int    // consecutive page numbers to be displayed for navigation
}
PageURL constructs a URL that displays the given page. It adds a "page" query parameter to the base URL.
func ( pagination) ( int) string {
	 := .baseURL.Query()
	.Set("page", strconv.Itoa())
	.baseURL.RawQuery = .Encode()
	return .baseURL.String()
}
newPagination constructs a pagination. Call it after some results have been obtained. resultCount is the number of results in the current page. totalCount is the total number of results.
func ( paginationParams, ,  int) pagination {
	return pagination{
		baseURL:     .baseURL,
		TotalCount:  ,
		ResultCount: ,
		Offset:      .offset(),
		limit:       .limit,
		Page:        .page,
		PrevPage:    prev(.page),
		NextPage:    next(.page, .limit, ),
		Pages:       pagesToLink(.page, numPages(.limit, ), defaultNumPagesToLink),
	}
}
paginationParams holds pagination parameters extracted from the request.
type paginationParams struct {
	baseURL *url.URL
	page    int // the number of the page to display
	limit   int // the maximum number of results to display on the page
}
offset returns the offset of the first result on the page.
func ( paginationParams) () int {
	return offset(.page, .limit)
}
newPaginationParams extracts pagination params from the request.
func ( *http.Request,  int) paginationParams {
	 := func( string,  int) ( int) {
		var  error
		if  := .FormValue();  != "" {
			,  = strconv.Atoi()
			if  != nil {
				log.Errorf(.Context(), "strconv.Atoi(%q) for page: %v", , )
			}
		}
		if  < 1 {
			 = 
		}
		return 
	}
	return paginationParams{
		baseURL: .URL,
		page:    ("page", 1),
		limit:   ("limit", ),
	}
}

const defaultNumPagesToLink = 5
pagesToLink returns the page numbers that will be displayed. Given a page, it returns a slice containing numPagesToLink integers in ascending order and optimizes for page to be in the middle of that range. The max value of an integer in the return slice will be less than numPages.
func (, ,  int) []int {
	var  []int
	 :=  - ( / 2)
	if ( - ) <  {
		 =  -  + 1
	}
	if  < 1 {
		 = 1
	}

	for  := ; ( < +) && ( <= ); ++ {
		 = append(, )
	}
	return 
}
numPages is the total number of pages needed to display all the results, given the specified maximum page size and the total number of results.
func (,  int) int {
	return ( +  - 1) / 
}
offset returns the offset of the first result on page, assuming all previous pages were of size limit.
func (,  int) int {
	if  <= 1 {
		return 0
	}
	return ( - 1) * 
}
prev returns the number of the page before the given page, or zero if the given page is 1 or smaller.
func ( int) int {
	if  <= 1 {
		return 0
	}
	return  - 1
}
next returns the number of the page after the given page, or zero if page is is the last page or larger. limit and totalCount are used to calculate the last page (see numPages).
func (, ,  int) int {
	if  >= numPages(, ) {
		return 0
	}
	return  + 1