-
Notifications
You must be signed in to change notification settings - Fork 6
/
button.go
139 lines (120 loc) · 5.04 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
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
}
// Button is a standard html form submit button. It corresponds to a <button> tag in html.
//
// The default behavior of a submit button is to submit a form. If you have text boxes on your
// form, pressing enter will submit the FIRST button in the form, and so this essentially becomes
// your default button. If you have more than one button, and you want the default button to
// NOT be the first button on the screen, you can handle this in one of two ways:
// - Make sure your default button comes out first in the html, but then use css to change
// the visible order of the buttons. Be sure to also set the tab order if you do this to reflect
// the visible arrangement of the buttons. Or,
// - Create another button as the first button, and give it a display attribute
// of none so that it is not visible. Set its action to be the default action you want.
//
// If you want the button to display an image, simple 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 := &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.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
}
// 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
// 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)
}
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{})
}