website/pkg/models/pagination.go

123 lines
2.3 KiB
Go

package models
import (
"math"
"net/http"
"strconv"
"code.nonshy.com/nonshy/website/pkg/config"
)
// Pagination result object.
type Pagination struct {
Page int // provide <0 to mean "last page"
PerPage int
Total int64
Sort string
// privates
lastPage bool
}
// Page for Iter.
type Page struct {
Page int
IsCurrent bool
}
// Load the page from form or query parameters.
func (p *Pagination) ParsePage(r *http.Request) {
raw := r.FormValue("page")
a, err := strconv.Atoi(raw)
if err == nil {
if a <= 0 {
p.lastPage = true
a = 1
}
p.Page = a
} else {
p.Page = 1
}
}
// Iter the pages, for templates.
func (p *Pagination) Iter() []Page {
var (
pages = []Page{}
pageIdx int
total = p.Pages()
)
for i := 1; i <= total; i++ {
pages = append(pages, Page{
Page: i,
IsCurrent: i == p.Page,
})
if i == p.Page {
pageIdx = i
}
}
// Do we have A LOT of pages?
if len(pages) > config.PagerButtonLimit {
// We return a slide only N pages long. Where is our current page in the offset?
if pageIdx <= config.PagerButtonLimit/2 {
// We are near the front, return the first N pages.
return pages[:config.PagerButtonLimit+1]
}
// Are we near the end?
if pageIdx > len(pages)-(config.PagerButtonLimit/2) {
// We are near the end, return the last N pages.
return pages[len(pages)-config.PagerButtonLimit-1:]
}
// We are somewhere in the middle.
var result = []Page{}
for i := pageIdx - (config.PagerButtonLimit / 2) - 1; i < pageIdx+(config.PagerButtonLimit/2); i++ {
if i >= 0 && i < len(pages) {
result = append(result, pages[i])
}
}
return result
}
return pages
}
func (p Pagination) Pages() int {
if p.PerPage == 0 {
return 0
}
return int(math.Ceil(float64(p.Total) / float64(p.PerPage)))
}
func (p *Pagination) GetOffset() int {
// Are we looking for the FINAL page?
if p.lastPage && p.Pages() >= 1 {
p.Page = p.Pages()
}
return (p.Page - 1) * p.PerPage
}
func (p *Pagination) HasNext() bool {
return p.Page < p.Pages()
}
func (p *Pagination) HasPrevious() bool {
return p.Page > 1
}
func (p *Pagination) Next() int {
if p.Page >= p.Pages() {
return p.Pages()
}
return p.Page + 1
}
func (p *Pagination) Previous() int {
if p.Page > 1 {
return p.Page - 1
}
return 1
}