2021-09-07 17:36:50 +03:00
|
|
|
package rui
|
|
|
|
|
|
|
|
import "strings"
|
|
|
|
|
2024-09-12 14:05:11 +03:00
|
|
|
// Constants which represent [View] specific focus events properties
|
2021-09-07 17:36:50 +03:00
|
|
|
const (
|
2021-11-04 21:13:34 +03:00
|
|
|
// FocusEvent is the constant for "focus-event" property tag.
|
2024-09-18 13:50:06 +03:00
|
|
|
//
|
|
|
|
// Used by `View`.
|
|
|
|
// Occur when the view takes input focus.
|
|
|
|
//
|
|
|
|
// General listener format:
|
|
|
|
// `func(View)`.
|
|
|
|
//
|
|
|
|
// where:
|
|
|
|
// view - Interface of a view which generated this event.
|
|
|
|
//
|
|
|
|
// Allowed listener formats:
|
|
|
|
// `func()`.
|
2021-09-07 17:36:50 +03:00
|
|
|
FocusEvent = "focus-event"
|
|
|
|
|
2021-11-04 21:13:34 +03:00
|
|
|
// LostFocusEvent is the constant for "lost-focus-event" property tag.
|
2024-09-18 13:50:06 +03:00
|
|
|
//
|
|
|
|
// Used by `View`.
|
|
|
|
// Occur when the View lost input focus.
|
|
|
|
//
|
|
|
|
// General listener format:
|
|
|
|
// `func(view rui.View)`.
|
|
|
|
//
|
|
|
|
// where:
|
|
|
|
// view - Interface of a view which generated this event.
|
|
|
|
//
|
|
|
|
// Allowed listener formats:
|
|
|
|
// `func()`.
|
2021-09-07 17:36:50 +03:00
|
|
|
LostFocusEvent = "lost-focus-event"
|
|
|
|
)
|
|
|
|
|
2022-07-31 15:37:26 +03:00
|
|
|
func valueToNoParamListeners[V any](value any) ([]func(V), bool) {
|
2021-09-07 17:36:50 +03:00
|
|
|
if value == nil {
|
|
|
|
return nil, true
|
|
|
|
}
|
|
|
|
|
|
|
|
switch value := value.(type) {
|
2022-07-27 20:31:57 +03:00
|
|
|
case func(V):
|
|
|
|
return []func(V){value}, true
|
2021-09-07 17:36:50 +03:00
|
|
|
|
|
|
|
case func():
|
2022-07-27 20:31:57 +03:00
|
|
|
fn := func(V) {
|
2021-09-07 17:36:50 +03:00
|
|
|
value()
|
|
|
|
}
|
2022-07-27 20:31:57 +03:00
|
|
|
return []func(V){fn}, true
|
2021-09-07 17:36:50 +03:00
|
|
|
|
2022-07-27 20:31:57 +03:00
|
|
|
case []func(V):
|
2021-09-07 17:36:50 +03:00
|
|
|
if len(value) == 0 {
|
|
|
|
return nil, true
|
|
|
|
}
|
|
|
|
for _, fn := range value {
|
|
|
|
if fn == nil {
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return value, true
|
|
|
|
|
|
|
|
case []func():
|
|
|
|
count := len(value)
|
|
|
|
if count == 0 {
|
|
|
|
return nil, true
|
|
|
|
}
|
2022-07-27 20:31:57 +03:00
|
|
|
listeners := make([]func(V), count)
|
2021-09-07 17:36:50 +03:00
|
|
|
for i, v := range value {
|
|
|
|
if v == nil {
|
|
|
|
return nil, false
|
|
|
|
}
|
2022-07-27 20:31:57 +03:00
|
|
|
listeners[i] = func(V) {
|
2021-09-07 17:36:50 +03:00
|
|
|
v()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return listeners, true
|
|
|
|
|
2022-07-26 18:36:00 +03:00
|
|
|
case []any:
|
2021-09-07 17:36:50 +03:00
|
|
|
count := len(value)
|
|
|
|
if count == 0 {
|
|
|
|
return nil, true
|
|
|
|
}
|
2022-07-27 20:31:57 +03:00
|
|
|
listeners := make([]func(V), count)
|
2021-09-07 17:36:50 +03:00
|
|
|
for i, v := range value {
|
|
|
|
if v == nil {
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
switch v := v.(type) {
|
2022-07-27 20:31:57 +03:00
|
|
|
case func(V):
|
2021-09-07 17:36:50 +03:00
|
|
|
listeners[i] = v
|
|
|
|
|
|
|
|
case func():
|
2022-07-27 20:31:57 +03:00
|
|
|
listeners[i] = func(V) {
|
2021-09-07 17:36:50 +03:00
|
|
|
v()
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return listeners, true
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
|
|
|
|
var focusEvents = map[string]struct{ jsEvent, jsFunc string }{
|
|
|
|
FocusEvent: {jsEvent: "onfocus", jsFunc: "focusEvent"},
|
|
|
|
LostFocusEvent: {jsEvent: "onblur", jsFunc: "blurEvent"},
|
|
|
|
}
|
|
|
|
|
2022-07-26 18:36:00 +03:00
|
|
|
func (view *viewData) setFocusListener(tag string, value any) bool {
|
2022-07-27 20:31:57 +03:00
|
|
|
listeners, ok := valueToNoParamListeners[View](value)
|
2021-09-07 17:36:50 +03:00
|
|
|
if !ok {
|
|
|
|
notCompatibleType(tag, value)
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
if listeners == nil {
|
|
|
|
view.removeFocusListener(tag)
|
|
|
|
} else if js, ok := focusEvents[tag]; ok {
|
|
|
|
view.properties[tag] = listeners
|
|
|
|
if view.created {
|
2022-10-30 17:22:33 +03:00
|
|
|
view.session.updateProperty(view.htmlID(), js.jsEvent, js.jsFunc+"(this, event)")
|
2021-09-07 17:36:50 +03:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (view *viewData) removeFocusListener(tag string) {
|
|
|
|
delete(view.properties, tag)
|
|
|
|
if view.created {
|
|
|
|
if js, ok := focusEvents[tag]; ok {
|
2022-10-30 17:22:33 +03:00
|
|
|
view.session.removeProperty(view.htmlID(), js.jsEvent)
|
2021-09-07 17:36:50 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-31 22:17:46 +03:00
|
|
|
func getFocusListeners(view View, subviewID []string, tag string) []func(View) {
|
|
|
|
if len(subviewID) > 0 && subviewID[0] != "" {
|
|
|
|
view = ViewByID(view, subviewID[0])
|
2021-09-07 17:36:50 +03:00
|
|
|
}
|
2022-08-31 22:17:46 +03:00
|
|
|
|
2021-09-07 17:36:50 +03:00
|
|
|
if view != nil {
|
|
|
|
if value := view.Get(tag); value != nil {
|
|
|
|
if result, ok := value.([]func(View)); ok {
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return []func(View){}
|
|
|
|
}
|
|
|
|
|
|
|
|
func focusEventsHtml(view View, buffer *strings.Builder) {
|
2022-01-15 01:20:04 +03:00
|
|
|
if view.Focusable() {
|
|
|
|
for _, js := range focusEvents {
|
2023-05-02 17:20:01 +03:00
|
|
|
buffer.WriteString(js.jsEvent)
|
|
|
|
buffer.WriteString(`="`)
|
|
|
|
buffer.WriteString(js.jsFunc)
|
|
|
|
buffer.WriteString(`(this, event)" `)
|
2021-09-07 17:36:50 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetFocusListeners returns a FocusListener list. If there are no listeners then the empty list is returned
|
2022-08-31 22:17:46 +03:00
|
|
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
|
|
|
func GetFocusListeners(view View, subviewID ...string) []func(View) {
|
2021-09-07 17:36:50 +03:00
|
|
|
return getFocusListeners(view, subviewID, FocusEvent)
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetLostFocusListeners returns a LostFocusListener list. If there are no listeners then the empty list is returned
|
2022-08-31 22:17:46 +03:00
|
|
|
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
|
|
|
func GetLostFocusListeners(view View, subviewID ...string) []func(View) {
|
2021-09-07 17:36:50 +03:00
|
|
|
return getFocusListeners(view, subviewID, LostFocusEvent)
|
|
|
|
}
|