diff --git a/components/navigation/events.go b/components/navigation/events.go index 72a1ab5..db5b6c9 100644 --- a/components/navigation/events.go +++ b/components/navigation/events.go @@ -2,22 +2,22 @@ package navigation import "github.com/vugu/vugu" -type PaginationEvent struct { +type PaginateEvent struct { vugu.DOMEvent - Page int + PaginationInfo // The current state of the pagination component. } // PaginationHandler is the interface for things that can handle PaginationEvent. -type PaginationHandler interface { - PaginationHandle(event PaginationEvent) +type PaginateHandler interface { + PaginateHandle(event PaginateEvent) } -// PaginationFunc implements PaginationHandler as a function. -type PaginationFunc func(event PaginationEvent) +// PaginateFunc implements PaginateHandler as a function. +type PaginateFunc func(event PaginateEvent) -// PaginationHandle implements the PaginationHandler interface. -func (f PaginationFunc) PaginationHandle(event PaginationEvent) { f(event) } +// PaginateHandle implements the PaginateHandler interface. +func (f PaginateFunc) PaginateHandle(event PaginateEvent) { f(event) } -// assert PaginationFunc implements PaginationHandler. -var _ PaginationHandler = PaginationFunc(nil) +// assert PaginateFunc implements PaginateHandler. +var _ PaginateHandler = PaginateFunc(nil) diff --git a/components/navigation/pagination-binder.go b/components/navigation/pagination-binder.go new file mode 100644 index 0000000..0127637 --- /dev/null +++ b/components/navigation/pagination-binder.go @@ -0,0 +1,26 @@ +package navigation + +// PaginationBinder is an interface that everything that every type that wants to bind to an pagination component must implement. +type PaginationBinder interface { + Page() int // Page returns the current page, as a 1-based index. A value of 0 means there is no active page. + Pages() int // Pages returns the total number of pages. + SetPage(page int) // SetPage changes the current page as a 1-based index. A value of 0 means there is no active page. +} + +// PaginationInfo implements the PaginationBinder interface and represents the current state of a pagination component. +type PaginationInfo struct { + CurrentPage int // The current page as a 1-based index. A value of 0 means there is no current page. + TotalPages int // The number of total pages. +} + +func (p *PaginationInfo) Page() int { + return p.CurrentPage +} + +func (p *PaginationInfo) Pages() int { + return p.TotalPages +} + +func (p *PaginationInfo) SetPage(page int) { + p.CurrentPage = page +} diff --git a/components/navigation/pagination.go b/components/navigation/pagination.go index 5f1919e..7a9a944 100644 --- a/components/navigation/pagination.go +++ b/components/navigation/pagination.go @@ -10,10 +10,9 @@ type Pagination struct { buttons []paginationButtonInfo - Page int `vugu:"data"` - Pages int `vugu:"data"` + Bind PaginationBinder - Pagination PaginationHandler // External handler that is called upon an event. + Paginate PaginateHandler // External handler that is called upon an event. } type paginationButtonInfo struct { @@ -21,32 +20,55 @@ type paginationButtonInfo struct { Class string } +func (c *Pagination) Page() int { + if c.Bind == nil { + return 0 + } + + return c.Bind.Page() +} + +func (c *Pagination) Pages() int { + if c.Bind == nil { + return 0 + } + + return c.Bind.Pages() +} + func (c *Pagination) handleClickPrev(event input.ClickEvent) { - c.handleClickPage(event, c.Page-1) + c.handleClickPage(event, c.Page()-1) } func (c *Pagination) handleClickNext(event input.ClickEvent) { - c.handleClickPage(event, c.Page+1) + c.handleClickPage(event, c.Page()+1) } func (c *Pagination) handleClickPage(event input.ClickEvent, page int) { - if page <= 0 || page > c.Pages { + pages := c.Pages() + + if page <= 0 || page > pages { return } - if c.Pagination != nil { - c.Pagination.PaginationHandle(PaginationEvent{ + if c.Bind != nil { + c.Bind.SetPage(page) + } + + if c.Paginate != nil { + c.Paginate.PaginateHandle(PaginateEvent{ DOMEvent: event, - Page: page, + PaginationInfo: PaginationInfo{ + CurrentPage: page, + TotalPages: pages, + }, }) } } -func (c *Pagination) Init(ctx vugu.InitCtx) { - c.Pages = 10 -} - func (c *Pagination) Compute(ctx vugu.ComputeCtx) { + page, pages := c.Page(), c.Pages() + // Number of buttons around the current page. // Excluding first and last page. const AroundButtons = 2 @@ -60,15 +82,15 @@ func (c *Pagination) Compute(ctx vugu.ComputeCtx) { // Prepare buttons. buttons := [TotalButtons]paginationButtonInfo{ 0: {Page: 1}, - TotalButtons - 1: {Page: c.Pages}, + TotalButtons - 1: {Page: pages}, } startPage := 2 - if startPage < c.Page-AroundButtons { - startPage = c.Page - AroundButtons + if startPage < page-AroundButtons { + startPage = page - AroundButtons } - if startPage > c.Pages-DynamicButtons { - startPage = c.Pages - DynamicButtons + if startPage > pages-DynamicButtons { + startPage = pages - DynamicButtons } for i := 0; i < DynamicButtons; i++ { @@ -79,13 +101,13 @@ func (c *Pagination) Compute(ctx vugu.ComputeCtx) { // pageCounter is used to check if pages are strictly monotonically increasing. buttonsFiltered := make([]paginationButtonInfo, 0, len(buttons)) pageCounter := 0 - for _, page := range buttons { - if pageCounter < page.Page && page.Page <= c.Pages { - pageCounter = page.Page - if page.Page == c.Page { - page.Class = "d3c-button-highlight" + for _, pageInfo := range buttons { + if pageCounter < pageInfo.Page && pageInfo.Page <= pages { + pageCounter = pageInfo.Page + if pageInfo.Page == page { + pageInfo.Class = "d3c-button-highlight" } - buttonsFiltered = append(buttonsFiltered, page) + buttonsFiltered = append(buttonsFiltered, pageInfo) } } diff --git a/page-layout.go b/page-layout.go index 9aff8d2..c273a95 100644 --- a/page-layout.go +++ b/page-layout.go @@ -8,15 +8,14 @@ import ( ) type PageLayout struct { - Page int `vugu:"data"` - Pages int `vugu:"data"` + Pagination navigation.PaginationInfo `vugu:"data"` } func (c *PageLayout) Init(ctx vugu.InitCtx) { - c.Pages = 10 + c.Pagination.CurrentPage = 2 + c.Pagination.TotalPages = 10 } -func (c *PageLayout) handlePagination(event navigation.PaginationEvent) { - log.Printf("Some page %v", event.Page) - c.Page = event.Page +func (c *PageLayout) handlePagination(event navigation.PaginateEvent) { + log.Printf("Current pagination info: %v", event.PaginationInfo) } diff --git a/page-layout.vugu b/page-layout.vugu index 5ba6e66..aa4f422 100644 --- a/page-layout.vugu +++ b/page-layout.vugu @@ -3,7 +3,7 @@

Layout

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.

Items

- + diff --git a/page-layout_vgen.go b/page-layout_vgen.go index c976511..64fa9ed 100644 --- a/page-layout_vgen.go +++ b/page-layout_vgen.go @@ -28,7 +28,7 @@ func (c *PageLayout) Build(vgin *vugu.BuildIn) (vgout *vugu.BuildOut) { vgn = &vugu.VGNode{Type: vugu.VGNodeType(1), Data: "\n\t"} vgparent.AppendChild(vgn) { - vgcompKey := vugu.MakeCompKey(0x3467920B61750485^vgin.CurrentPositionHash(), vgiterkey) + vgcompKey := vugu.MakeCompKey(0x60B66E06F722C68^vgin.CurrentPositionHash(), vgiterkey) // ask BuildEnv for prior instance of this specific component vgcomp, _ := vgin.BuildEnv.CachedComponent(vgcompKey).(*layout.Container) if vgcomp == nil { @@ -62,7 +62,7 @@ func (c *PageLayout) Build(vgin *vugu.BuildIn) (vgout *vugu.BuildOut) { vgn = &vugu.VGNode{Type: vugu.VGNodeType(1), Data: "\n\t\t"} vgparent.AppendChild(vgn) { - vgcompKey := vugu.MakeCompKey(0x6A61FD21D9782C05^vgin.CurrentPositionHash(), vgiterkey) + vgcompKey := vugu.MakeCompKey(0xD22F5BB58705C5DF^vgin.CurrentPositionHash(), vgiterkey) // ask BuildEnv for prior instance of this specific component vgcomp, _ := vgin.BuildEnv.CachedComponent(vgcompKey).(*navigation.Pagination) if vgcomp == nil { @@ -71,9 +71,8 @@ func (c *PageLayout) Build(vgin *vugu.BuildIn) (vgout *vugu.BuildOut) { vgin.BuildEnv.WireComponent(vgcomp) } vgin.BuildEnv.UseComponent(vgcompKey, vgcomp) // ensure we can use this in the cache next time around - vgcomp.Page = c.Page - vgcomp.Pages = c.Pages - vgcomp.Pagination = navigation.PaginationFunc(func(event navigation.PaginationEvent) { c.handlePagination(event) }) + vgcomp.Bind = &c.Pagination + vgcomp.Paginate = navigation.PaginateFunc(func(event navigation.PaginateEvent) { c.handlePagination(event) }) vgout.Components = append(vgout.Components, vgcomp) vgn = &vugu.VGNode{Component: vgcomp} vgparent.AppendChild(vgn) @@ -81,7 +80,7 @@ func (c *PageLayout) Build(vgin *vugu.BuildIn) (vgout *vugu.BuildOut) { vgn = &vugu.VGNode{Type: vugu.VGNodeType(1), Data: "\n\t\t"} vgparent.AppendChild(vgn) { - vgcompKey := vugu.MakeCompKey(0xD67C1752436E9AB1^vgin.CurrentPositionHash(), vgiterkey) + vgcompKey := vugu.MakeCompKey(0xE6379FC706A49E07^vgin.CurrentPositionHash(), vgiterkey) // ask BuildEnv for prior instance of this specific component vgcomp, _ := vgin.BuildEnv.CachedComponent(vgcompKey).(*ComponentAddress) if vgcomp == nil {