a760e46f by astaxie

Merge pull request #837 from bsingr/develop

Insert pagination utilities from beego/wetalk. Refs #835.
2 parents c147f26c 262665f4
1 // Copyright 2014 beego Author. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 package pagination
16
17 import (
18 "github.com/astaxie/beego/context"
19 )
20
21 // Instantiates a Paginator and assigns it to context.Input.Data["paginator"].
22 func SetPaginator(context *context.Context, per int, nums int64) (paginator *Paginator) {
23 paginator = NewPaginator(context.Request, per, nums)
24 context.Input.Data["paginator"] = paginator
25 return
26 }
1 /*
2
3 The pagination package provides utilities to setup a paginator within the
4 context of a http request.
5
6 Usage
7
8 In your beego.Controller:
9
10 package controllers
11
12 import "github.com/astaxie/beego/utils/pagination"
13
14 type PostsController struct {
15 beego.Controller
16 }
17
18 func (this *PostsController) ListAllPosts() {
19 // sets this.Data["paginator"] with the current offset (from the url query param)
20 postsPerPage := 20
21 paginator := pagination.SetPaginator(this.Ctx, postsPerPage, CountPosts())
22
23 // fetch the next 20 posts
24 this.Data["posts"] = ListPostsByOffsetAndLimit(paginator.Offset(), postsPerPage)
25 }
26
27
28 In your view templates:
29
30 {{if .paginator.HasPages}}
31 <ul class="pagination pagination">
32 {{if .paginator.HasPrev}}
33 <li><a href="{{.paginator.PageLinkFirst}}">{{ i18n .Lang "paginator.first_page"}}</a></li>
34 <li><a href="{{.paginator.PageLinkPrev}}">&laquo;</a></li>
35 {{else}}
36 <li class="disabled"><a>{{ i18n .Lang "paginator.first_page"}}</a></li>
37 <li class="disabled"><a>&laquo;</a></li>
38 {{end}}
39 {{range $index, $page := .paginator.Pages}}
40 <li{{if $.paginator.IsActive .}} class="active"{{end}}>
41 <a href="{{$.paginator.PageLink $page}}">{{$page}}</a>
42 </li>
43 {{end}}
44 {{if .paginator.HasNext}}
45 <li><a href="{{.paginator.PageLinkNext}}">&raquo;</a></li>
46 <li><a href="{{.paginator.PageLinkLast}}">{{ i18n .Lang "paginator.last_page"}}</a></li>
47 {{else}}
48 <li class="disabled"><a>&raquo;</a></li>
49 <li class="disabled"><a>{{ i18n .Lang "paginator.last_page"}}</a></li>
50 {{end}}
51 </ul>
52 {{end}}
53
54 See also
55
56 http://beego.me/docs/mvc/view/page.md
57
58 */
59 package pagination
1 // Copyright 2014 beego Author. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 package pagination
16
17 import (
18 "math"
19 "net/http"
20 "net/url"
21 "strconv"
22 )
23
24 // Paginator within the state of a http request.
25 type Paginator struct {
26 Request *http.Request
27 PerPageNums int
28 MaxPages int
29
30 nums int64
31 pageRange []int
32 pageNums int
33 page int
34 }
35
36 // Returns the total number of pages.
37 func (p *Paginator) PageNums() int {
38 if p.pageNums != 0 {
39 return p.pageNums
40 }
41 pageNums := math.Ceil(float64(p.nums) / float64(p.PerPageNums))
42 if p.MaxPages > 0 {
43 pageNums = math.Min(pageNums, float64(p.MaxPages))
44 }
45 p.pageNums = int(pageNums)
46 return p.pageNums
47 }
48
49 // Returns the total number of items (e.g. from doing SQL count).
50 func (p *Paginator) Nums() int64 {
51 return p.nums
52 }
53
54 // Sets the total number of items.
55 func (p *Paginator) SetNums(nums interface{}) {
56 p.nums, _ = ToInt64(nums)
57 }
58
59 // Returns the current page.
60 func (p *Paginator) Page() int {
61 if p.page != 0 {
62 return p.page
63 }
64 if p.Request.Form == nil {
65 p.Request.ParseForm()
66 }
67 p.page, _ = strconv.Atoi(p.Request.Form.Get("p"))
68 if p.page > p.PageNums() {
69 p.page = p.PageNums()
70 }
71 if p.page <= 0 {
72 p.page = 1
73 }
74 return p.page
75 }
76
77 // Returns a list of all pages.
78 //
79 // Usage (in a view template):
80 //
81 // {{range $index, $page := .paginator.Pages}}
82 // <li{{if $.paginator.IsActive .}} class="active"{{end}}>
83 // <a href="{{$.paginator.PageLink $page}}">{{$page}}</a>
84 // </li>
85 // {{end}}
86 func (p *Paginator) Pages() []int {
87 if p.pageRange == nil && p.nums > 0 {
88 var pages []int
89 pageNums := p.PageNums()
90 page := p.Page()
91 switch {
92 case page >= pageNums-4 && pageNums > 9:
93 start := pageNums - 9 + 1
94 pages = make([]int, 9)
95 for i, _ := range pages {
96 pages[i] = start + i
97 }
98 case page >= 5 && pageNums > 9:
99 start := page - 5 + 1
100 pages = make([]int, int(math.Min(9, float64(page+4+1))))
101 for i, _ := range pages {
102 pages[i] = start + i
103 }
104 default:
105 pages = make([]int, int(math.Min(9, float64(pageNums))))
106 for i, _ := range pages {
107 pages[i] = i + 1
108 }
109 }
110 p.pageRange = pages
111 }
112 return p.pageRange
113 }
114
115 // Returns URL for a given page index.
116 func (p *Paginator) PageLink(page int) string {
117 link, _ := url.ParseRequestURI(p.Request.RequestURI)
118 values := link.Query()
119 if page == 1 {
120 values.Del("p")
121 } else {
122 values.Set("p", strconv.Itoa(page))
123 }
124 link.RawQuery = values.Encode()
125 return link.String()
126 }
127
128 // Returns URL to the previous page.
129 func (p *Paginator) PageLinkPrev() (link string) {
130 if p.HasPrev() {
131 link = p.PageLink(p.Page() - 1)
132 }
133 return
134 }
135
136 // Returns URL to the next page.
137 func (p *Paginator) PageLinkNext() (link string) {
138 if p.HasNext() {
139 link = p.PageLink(p.Page() + 1)
140 }
141 return
142 }
143
144 // Returns URL to the first page.
145 func (p *Paginator) PageLinkFirst() (link string) {
146 return p.PageLink(1)
147 }
148
149 // Returns URL to the last page.
150 func (p *Paginator) PageLinkLast() (link string) {
151 return p.PageLink(p.PageNums())
152 }
153
154 // Returns true if the current page has a predecessor.
155 func (p *Paginator) HasPrev() bool {
156 return p.Page() > 1
157 }
158
159 // Returns true if the current page has a successor.
160 func (p *Paginator) HasNext() bool {
161 return p.Page() < p.PageNums()
162 }
163
164 // Returns true if the given page index points to the current page.
165 func (p *Paginator) IsActive(page int) bool {
166 return p.Page() == page
167 }
168
169 // Returns the current offset.
170 func (p *Paginator) Offset() int {
171 return (p.Page() - 1) * p.PerPageNums
172 }
173
174 // Returns true if there is more than one page.
175 func (p *Paginator) HasPages() bool {
176 return p.PageNums() > 1
177 }
178
179 // Instantiates a paginator struct for the current http request.
180 func NewPaginator(req *http.Request, per int, nums interface{}) *Paginator {
181 p := Paginator{}
182 p.Request = req
183 if per <= 0 {
184 per = 10
185 }
186 p.PerPageNums = per
187 p.SetNums(nums)
188 return &p
189 }
1 // Copyright 2014 beego Author. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 package pagination
16
17 import (
18 "fmt"
19 "reflect"
20 )
21
22 // convert any numeric value to int64
23 func ToInt64(value interface{}) (d int64, err error) {
24 val := reflect.ValueOf(value)
25 switch value.(type) {
26 case int, int8, int16, int32, int64:
27 d = val.Int()
28 case uint, uint8, uint16, uint32, uint64:
29 d = int64(val.Uint())
30 default:
31 err = fmt.Errorf("ToInt64 need numeric not `%T`", value)
32 }
33 return
34 }
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!