-
Notifications
You must be signed in to change notification settings - Fork 6
/
list_unordered.go
205 lines (180 loc) · 6.12 KB
/
list_unordered.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
package control
import (
"bytes"
"context"
"github.com/goradd/goradd/pkg/html"
"github.com/goradd/goradd/pkg/page"
"reflect"
)
type UnorderedListI interface {
page.ControlI
ItemListI
GetItemsHtml(items []*ListItem) string
DataManagerEmbedder
SetBulletStyle(s string) UnorderedListI
SetItemTag(s string) UnorderedListI
}
// UnorderedList is a dynamically generated html unordered list (ul). Such lists are often used as the basis for
// javascript and css widgets. If you use a data provider to set the data, you should call AddItems to the list
// in your LoadData function.
type UnorderedList struct {
page.ControlBase
ItemList
DataManager
itemTag string
}
const (
// UnoderedListStyleDisc is the default list style for main items and is a bullet
UnorderedListStyleDisc = "disc" // default
// UnorderedListStyleCircle is the default list style for 2nd level items and is an open circle
UnorderedListStyleCircle = "circle"
// UnorderedListStyleSquare sets a square as the bullet
UnorderedListStyleSquare = "square"
// UnorderedListStyleNone removes the bullet from the list
UnorderedListStyleNone = "none"
)
// NewUnorderedList creates a new ul type list.
func NewUnorderedList(parent page.ControlI, id string) *UnorderedList {
l := &UnorderedList{}
l.Self = l
l.Init(parent, id)
return l
}
func (l *UnorderedList) Init(parent page.ControlI, id string) {
l.ControlBase.Init(parent, id)
l.ItemList = NewItemList(l)
l.Tag = "ul"
l.itemTag = "li"
}
// this() supports object oriented features by giving easy access to the virtual function interface.
func (l *UnorderedList) this() UnorderedListI {
return l.Self.(UnorderedListI)
}
// SetItemTag sets the tag that will be used for items in the list. By default this is "li".
func (l *UnorderedList) SetItemTag(s string) UnorderedListI {
l.itemTag = s
return l.this()
}
// SetBulletType sets the list-style-type attribute of the list. Choose from the UnorderedListStyle* constants.
func (l *UnorderedList) SetBulletStyle(s string) UnorderedListI {
l.ControlBase.SetStyle("list-style-type", s)
return l.this()
}
func (l *UnorderedList) DrawTag(ctx context.Context) string {
if l.HasDataProvider() {
l.LoadData(ctx, l.this())
defer l.ResetData()
}
return l.ControlBase.DrawTag(ctx)
}
// DrawingAttributes retrieves the tag's attributes at draw time. You should not normally need to call this, and the
// attributes are disposed of after drawing, so they are essentially read-only.
func (l *UnorderedList) DrawingAttributes(ctx context.Context) html.Attributes {
a := l.ControlBase.DrawingAttributes(ctx)
a.SetDataAttribute("grctl", "hlist")
return a
}
func (l *UnorderedList) DrawInnerHtml(ctx context.Context, buf *bytes.Buffer) (err error) {
h := l.this().GetItemsHtml(l.items)
buf.WriteString(h)
return nil
}
// GetItemsHtml is used by the framework to get the items for the html. It is exported so that
// it can be overridden by other implementations of an UnorderedList.
func (l *UnorderedList) GetItemsHtml(items []*ListItem) string {
var h = ""
for _, item := range items {
if item.HasChildItems() {
innerhtml := l.this().GetItemsHtml(item.ListItems())
innerhtml = html.RenderTag(l.Tag, nil, innerhtml)
h += html.RenderTag(l.itemTag, item.Attributes(), item.Label()+" "+innerhtml)
} else {
h += html.RenderTag(l.itemTag, item.Attributes(), item.RenderLabel())
}
}
return h
}
// SetData replaces the current list with the given data.
// ItemLister, ItemIDer, Labeler or Stringer types are accepted.
// This function can accept one or more lists of items, or
// single items. They will all get added to the top level of the list. To add sub items, get a list item
// and add items to it.
func (l *UnorderedList) SetData(data interface{}) {
kind := reflect.TypeOf(data).Kind()
if !(kind == reflect.Slice || kind == reflect.Array) {
panic("you must call SetData with a slice or array")
}
l.ItemList.Clear()
l.AddListItems(data)
}
func (l *UnorderedList) Serialize(e page.Encoder) (err error) {
if err = l.ControlBase.Serialize(e); err != nil {
return
}
if err = l.ItemList.Serialize(e); err != nil {
return
}
if err = l.DataManager.Serialize(e); err != nil {
return
}
if err = e.Encode(l.itemTag); err != nil {
return
}
return
}
func (l *UnorderedList) Deserialize(dec page.Decoder) (err error) {
if err = l.ControlBase.Deserialize(dec); err != nil {
return
}
if err = l.ItemList.Deserialize(dec); err != nil {
panic(err)
}
if err = l.DataManager.Deserialize(dec); err != nil {
panic(err)
}
if err = dec.Decode(&l.itemTag); err != nil {
panic(err)
}
return
}
type UnorderedListCreator struct {
ID string
// Items is a static list of labels and values that will be in the list. Or, use a DataProvider to dynamically generate the items.
Items []ListValue
// DataProvider is the control that will dynamically provide the data for the list and that implements the DataBinder interface.
DataProvider DataBinder
// DataProviderID is the id of a control that will dynamically provide the data for the list and that implements the DataBinder interface.
DataProviderID string
// BulletStyle is the list-style-type property.
BulletStyle string
page.ControlOptions
}
// Create is called by the framework to create a new control from the Creator. You
// do not normally need to call this.
func (c UnorderedListCreator) Create(ctx context.Context, parent page.ControlI) page.ControlI {
ctrl := NewUnorderedList(parent, c.ID)
c.Init(ctx, ctrl)
return ctrl
}
func (c UnorderedListCreator) Init(ctx context.Context, ctrl UnorderedListI) {
if c.Items != nil {
ctrl.AddListItems(c.Items)
}
if c.DataProvider != nil {
ctrl.SetDataProvider(c.DataProvider)
} else if c.DataProviderID != "" {
provider := ctrl.Page().GetControl(c.DataProviderID).(DataBinder)
ctrl.SetDataProvider(provider)
}
if c.BulletStyle != "" {
ctrl.SetBulletStyle(c.BulletStyle)
}
ctrl.ApplyOptions(ctx, c.ControlOptions)
}
// GetUnorderedList is a convenience method to return the control with the given id from the page.
func GetUnorderedList(c page.ControlI, id string) *UnorderedList {
return c.Page().GetControl(id).(*UnorderedList)
}
func init() {
page.RegisterControl(&UnorderedList{})
}