-
Notifications
You must be signed in to change notification settings - Fork 6
/
button.go
157 lines (136 loc) · 5.43 KB
/
button.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
package control
import (
"context"
"github.com/goradd/goradd/pkg/html"
"github.com/goradd/goradd/pkg/page"
"github.com/goradd/goradd/pkg/page/action"
"github.com/goradd/goradd/pkg/page/event"
)
type ButtonI interface {
page.ControlI
SetLabel(label string) page.ControlI
OnSubmit(action action.ActionI) page.ControlI
SetIsPrimary(p bool)
}
// Button is a standard html form button. It corresponds to a <button> tag in html.
//
// By default, we set the "type" attribute of the button to "button". This will prevent
// the button from submitting the form when the user presses the return key.
// To choose which button will submit on a return, call SetIsPrimary() or set the "type" attribute to "submit".
//
// If multiple "submit" buttons are on the page, the default behavior
// will occur if you there are text boxes on the
// form, and pressing enter will submit the FIRST button in the form as encountered in the html.
// Using CSS to alter the placement of the buttons (using float for instance), will not change
// which button the browser considers to be the first.
//
// If you want the button to display an image, create an Image control as a child of the button.
type Button struct {
page.ControlBase
}
// NewButton creates a new standard html button
func NewButton(parent page.ControlI, id string) *Button {
b := new(Button)
b.Self = b
b.Init(parent, id)
return b
}
// Init is called by subclasses of Button to initialize the button control structure.
func (b *Button) Init(parent page.ControlI, id string) {
b.ControlBase.Init(parent, id)
b.Tag = "button"
b.SetAttribute("type", "button")
b.SetValidationType(page.ValidateForm) // default to validate the entire form. Can be changed after creation.
}
func (c *Button) this() ButtonI {
return c.Self.(ButtonI)
}
// SetLabel is an alias for SetText on buttons. Standard buttons do not normally have separate labels.
// Subclasses can redefine this if they use separate labels.
func (b *Button) SetLabel(label string) page.ControlI {
b.SetText(label)
return b.this()
}
// SetIsPrimary will set this button to be the default button on the form, which is the button clicked when
// the user presses a return. Some browsers only respond to this when there is a textbox on the screen.
func (b *Button) SetIsPrimary(s bool) {
if s {
b.SetAttribute("type", "submit")
} else {
b.SetAttribute("type", "button")
}
}
// On causes the given actions to execute when the given event is triggered.
func (b *Button) On(e *page.Event, action action.ActionI) page.ControlI {
e.Terminating() // prevent default action (override submit)
b.ControlBase.On(e, action)
return b.this()
}
// 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 (b *Button) DrawingAttributes(ctx context.Context) html.Attributes {
a := b.ControlBase.DrawingAttributes(ctx)
a.SetDataAttribute("grctl", "button")
a.Set("name", page.HtmlVarAction) // needed for non-javascript posts
a.Set("value", b.ID())
//a.Set("type", "submit")
return a
}
// OnSubmit is a shortcut for adding a click event handler that is particular to buttons and button like objects.
// It debounces the click, so that all other events are lost until this event processes. It should generally be used for
// operations that will eventually redirect to a different page. If coupling this with an ajax response, you should
// probably also make the response priority PriorityFinal.
func (b *Button) OnSubmit(action action.ActionI) page.ControlI {
// We delay here to try to make sure any other delayed events are executed first.
return b.On(event.Click().Terminating().Delay(200).Blocking(), action)
}
// ButtonCreator is the initialization structure for declarative creation of buttons
type ButtonCreator struct {
// ID is the control id
ID string
// Text is the text displayed in the button
Text string
// Set IsPrimary to true to make this the default button on the page
IsPrimary bool
// OnSubmit is the action to take when the button is submitted. Use this specifically
// for buttons that move to other pages or processes transactions, as it debounces the button
// and waits until all other actions complete
OnSubmit action.ActionI
// OnClick is an action to take when the button is pressed. Do not specify both
// a OnClick and OnSubmit.
OnClick action.ActionI
ValidationType page.ValidationType
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 ButtonCreator) Create(ctx context.Context, parent page.ControlI) page.ControlI {
ctrl := NewButton(parent, c.ID)
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 ButtonCreator) Init(ctx context.Context, ctrl ButtonI) {
ctrl.SetLabel(c.Text)
if c.OnSubmit != nil {
ctrl.OnSubmit(c.OnSubmit)
}
if c.OnClick != nil {
ctrl.On(event.Click(), c.OnClick)
}
if c.ValidationType != page.ValidateDefault {
ctrl.SetValidationType(c.ValidationType)
}
if c.IsPrimary {
ctrl.SetIsPrimary(true)
}
ctrl.ApplyOptions(ctx, c.ControlOptions)
}
// GetButton is a convenience method to return the button with the given id from the page.
func GetButton(c page.ControlI, id string) *Button {
return c.Page().GetControl(id).(*Button)
}
func init() {
page.RegisterControl(&Button{})
}