gf/util/gpage/gpage.go

227 lines
7.0 KiB
Go
Raw Normal View History

2021-01-17 21:46:25 +08:00
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
2018-04-22 10:07:24 +08:00
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
2018-04-22 10:07:24 +08:00
2019-01-15 23:27:47 +08:00
// Package gpage provides useful paging functionality for web pages.
2018-04-22 10:07:24 +08:00
package gpage
import (
2019-06-19 09:06:52 +08:00
"fmt"
2021-11-13 23:30:31 +08:00
"math"
2021-10-11 21:41:56 +08:00
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
2018-04-22 10:07:24 +08:00
)
// Page is the pagination implementer.
2020-03-05 18:07:07 +08:00
// All the attributes are public, you can change them when necessary.
2018-04-22 10:07:24 +08:00
type Page struct {
TotalSize int // Total size.
TotalPage int // Total page, which is automatically calculated.
CurrentPage int // Current page number >= 1.
2020-03-05 18:07:07 +08:00
UrlTemplate string // Custom url template for page url producing.
LinkStyle string // CSS style name for HTML link tag `a`.
SpanStyle string // CSS style name for HTML span tag `span`, which is used for first, current and last page tag.
SelectStyle string // CSS style name for HTML select tag `select`.
NextPageTag string // Tag name for next p.
PrevPageTag string // Tag name for prev p.
FirstPageTag string // Tag name for first p.
LastPageTag string // Tag name for last p.
2020-03-05 18:07:07 +08:00
PrevBarTag string // Tag string for prev bar.
NextBarTag string // Tag string for next bar.
PageBarNum int // Page bar number for displaying.
AjaxActionName string // Ajax function name. Ajax is enabled if this attribute is not empty.
2018-04-22 10:07:24 +08:00
}
2020-03-06 11:01:03 +08:00
const (
DefaultPageName = "page" // DefaultPageName defines the default page name.
DefaultPagePlaceHolder = "{.page}" // DefaultPagePlaceHolder defines the place holder for the url template.
2020-03-06 11:01:03 +08:00
)
2020-03-05 18:07:07 +08:00
// New creates and returns a pagination manager.
// Note that the parameter `urlTemplate` specifies the URL producing template, like:
2020-03-05 18:07:07 +08:00
// /user/list/{.page}, /user/list/{.page}.html, /user/list?page={.page}&type=1, etc.
// The build-in variable in `urlTemplate` "{.page}" specifies the page number, which will be replaced by certain
2020-03-05 18:07:07 +08:00
// page number when producing.
func New(totalSize, pageSize, currentPage int, urlTemplate string) *Page {
p := &Page{
2020-03-05 18:07:07 +08:00
LinkStyle: "GPageLink",
SpanStyle: "GPageSpan",
SelectStyle: "GPageSelect",
2019-06-19 09:06:52 +08:00
PrevPageTag: "<",
NextPageTag: ">",
FirstPageTag: "|<",
LastPageTag: ">|",
2020-03-05 18:07:07 +08:00
PrevBarTag: "<<",
NextBarTag: ">>",
TotalSize: totalSize,
TotalPage: int(math.Ceil(float64(totalSize) / float64(pageSize))),
2020-03-05 18:07:07 +08:00
CurrentPage: currentPage,
2019-06-19 09:06:52 +08:00
PageBarNum: 10,
UrlTemplate: urlTemplate,
2019-06-19 09:06:52 +08:00
}
2020-03-05 18:07:07 +08:00
if currentPage == 0 {
p.CurrentPage = 1
2019-06-19 09:06:52 +08:00
}
return p
}
2020-03-05 18:07:07 +08:00
// NextPage returns the HTML content for the next page.
func (p *Page) NextPage() string {
if p.CurrentPage < p.TotalPage {
2020-03-05 18:07:07 +08:00
return p.GetLink(p.CurrentPage+1, p.NextPageTag, "")
2019-06-19 09:06:52 +08:00
}
2020-03-05 18:07:07 +08:00
return fmt.Sprintf(`<span class="%s">%s</span>`, p.SpanStyle, p.NextPageTag)
2018-04-22 10:07:24 +08:00
}
2020-03-05 18:07:07 +08:00
// PrevPage returns the HTML content for the previous page.
func (p *Page) PrevPage() string {
if p.CurrentPage > 1 {
2020-03-05 18:07:07 +08:00
return p.GetLink(p.CurrentPage-1, p.PrevPageTag, "")
2019-06-19 09:06:52 +08:00
}
2020-03-05 18:07:07 +08:00
return fmt.Sprintf(`<span class="%s">%s</span>`, p.SpanStyle, p.PrevPageTag)
2018-04-22 10:07:24 +08:00
}
2020-03-05 18:07:07 +08:00
// FirstPage returns the HTML content for the first page.
func (p *Page) FirstPage() string {
if p.CurrentPage == 1 {
2020-03-05 18:07:07 +08:00
return fmt.Sprintf(`<span class="%s">%s</span>`, p.SpanStyle, p.FirstPageTag)
2019-06-19 09:06:52 +08:00
}
2020-03-05 18:07:07 +08:00
return p.GetLink(1, p.FirstPageTag, "")
2018-04-22 11:26:19 +08:00
}
2020-03-05 18:07:07 +08:00
// LastPage returns the HTML content for the last page.
func (p *Page) LastPage() string {
if p.CurrentPage == p.TotalPage {
2020-03-05 18:07:07 +08:00
return fmt.Sprintf(`<span class="%s">%s</span>`, p.SpanStyle, p.LastPageTag)
2019-06-19 09:06:52 +08:00
}
2020-03-05 18:07:07 +08:00
return p.GetLink(p.TotalPage, p.LastPageTag, "")
2018-04-22 11:26:19 +08:00
}
2020-03-05 18:07:07 +08:00
// PageBar returns the HTML page bar content with link and span tags.
func (p *Page) PageBar() string {
plus := int(math.Ceil(float64(p.PageBarNum / 2)))
if p.PageBarNum-plus+p.CurrentPage > p.TotalPage {
plus = p.PageBarNum - p.TotalPage + p.CurrentPage
2019-06-19 09:06:52 +08:00
}
begin := p.CurrentPage - plus + 1
2019-06-19 09:06:52 +08:00
if begin < 1 {
begin = 1
}
2020-03-05 18:07:07 +08:00
barContent := ""
for i := begin; i < begin+p.PageBarNum; i++ {
if i <= p.TotalPage {
if i != p.CurrentPage {
2020-03-05 18:07:07 +08:00
barText := gconv.String(i)
barContent += p.GetLink(i, barText, barText)
2019-06-19 09:06:52 +08:00
} else {
2020-03-05 18:07:07 +08:00
barContent += fmt.Sprintf(`<span class="%s">%d</span>`, p.SpanStyle, i)
2019-06-19 09:06:52 +08:00
}
} else {
break
}
}
2020-03-05 18:07:07 +08:00
return barContent
2018-04-22 10:07:24 +08:00
}
2019-06-19 09:06:52 +08:00
2020-03-05 18:07:07 +08:00
// SelectBar returns the select HTML content for pagination.
func (p *Page) SelectBar() string {
2020-03-05 18:07:07 +08:00
barContent := fmt.Sprintf(`<select name="%s" onchange="window.location.href=this.value">`, p.SelectStyle)
for i := 1; i <= p.TotalPage; i++ {
if i == p.CurrentPage {
2020-03-05 18:07:07 +08:00
barContent += fmt.Sprintf(`<option value="%s" selected>%d</option>`, p.GetUrl(i), i)
2019-06-19 09:06:52 +08:00
} else {
2020-03-05 18:07:07 +08:00
barContent += fmt.Sprintf(`<option value="%s">%d</option>`, p.GetUrl(i), i)
2019-06-19 09:06:52 +08:00
}
}
2020-03-05 18:07:07 +08:00
barContent += "</select>"
return barContent
2018-04-22 10:07:24 +08:00
}
2020-03-05 18:07:07 +08:00
// GetContent returns the page content for predefined mode.
// These predefined contents are mainly for chinese localization purpose. You can defines your own
// page function retrieving the page content according to the implementation of this function.
func (p *Page) GetContent(mode int) string {
2019-06-19 09:06:52 +08:00
switch mode {
case 1:
p.NextPageTag = "下一页"
p.PrevPageTag = "上一页"
2019-06-19 09:06:52 +08:00
return fmt.Sprintf(
`%s <span class="current">%d</span> %s`,
p.PrevPage(),
p.CurrentPage,
p.NextPage(),
2019-06-19 09:06:52 +08:00
)
2019-06-19 09:06:52 +08:00
case 2:
p.NextPageTag = "下一页>>"
p.PrevPageTag = "<<上一页"
p.FirstPageTag = "首页"
p.LastPageTag = "尾页"
2019-06-19 09:06:52 +08:00
return fmt.Sprintf(
`%s%s<span class="current">[第%d页]</span>%s%s第%s页`,
p.FirstPage(),
p.PrevPage(),
p.CurrentPage,
p.NextPage(),
p.LastPage(),
p.SelectBar(),
2019-06-19 09:06:52 +08:00
)
2019-06-19 09:06:52 +08:00
case 3:
p.NextPageTag = "下一页"
p.PrevPageTag = "上一页"
p.FirstPageTag = "首页"
p.LastPageTag = "尾页"
pageStr := p.FirstPage()
pageStr += p.PrevPage()
2020-03-05 18:07:07 +08:00
pageStr += p.PageBar()
pageStr += p.NextPage()
pageStr += p.LastPage()
2019-06-19 09:06:52 +08:00
pageStr += fmt.Sprintf(
`<span>当前页%d/%d</span> <span>共%d条</span>`,
p.CurrentPage,
p.TotalPage,
p.TotalSize,
2019-06-19 09:06:52 +08:00
)
return pageStr
2019-06-19 09:06:52 +08:00
case 4:
p.NextPageTag = "下一页"
p.PrevPageTag = "上一页"
p.FirstPageTag = "首页"
p.LastPageTag = "尾页"
pageStr := p.FirstPage()
pageStr += p.PrevPage()
2020-03-05 18:07:07 +08:00
pageStr += p.PageBar()
pageStr += p.NextPage()
pageStr += p.LastPage()
2019-06-19 09:06:52 +08:00
return pageStr
}
return ""
2018-04-22 11:26:19 +08:00
}
2020-03-05 18:07:07 +08:00
// GetUrl parses the UrlTemplate with given page number and returns the URL string.
// Note that the UrlTemplate attribute can be either an URL or an URI string with "{.page}"
2020-03-05 18:07:07 +08:00
// place holder specifying the page number position.
func (p *Page) GetUrl(page int) string {
return gstr.Replace(p.UrlTemplate, DefaultPagePlaceHolder, gconv.String(page))
2018-08-06 22:38:55 +08:00
}
// GetLink returns the HTML link tag `a` content for given page number.
2020-03-05 18:07:07 +08:00
func (p *Page) GetLink(page int, text, title string) string {
if len(p.AjaxActionName) > 0 {
2020-03-05 18:07:07 +08:00
return fmt.Sprintf(
`<a class="%s" href="javascript:%s('%s')" title="%s">%s</a>`,
p.LinkStyle, p.AjaxActionName, p.GetUrl(page), title, text,
)
2019-06-19 09:06:52 +08:00
} else {
2020-03-05 18:07:07 +08:00
return fmt.Sprintf(
`<a class="%s" href="%s" title="%s">%s</a>`,
p.LinkStyle, p.GetUrl(page), title, text,
)
2019-06-19 09:06:52 +08:00
}
2018-04-22 10:07:24 +08:00
}