123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- // Copyright 2014 beego Author. All Rights Reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package pagination
- import (
- "math"
- "net/http"
- "net/url"
- "strconv"
- )
- // Paginator within the state of a http request.
- type Paginator struct {
- Request *http.Request
- PerPageNums int
- MaxPages int
- nums int64
- pageRange []int
- pageNums int
- page int
- }
- // PageNums Returns the total number of pages.
- func (p *Paginator) PageNums() int {
- if p.pageNums != 0 {
- return p.pageNums
- }
- pageNums := math.Ceil(float64(p.nums) / float64(p.PerPageNums))
- if p.MaxPages > 0 {
- pageNums = math.Min(pageNums, float64(p.MaxPages))
- }
- p.pageNums = int(pageNums)
- return p.pageNums
- }
- // Nums Returns the total number of items (e.g. from doing SQL count).
- func (p *Paginator) Nums() int64 {
- return p.nums
- }
- // SetNums Sets the total number of items.
- func (p *Paginator) SetNums(nums interface{}) {
- p.nums, _ = toInt64(nums)
- }
- // Page Returns the current page.
- func (p *Paginator) Page() int {
- if p.page != 0 {
- return p.page
- }
- if p.Request.Form == nil {
- p.Request.ParseForm()
- }
- p.page, _ = strconv.Atoi(p.Request.Form.Get("p"))
- if p.page > p.PageNums() {
- p.page = p.PageNums()
- }
- if p.page <= 0 {
- p.page = 1
- }
- return p.page
- }
- // Pages Returns a list of all pages.
- //
- // Usage (in a view template):
- //
- // {{range $index, $page := .paginator.Pages}}
- // <li{{if $.paginator.IsActive .}} class="active"{{end}}>
- // <a href="{{$.paginator.PageLink $page}}">{{$page}}</a>
- // </li>
- // {{end}}
- func (p *Paginator) Pages() []int {
- if p.pageRange == nil && p.nums > 0 {
- var pages []int
- pageNums := p.PageNums()
- page := p.Page()
- switch {
- case page >= pageNums-4 && pageNums > 9:
- start := pageNums - 9 + 1
- pages = make([]int, 9)
- for i := range pages {
- pages[i] = start + i
- }
- case page >= 5 && pageNums > 9:
- start := page - 5 + 1
- pages = make([]int, int(math.Min(9, float64(page+4+1))))
- for i := range pages {
- pages[i] = start + i
- }
- default:
- pages = make([]int, int(math.Min(9, float64(pageNums))))
- for i := range pages {
- pages[i] = i + 1
- }
- }
- p.pageRange = pages
- }
- return p.pageRange
- }
- // PageLink Returns URL for a given page index.
- func (p *Paginator) PageLink(page int) string {
- link, _ := url.ParseRequestURI(p.Request.URL.String())
- values := link.Query()
- if page == 1 {
- values.Del("p")
- } else {
- values.Set("p", strconv.Itoa(page))
- }
- link.RawQuery = values.Encode()
- return link.String()
- }
- // PageLinkPrev Returns URL to the previous page.
- func (p *Paginator) PageLinkPrev() (link string) {
- if p.HasPrev() {
- link = p.PageLink(p.Page() - 1)
- }
- return
- }
- // PageLinkNext Returns URL to the next page.
- func (p *Paginator) PageLinkNext() (link string) {
- if p.HasNext() {
- link = p.PageLink(p.Page() + 1)
- }
- return
- }
- // PageLinkFirst Returns URL to the first page.
- func (p *Paginator) PageLinkFirst() (link string) {
- return p.PageLink(1)
- }
- // PageLinkLast Returns URL to the last page.
- func (p *Paginator) PageLinkLast() (link string) {
- return p.PageLink(p.PageNums())
- }
- // HasPrev Returns true if the current page has a predecessor.
- func (p *Paginator) HasPrev() bool {
- return p.Page() > 1
- }
- // HasNext Returns true if the current page has a successor.
- func (p *Paginator) HasNext() bool {
- return p.Page() < p.PageNums()
- }
- // IsActive Returns true if the given page index points to the current page.
- func (p *Paginator) IsActive(page int) bool {
- return p.Page() == page
- }
- // Offset Returns the current offset.
- func (p *Paginator) Offset() int {
- return (p.Page() - 1) * p.PerPageNums
- }
- // HasPages Returns true if there is more than one page.
- func (p *Paginator) HasPages() bool {
- return p.PageNums() > 1
- }
- // NewPaginator Instantiates a paginator struct for the current http request.
- func NewPaginator(req *http.Request, per int, nums interface{}) *Paginator {
- p := Paginator{}
- p.Request = req
- if per <= 0 {
- per = 10
- }
- p.PerPageNums = per
- p.SetNums(nums)
- return &p
- }
|