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  }