gpage.go 7.0 KB

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