-
Notifications
You must be signed in to change notification settings - Fork 6
/
data_pager.go
207 lines (174 loc) · 6.09 KB
/
data_pager.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
package control
import (
"context"
"fmt"
"github.com/goradd/goradd/pkg/page"
"github.com/goradd/goradd/pkg/page/control"
"github.com/goradd/html5tag"
"strconv"
)
type DataPagerI interface {
control.DataPagerI
}
// DataPager is a toolbar designed to aid scrolling through a large set of data. It is implemented using Aria design
// best practices. It is designed to be paired with a Table or DataRepeater to aid in navigating through the data.
// It is similar to a Paginator, but a paginator is for navigating through a whole series of pages and not just for
// data on one override.
type DataPager struct {
control.DataPager
ButtonStyle ButtonStyle
HighlightStyle ButtonStyle
}
func NewDataPager(parent page.ControlI, id string, pagedControl control.PagedControlI) *DataPager {
d := new(DataPager)
d.Self = d
d.Init(parent, id, pagedControl)
return d
}
func (d *DataPager) Init(parent page.ControlI, id string, pagedControl control.PagedControlI) {
d.DataPager.Init(parent, id, pagedControl)
d.SetLabels(`<span aria-hidden="true">«</span><span class="visually-hidden">Previous</span>`,
`<span aria-hidden="true">»</span> <span class="visually-hidden">Next</span>`)
d.ButtonStyle = ButtonStyleOutlineSecondary
d.HighlightStyle = ButtonStylePrimary
d.SetAttribute("aria-label", "Data pager")
}
func (d *DataPager) this() DataPagerI {
return d.Self.(DataPagerI)
}
func (d *DataPager) DrawingAttributes(ctx context.Context) html5tag.Attributes {
a := d.DataPager.DrawingAttributes(ctx)
a.AddClass("btn-group")
return a
}
func (d *DataPager) PreviousButtonsHtml() string {
var prev string
var actionValue string
pageNum := d.PagedControl().PageNum()
actionValue = strconv.Itoa(pageNum - 1)
attr := html5tag.NewAttributes().
Set("id", d.ID()+"_arrow_"+actionValue).
SetClass("btn " + string(d.ButtonStyle))
if pageNum <= 1 {
attr.SetDisabled(true)
attr.SetStyle("cursor", "not-allowed")
}
prev = d.ButtonProxy().ButtonHtml(d.LabelForPrevious, actionValue, attr, true)
h := prev
pageStart, _ := d.CalcBunch()
if pageStart != 1 {
h += d.PageButtonsHtml(1)
h += fmt.Sprintf(`<button disabled class="btn %s" style="cursor: not-allowed">…</button>`, d.ButtonStyle)
}
return h
}
func (d *DataPager) NextButtonsHtml() string {
var next string
var actionValue string
pageNum := d.PagedControl().PageNum()
actionValue = strconv.Itoa(pageNum + 1)
attr := html5tag.NewAttributes().
Set("id", d.ID()+"_arrow_"+actionValue).
SetClass("btn " + string(d.ButtonStyle))
_, pageEnd := d.CalcBunch()
pageCount := d.PagedControl().CalcPageCount()
if pageNum >= pageCount {
attr.SetDisabled(true)
attr.SetStyle("cursor", "not-allowed")
}
next = d.ButtonProxy().ButtonHtml(d.LabelForNext, actionValue, attr, true)
h := next
if pageEnd != pageCount {
h += d.PageButtonsHtml(pageCount) + h
h = fmt.Sprintf(`<button disabled class="btn %s" style="cursor: not-allowed">…</button>`, d.ButtonStyle) + h
}
return h
}
func (d *DataPager) PageButtonsHtml(i int) string {
pageNum := d.PagedControl().PageNum()
actionValue := strconv.Itoa(i)
attr := html5tag.NewAttributes().Set("id", d.ID()+"_page_"+actionValue).
Set("role", "tab").
AddClass("btn")
if pageNum == i {
attr.AddClass(string(d.HighlightStyle))
attr.Set("aria-selected", "true")
attr.Set("tabindex", "0")
} else {
attr.AddClass(string(d.ButtonStyle))
attr.Set("aria-selected", "false")
attr.Set("tabindex", "-1")
// TODO: We need javascript to respond to arrow keys to set the focus on the buttons. User could then press space to click on button.
}
return d.ButtonProxy().ButtonHtml(actionValue, actionValue, attr, false)
}
func (d *DataPager) Serialize(e page.Encoder) {
d.DataPager.Serialize(e)
if err := e.Encode(d.ButtonStyle); err != nil {
panic(err)
}
if err := e.Encode(d.HighlightStyle); err != nil {
panic(err)
}
}
func (d *DataPager) Deserialize(dec page.Decoder) {
d.DataPager.Deserialize(dec)
if err := dec.Decode(&d.ButtonStyle); err != nil {
panic(err)
}
if err := dec.Decode(&d.HighlightStyle); err != nil {
panic(err)
}
}
// DataPagerCreator is the initialization structure for declarative creation of data pagers
type DataPagerCreator struct {
// ID is the control id
ID string
// MaxPageButtons is the maximum number of page buttons to display in the pager
MaxPageButtons int
// ObjectName is the name of the object being displayed in the table
ObjectName string
// ObjectPluralName is the plural name of the object being displayed
ObjectPluralName string
// LabelForNext is the text to use in the Next button
LabelForNext string
// LabelForPrevious is the text to use in the Previous button
LabelForPrevious string
// PagedControl is the id of the control that will be paged by the pager
PagedControl string
page.ControlOptions
// ButtonStyle is the style that will be used to draw the standard buttons
ButtonStyle ButtonStyle
// HighlightStyle is the style that will be used to draw the highlighted buttons
HighlightStyle ButtonStyle
}
// Create is called by the framework to create a new control from the Creator. You
// do not normally need to call this.
func (c DataPagerCreator) Create(ctx context.Context, parent page.ControlI) page.ControlI {
if !parent.Page().HasControl(c.PagedControl) {
panic("you must declare the paged control before the data pager")
}
p := parent.Page().GetControl(c.PagedControl).(control.PagedControlI)
ctrl := NewDataPager(parent, c.ID, p)
c.Init(ctx, ctrl)
return ctrl
}
// Init is called by implementations of Buttons to initialize a control with the
// creator. You do not normally need to call this.
func (c DataPagerCreator) Init(ctx context.Context, ctrl DataPagerI) {
ctrl.(*DataPager).ButtonStyle = c.ButtonStyle
ctrl.(*DataPager).HighlightStyle = c.HighlightStyle
sub := control.DataPagerCreator{
MaxPageButtons: c.MaxPageButtons,
ObjectName: c.ObjectName,
ObjectPluralName: c.ObjectPluralName,
LabelForNext: c.LabelForNext,
LabelForPrevious: c.LabelForPrevious,
PagedControl: c.PagedControl,
ControlOptions: c.ControlOptions,
}
sub.Init(ctx, ctrl)
}
func init() {
page.RegisterControl(&DataPager{})
}