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