Changed the main DropDownList and EditView listener

This commit is contained in:
anoshenko 2023-04-23 18:07:01 +03:00
parent eac3379fb1
commit 2a480cc6ac
5 changed files with 262 additions and 36 deletions

View File

@ -3107,13 +3107,21 @@ string свойство "edit-view-pattern" (константа EditViewPattern)
Для отслеживания изменения текста используется событие "edit-text-changed" (константа
EditTextChangedEvent). Основной слушатель события имеет следующий формат:
func(EditView, string)
func(EditView, string, string)
где второй аргумент это новое значение текста
где второй аргумент это новое значение текста, третий аргумент - предыдущее значение текста.
Дополнительные слушатели события могут иметь следующий формат
func(EditView, newText string)
func(newText, oldText string)
func(newText string)
func(EditView)
func()
Получить текущий список слушателей изменения текста можно с помощью функции
func GetTextChangedListeners(view View, subviewID ...string) []func(EditView, string)
func GetTextChangedListeners(view View, subviewID ...string) []func(EditView, string, string)
## NumberPicker
@ -3425,13 +3433,21 @@ float32, float64, int, int8…int64, uint, uint8…uint64.
Для отслеживания изменения свойства "current" используется событие "drop-down-event" (константа
DropDownEvent). Основной слушатель события имеет следующий формат:
func(list DropDownList, newCurrent int)
func(list DropDownList, newCurrent, oldCurrent int)
где второй аргумент это индекс выбранного элемента
где второй аргумент это индекс выбранного элемента, третий аргумент - предыдущее значение индекса.
Дополнительные слушатели события могут иметь следующий формат
func(list DropDownList, newCurrent int)
func(newCurrent, oldCurrent int)
func(newCurrent int)
func(list DropDownList)
func()
Получить текущий список слушателей изменения даты можно с помощью функции
func GetDropDownListeners(view View, subviewID ...string) []func(DropDownList, int)
func GetDropDownListeners(view View, subviewID ...string) []func(DropDownList, int, int)
## ProgressBar

View File

@ -3071,13 +3071,21 @@ The following functions can be used to get the values of the properties of an Ed
The "edit-text-changed" event (EditTextChangedEvent constant) is used to track changes to the text.
The main event listener has the following format:
func(EditView, string)
func(EditView, string, string)
where the second argument is the new text value
where the second argument is the new text value the third argument is the previous text value.
Additional event listeners can have the following format
func(EditView, newText string)
func(newText, oldText string)
func(newText string)
func(EditView)
func()
You can get the current list of text change listeners using the function
func GetTextChangedListeners(view View, subviewID ...string) []func(EditView, string)
func GetTextChangedListeners(view View, subviewID ...string) []func(EditView, string, string)
## NumberPicker
@ -3393,11 +3401,19 @@ The main event listener has the following format:
func(list DropDownList, newCurrent int)
where the second argument is the index of the selected item
where the second argument is the index of the selected item, the third argument is the previous index value.
Additional event listeners can have the following format
func(list DropDownList, newCurrent int)
func(newCurrent, oldCurrent int)
func(newCurrent int)
func(list DropDownList)
func()
You can get the current list of date change listeners using the function
func GetDropDownListeners(view View, subviewID ...string) []func(DropDownList, int)
func GetDropDownListeners(view View, subviewID ...string) []func(DropDownList, int, int)
## ProgressBar

View File

@ -21,7 +21,7 @@ type dropDownListData struct {
viewData
items []string
disabledItems []any
dropDownListener []func(DropDownList, int)
dropDownListener []func(DropDownList, int, int)
}
// NewDropDownList create new DropDownList object and return it
@ -41,7 +41,7 @@ func (list *dropDownListData) init(session Session) {
list.tag = "DropDownList"
list.items = []string{}
list.disabledItems = []any{}
list.dropDownListener = []func(DropDownList, int){}
list.dropDownListener = []func(DropDownList, int, int){}
}
func (list *dropDownListData) String() string {
@ -78,7 +78,7 @@ func (list *dropDownListData) remove(tag string) {
case DropDownEvent:
if len(list.dropDownListener) > 0 {
list.dropDownListener = []func(DropDownList, int){}
list.dropDownListener = []func(DropDownList, int, int){}
list.propertyChangedEvent(tag)
}
@ -89,7 +89,7 @@ func (list *dropDownListData) remove(tag string) {
if list.created {
list.session.callFunc("selectDropDownListItem", list.htmlID(), 0)
}
list.onSelectedItemChanged(0)
list.onSelectedItemChanged(0, oldCurrent)
}
default:
@ -116,12 +116,12 @@ func (list *dropDownListData) set(tag string, value any) bool {
return list.setDisabledItems(value)
case DropDownEvent:
listeners, ok := valueToEventListeners[DropDownList, int](value)
listeners, ok := valueToEventWithOldListeners[DropDownList, int](value)
if !ok {
notCompatibleType(tag, value)
return false
} else if listeners == nil {
listeners = []func(DropDownList, int){}
listeners = []func(DropDownList, int, int){}
}
list.dropDownListener = listeners
list.propertyChangedEvent(tag)
@ -137,7 +137,7 @@ func (list *dropDownListData) set(tag string, value any) bool {
if list.created {
list.session.callFunc("selectDropDownListItem", list.htmlID(), current)
}
list.onSelectedItemChanged(current)
list.onSelectedItemChanged(current, oldCurrent)
}
return true
}
@ -377,9 +377,9 @@ func (list *dropDownListData) htmlDisabledProperties(self View, buffer *strings.
}
}
func (list *dropDownListData) onSelectedItemChanged(number int) {
func (list *dropDownListData) onSelectedItemChanged(number, old int) {
for _, listener := range list.dropDownListener {
listener(list, number)
listener(list, number, old)
}
list.propertyChangedEvent(Current)
}
@ -390,8 +390,9 @@ func (list *dropDownListData) handleCommand(self View, command string, data Data
if text, ok := data.PropertyValue("number"); ok {
if number, err := strconv.Atoi(text); err == nil {
if GetCurrent(list) != number && number >= 0 && number < len(list.items) {
old := GetCurrent(list)
list.properties[Current] = number
list.onSelectedItemChanged(number)
list.onSelectedItemChanged(number, old)
}
} else {
ErrorLog(err.Error())
@ -406,8 +407,8 @@ func (list *dropDownListData) handleCommand(self View, command string, data Data
// GetDropDownListeners returns the "drop-down-event" listener list. If there are no listeners then the empty list is returned.
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetDropDownListeners(view View, subviewID ...string) []func(DropDownList, int) {
return getEventListeners[DropDownList, int](view, subviewID, DropDownEvent)
func GetDropDownListeners(view View, subviewID ...string) []func(DropDownList, int, int) {
return getEventWithOldListeners[DropDownList, int](view, subviewID, DropDownEvent)
}
// GetDropDownItems return the DropDownList items list.

View File

@ -41,7 +41,7 @@ type EditView interface {
type editViewData struct {
viewData
textChangeListeners []func(EditView, string)
textChangeListeners []func(EditView, string, string)
}
// NewEditView create new EditView object and return it
@ -58,7 +58,7 @@ func newEditView(session Session) View {
func (edit *editViewData) init(session Session) {
edit.viewData.init(session)
edit.textChangeListeners = []func(EditView, string){}
edit.textChangeListeners = []func(EditView, string, string){}
edit.tag = "EditView"
}
@ -125,7 +125,7 @@ func (edit *editViewData) remove(tag string) {
case EditTextChangedEvent:
if len(edit.textChangeListeners) > 0 {
edit.textChangeListeners = []func(EditView, string){}
edit.textChangeListeners = []func(EditView, string, string){}
edit.propertyChangedEvent(tag)
}
@ -134,7 +134,7 @@ func (edit *editViewData) remove(tag string) {
oldText := GetText(edit)
delete(edit.properties, tag)
if oldText != "" {
edit.textChanged("")
edit.textChanged("", oldText)
if edit.created {
edit.session.callFunc("setInputValue", edit.htmlID(), "")
}
@ -205,7 +205,7 @@ func (edit *editViewData) set(tag string, value any) bool {
if text, ok := value.(string); ok {
edit.properties[Text] = text
if text = GetText(edit); oldText != text {
edit.textChanged(text)
edit.textChanged(text, oldText)
if edit.created {
if GetEditViewType(edit) == MultiLineText {
updateInnerHTML(edit.htmlID(), edit.Session())
@ -328,12 +328,12 @@ func (edit *editViewData) set(tag string, value any) bool {
return false
case EditTextChangedEvent:
listeners, ok := valueToEventListeners[EditView, string](value)
listeners, ok := valueToEventWithOldListeners[EditView, string](value)
if !ok {
notCompatibleType(tag, value)
return false
} else if listeners == nil {
listeners = []func(EditView, string){}
listeners = []func(EditView, string, string){}
}
edit.textChangeListeners = listeners
edit.propertyChangedEvent(tag)
@ -358,10 +358,11 @@ func (edit *editViewData) AppendText(text string) {
if GetEditViewType(edit) == MultiLineText {
if value := edit.getRaw(Text); value != nil {
if textValue, ok := value.(string); ok {
oldText := textValue
textValue += text
edit.properties[Text] = textValue
edit.session.callFunc("appendToInnerHTML", edit.htmlID(), text)
edit.textChanged(textValue)
edit.textChanged(textValue, oldText)
return
}
}
@ -371,9 +372,9 @@ func (edit *editViewData) AppendText(text string) {
}
}
func (edit *editViewData) textChanged(newText string) {
func (edit *editViewData) textChanged(newText, oldText string) {
for _, listener := range edit.textChangeListeners {
listener(edit, newText)
listener(edit, newText, oldText)
}
edit.propertyChangedEvent(Text)
}
@ -485,7 +486,7 @@ func (edit *editViewData) handleCommand(self View, command string, data DataObje
if text, ok := data.PropertyValue("text"); ok {
edit.properties[Text] = text
if text := GetText(edit); text != oldText {
edit.textChanged(text)
edit.textChanged(text, oldText)
}
}
return true
@ -552,8 +553,8 @@ func IsSpellcheck(view View, subviewID ...string) bool {
// GetTextChangedListeners returns the TextChangedListener list of an EditView or MultiLineEditView subview.
// If there are no listeners then the empty list is returned
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetTextChangedListeners(view View, subviewID ...string) []func(EditView, string) {
return getEventListeners[EditView, string](view, subviewID, EditTextChangedEvent)
func GetTextChangedListeners(view View, subviewID ...string) []func(EditView, string, string) {
return getEventWithOldListeners[EditView, string](view, subviewID, EditTextChangedEvent)
}
// GetEditViewType returns a value of the Type property of EditView.

View File

@ -193,6 +193,185 @@ func valueToEventListeners[V View, E any](value any) ([]func(V, E), bool) {
return nil, false
}
func valueToEventWithOldListeners[V View, E any](value any) ([]func(V, E, E), bool) {
if value == nil {
return nil, true
}
switch value := value.(type) {
case func(V, E, E):
return []func(V, E, E){value}, true
case func(V, E):
fn := func(v V, val, _ E) {
value(v, val)
}
return []func(V, E, E){fn}, true
case func(E, E):
fn := func(_ V, val, old E) {
value(val, old)
}
return []func(V, E, E){fn}, true
case func(E):
fn := func(_ V, val, _ E) {
value(val)
}
return []func(V, E, E){fn}, true
case func(V):
fn := func(v V, _, _ E) {
value(v)
}
return []func(V, E, E){fn}, true
case func():
fn := func(V, E, E) {
value()
}
return []func(V, E, E){fn}, true
case []func(V, E, E):
if len(value) == 0 {
return nil, true
}
for _, fn := range value {
if fn == nil {
return nil, false
}
}
return value, true
case []func(V, E):
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(V, E, E), count)
for i, fn := range value {
if fn == nil {
return nil, false
}
listeners[i] = func(view V, val, _ E) {
fn(view, val)
}
}
return listeners, true
case []func(E):
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(V, E, E), count)
for i, fn := range value {
if fn == nil {
return nil, false
}
listeners[i] = func(_ V, val, _ E) {
fn(val)
}
}
return listeners, true
case []func(E, E):
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(V, E, E), count)
for i, fn := range value {
if fn == nil {
return nil, false
}
listeners[i] = func(_ V, val, old E) {
fn(val, old)
}
}
return listeners, true
case []func(V):
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(V, E, E), count)
for i, fn := range value {
if fn == nil {
return nil, false
}
listeners[i] = func(view V, _, _ E) {
fn(view)
}
}
return listeners, true
case []func():
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(V, E, E), count)
for i, fn := range value {
if fn == nil {
return nil, false
}
listeners[i] = func(V, E, E) {
fn()
}
}
return listeners, true
case []any:
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(V, E, E), count)
for i, v := range value {
if v == nil {
return nil, false
}
switch fn := v.(type) {
case func(V, E, E):
listeners[i] = fn
case func(V, E):
listeners[i] = func(view V, val, _ E) {
fn(view, val)
}
case func(E, E):
listeners[i] = func(_ V, val, old E) {
fn(val, old)
}
case func(E):
listeners[i] = func(_ V, val, _ E) {
fn(val)
}
case func(V):
listeners[i] = func(view V, _, _ E) {
fn(view)
}
case func():
listeners[i] = func(V, E, E) {
fn()
}
default:
return nil, false
}
}
return listeners, true
}
return nil, false
}
var keyEvents = map[string]struct{ jsEvent, jsFunc string }{
KeyDownEvent: {jsEvent: "onkeydown", jsFunc: "keyDownEvent"},
KeyUpEvent: {jsEvent: "onkeyup", jsFunc: "keyUpEvent"},
@ -227,6 +406,19 @@ func (view *viewData) removeKeyListener(tag string) {
}
}
func getEventWithOldListeners[V View, E any](view View, subviewID []string, tag string) []func(V, E, E) {
if len(subviewID) > 0 && subviewID[0] != "" {
view = ViewByID(view, subviewID[0])
}
if view != nil {
if value := view.Get(tag); value != nil {
if result, ok := value.([]func(V, E, E)); ok {
return result
}
}
}
return []func(V, E, E){}
}
func getEventListeners[V View, E any](view View, subviewID []string, tag string) []func(V, E) {
if len(subviewID) > 0 && subviewID[0] != "" {
view = ViewByID(view, subviewID[0])