-
Notifications
You must be signed in to change notification settings - Fork 0
/
gpage.go
226 lines (208 loc) · 6.98 KB
/
gpage.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// 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.
// Package gpage provides useful paging functionality for web pages.
package gpage
import (
"fmt"
"math"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
)
// Page is the pagination implementer.
// All the attributes are public, you can change them when necessary.
type Page struct {
TotalSize int // Total size.
TotalPage int // Total page, which is automatically calculated.
CurrentPage int // Current page number >= 1.
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.
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.
}
const (
DefaultPageName = "page" // DefaultPageName defines the default page name.
DefaultPagePlaceHolder = "{.page}" // DefaultPagePlaceHolder defines the place holder for the url template.
)
// New creates and returns a pagination manager.
// Note that the parameter `urlTemplate` specifies the URL producing template, like:
// /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
// page number when producing.
func New(totalSize, pageSize, currentPage int, urlTemplate string) *Page {
p := &Page{
LinkStyle: "GPageLink",
SpanStyle: "GPageSpan",
SelectStyle: "GPageSelect",
PrevPageTag: "<",
NextPageTag: ">",
FirstPageTag: "|<",
LastPageTag: ">|",
PrevBarTag: "<<",
NextBarTag: ">>",
TotalSize: totalSize,
TotalPage: int(math.Ceil(float64(totalSize) / float64(pageSize))),
CurrentPage: currentPage,
PageBarNum: 10,
UrlTemplate: urlTemplate,
}
if currentPage == 0 {
p.CurrentPage = 1
}
return p
}
// NextPage returns the HTML content for the next page.
func (p *Page) NextPage() string {
if p.CurrentPage < p.TotalPage {
return p.GetLink(p.CurrentPage+1, p.NextPageTag, "")
}
return fmt.Sprintf(`<span class="%s">%s</span>`, p.SpanStyle, p.NextPageTag)
}
// PrevPage returns the HTML content for the previous page.
func (p *Page) PrevPage() string {
if p.CurrentPage > 1 {
return p.GetLink(p.CurrentPage-1, p.PrevPageTag, "")
}
return fmt.Sprintf(`<span class="%s">%s</span>`, p.SpanStyle, p.PrevPageTag)
}
// FirstPage returns the HTML content for the first page.
func (p *Page) FirstPage() string {
if p.CurrentPage == 1 {
return fmt.Sprintf(`<span class="%s">%s</span>`, p.SpanStyle, p.FirstPageTag)
}
return p.GetLink(1, p.FirstPageTag, "")
}
// LastPage returns the HTML content for the last page.
func (p *Page) LastPage() string {
if p.CurrentPage == p.TotalPage {
return fmt.Sprintf(`<span class="%s">%s</span>`, p.SpanStyle, p.LastPageTag)
}
return p.GetLink(p.TotalPage, p.LastPageTag, "")
}
// 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
}
begin := p.CurrentPage - plus + 1
if begin < 1 {
begin = 1
}
barContent := ""
for i := begin; i < begin+p.PageBarNum; i++ {
if i <= p.TotalPage {
if i != p.CurrentPage {
barText := gconv.String(i)
barContent += p.GetLink(i, barText, barText)
} else {
barContent += fmt.Sprintf(`<span class="%s">%d</span>`, p.SpanStyle, i)
}
} else {
break
}
}
return barContent
}
// SelectBar returns the select HTML content for pagination.
func (p *Page) SelectBar() string {
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 {
barContent += fmt.Sprintf(`<option value="%s" selected>%d</option>`, p.GetUrl(i), i)
} else {
barContent += fmt.Sprintf(`<option value="%s">%d</option>`, p.GetUrl(i), i)
}
}
barContent += "</select>"
return barContent
}
// 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 {
switch mode {
case 1:
p.NextPageTag = "下一页"
p.PrevPageTag = "上一页"
return fmt.Sprintf(
`%s <span class="current">%d</span> %s`,
p.PrevPage(),
p.CurrentPage,
p.NextPage(),
)
case 2:
p.NextPageTag = "下一页>>"
p.PrevPageTag = "<<上一页"
p.FirstPageTag = "首页"
p.LastPageTag = "尾页"
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(),
)
case 3:
p.NextPageTag = "下一页"
p.PrevPageTag = "上一页"
p.FirstPageTag = "首页"
p.LastPageTag = "尾页"
pageStr := p.FirstPage()
pageStr += p.PrevPage()
pageStr += p.PageBar()
pageStr += p.NextPage()
pageStr += p.LastPage()
pageStr += fmt.Sprintf(
`<span>当前页%d/%d</span> <span>共%d条</span>`,
p.CurrentPage,
p.TotalPage,
p.TotalSize,
)
return pageStr
case 4:
p.NextPageTag = "下一页"
p.PrevPageTag = "上一页"
p.FirstPageTag = "首页"
p.LastPageTag = "尾页"
pageStr := p.FirstPage()
pageStr += p.PrevPage()
pageStr += p.PageBar()
pageStr += p.NextPage()
pageStr += p.LastPage()
return pageStr
}
return ""
}
// 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}"
// place holder specifying the page number position.
func (p *Page) GetUrl(page int) string {
return gstr.Replace(p.UrlTemplate, DefaultPagePlaceHolder, gconv.String(page))
}
// GetLink returns the HTML link tag `a` content for given page number.
func (p *Page) GetLink(page int, text, title string) string {
if len(p.AjaxActionName) > 0 {
return fmt.Sprintf(
`<a class="%s" href="javascript:%s('%s')" title="%s">%s</a>`,
p.LinkStyle, p.AjaxActionName, p.GetUrl(page), title, text,
)
} else {
return fmt.Sprintf(
`<a class="%s" href="%s" title="%s">%s</a>`,
p.LinkStyle, p.GetUrl(page), title, text,
)
}
}