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