Added "data-list" property

This commit is contained in:
Alexei Anoshenko 2024-05-18 18:57:41 +03:00
parent fd516af017
commit b4d1e34f21
10 changed files with 444 additions and 26 deletions

View File

@ -1,3 +1,7 @@
# v0.13.0
* Added "data-list" property
* Bug fixing
# v0.14.0 # v0.14.0
* Added the ability to work without creating a WebSocket. Added NoSocket property to AppParams. * Added the ability to work without creating a WebSocket. Added NoSocket property to AppParams.
* Added SocketAutoClose property to AppParams. * Added SocketAutoClose property to AppParams.

View File

@ -3104,8 +3104,17 @@ string свойство "edit-view-pattern" (константа EditViewPattern)
текст переносится на новую строку. текст переносится на новую строку.
Для изменения цвета каретки ввода текста используется Color свойство "caret-color" (константа CaretColor). Для изменения цвета каретки ввода текста используется Color свойство "caret-color" (константа CaretColor).
Свойство "caret-color" может быть задано не только для EditView, но и для любого контейнера. В этом случае Свойство "caret-color" может быть задано не только для EditView, но и для любого контейнера.
цвет каретки меняется для всех дочерних EditView помещенных в этот контейнер В этом случае цвет каретки меняется для всех дочерних EditView помещенных в этот контейнер.
Свойство "data-list" (константа DataList) позволяет задать массив рекомендованных значений.
Если задать свойство "data-list" то у редактора появиться выпадающее меню со списком
данных значений. В качестве значения данного свойство должен использоваться массив строк.
Например
editor := rui.NewEditView(session, rui.Params{
rui.DataList: []string{"Text 1", "Text 2", "Text 3"},
})
Для получения значений свойств EditView могут использоваться следующие функции: Для получения значений свойств EditView могут использоваться следующие функции:
@ -3118,6 +3127,7 @@ string свойство "edit-view-pattern" (константа EditViewPattern)
func IsEditViewWrap(view View, subviewID ...string) bool func IsEditViewWrap(view View, subviewID ...string) bool
func IsSpellcheck(view View, subviewID ...string) bool func IsSpellcheck(view View, subviewID ...string) bool
func GetCaretColor(view View, subviewID ...string) Color func GetCaretColor(view View, subviewID ...string) Color
func GetDataList(view View, subviewID ...string) []string
Для отслеживания изменения текста используется событие "edit-text-changed" (константа Для отслеживания изменения текста используется событие "edit-text-changed" (константа
EditTextChangedEvent). Основной слушатель события имеет следующий формат: EditTextChangedEvent). Основной слушатель события имеет следующий формат:
@ -3190,6 +3200,30 @@ NumberPicker может работать в двух режимах: редак
func GetNumberPickerMinMax(view View, subviewID ...string) (float64, float64) func GetNumberPickerMinMax(view View, subviewID ...string) (float64, float64)
func GetNumberPickerStep(view View, subviewID ...string) float64 func GetNumberPickerStep(view View, subviewID ...string) float64
Свойство "data-list" (константа DataList) позволяет задать массив рекомендованных значений.
Если задать свойство "data-list" в случае
* если "number-picker-type" задано как NumberEditor, то у редактора появиться выпадающее меню со списком этих значений;
* если "number-picker-type" задано как NumberSlider, то у слайдера будут отображены метки соответствующие этим значениям;
В качестве значения свойство "data-list" должен использоваться массив строк, целых чисел,
вещественных чисел или их комбинация. Например
editor1 := rui.NewNumberPicker(session, rui.Params{
rui.DataList: []string{"1", "2", "3"},
})
editor2 := rui.NewNumberPicker(session, rui.Params{
rui.DataList: []int{1, 2, 3},
})
editor3 := rui.NewNumberPicker(session, rui.Params{
rui.DataList: []any{"1", 2, 3.0},
})
Получить значение свойства "data-list" можно с помощью функции
func GetDataList(view View, subviewID ...string) []string
Для отслеживания изменения вводимого значения используется событие "number-changed" (константа Для отслеживания изменения вводимого значения используется событие "number-changed" (константа
NumberChangedEvent). Основной слушатель события имеет следующий формат: NumberChangedEvent). Основной слушатель события имеет следующий формат:
@ -3244,6 +3278,17 @@ NumberChangedEvent). Основной слушатель события име
func GetDatePickerMax(view View, subviewID ...string) (time.Time, bool) func GetDatePickerMax(view View, subviewID ...string) (time.Time, bool)
func GetDatePickerStep(view View, subviewID ...string) int func GetDatePickerStep(view View, subviewID ...string) int
Свойство "data-list" (константа DataList) позволяет задать массив рекомендованных значений.
Если задать свойство "data-list" то у редактора может появиться выпадающее меню со списком
данных значений. Некоторые браузеры могут игнорировать данное свойство, например Safari for macOS.
В качестве значения данного свойство должен использоваться массив строк в формате "YYYY-MM-DD".
Например
editor := rui.NewDatePicker(session, rui.Params{
rui.DataList: []string{"1990-09-02", "2010-05-24"},
})
Для отслеживания изменения вводимого значения используется событие "date-changed" (константа Для отслеживания изменения вводимого значения используется событие "date-changed" (константа
DateChangedEvent). Основной слушатель события имеет следующий формат: DateChangedEvent). Основной слушатель события имеет следующий формат:
@ -3298,6 +3343,17 @@ DateChangedEvent). Основной слушатель события имее
func GetTimePickerMax(view View, subviewID ...string) (time.Time, bool) func GetTimePickerMax(view View, subviewID ...string) (time.Time, bool)
func GetTimePickerStep(view View, subviewID ...string) int func GetTimePickerStep(view View, subviewID ...string) int
Свойство "data-list" (константа DataList) позволяет задать массив рекомендованных значений.
Если задать свойство "data-list" то у редактора может появиться выпадающее меню со списком
данных значений. Некоторые браузеры могут игнорировать данное свойство, например Safari for macOS.
В качестве значения данного свойство должен использоваться массив строк в формате "HH:MM:SS" или "HH:MM".
Например
editor := rui.NewTimePicker(session, rui.Params{
rui.DataList: []string{"10:22", "08:00"},
})
Для отслеживания изменения вводимого значения используется событие "time-changed" (константа Для отслеживания изменения вводимого значения используется событие "time-changed" (константа
TimeChangedEvent). Основной слушатель события имеет следующий формат: TimeChangedEvent). Основной слушатель события имеет следующий формат:

View File

@ -3079,6 +3079,14 @@ To change the color of the text input caret, use the Color property "caret-color
The "caret-color" property can be set not only for EditView, but for any container. The "caret-color" property can be set not only for EditView, but for any container.
In this case, the color of the caret changes for all child EditViews placed in this container. In this case, the color of the caret changes for all child EditViews placed in this container.
The "data-list" property (DataList constant) allows you to specify an array of recommended values.
If you set the "data-list" property, the editor will have a drop-down menu with a list of these values.
The value of this property must be an array of strings. For example
editor := rui.NewEditView(session, rui.Params{
rui.DataList: []string{"Text 1", "Text 2", "Text 3"},
})
The following functions can be used to get the values of the properties of an EditView: The following functions can be used to get the values of the properties of an EditView:
func GetText(view View, subviewID ...string) string func GetText(view View, subviewID ...string) string
@ -3090,6 +3098,7 @@ The following functions can be used to get the values of the properties of an Ed
func IsEditViewWrap(view View, subviewID ...string) bool func IsEditViewWrap(view View, subviewID ...string) bool
func IsSpellcheck(view View, subviewID ...string) bool func IsSpellcheck(view View, subviewID ...string) bool
func GetCaretColor(view View, subviewID ...string) Color func GetCaretColor(view View, subviewID ...string) Color
func GetDataList(view View, subviewID ...string) []string
The "edit-text-changed" event (EditTextChangedEvent constant) is used to track changes to the text. The "edit-text-changed" event (EditTextChangedEvent constant) is used to track changes to the text.
The main event listener has the following format: The main event listener has the following format:
@ -3161,6 +3170,29 @@ You can read the values of these properties using the functions:
func GetNumberPickerMinMax(view View, subviewID ...string) (float64, float64) func GetNumberPickerMinMax(view View, subviewID ...string) (float64, float64)
func GetNumberPickerStep(view View, subviewID ...string) float64 func GetNumberPickerStep(view View, subviewID ...string) float64
The "data-list" property (DataList constant) allows you to specify an array of recommended values.
If you set the "data-list" property in case
* if "number-picker-type" is set to NumberEditor, then the editor will have a drop-down menu with a list of these values;
* if "number-picker-type" is set to NumberSlider, then the slider will display labels corresponding to these values;
The value of the "data-list" property must be an array of strings, integers, real numbers, or a combination of these. For example
editor1 := rui.NewNumberPicker(session, rui.Params{
rui.DataList: []string{"1", "2", "3"},
})
editor2 := rui.NewNumberPicker(session, rui.Params{
rui.DataList: []int{1, 2, 3},
})
editor3 := rui.NewNumberPicker(session, rui.Params{
rui.DataList: []any{"1", 2, 3.0},
})
You can get the value of the "data-list" property using the function
func GetDataList(view View, subviewID ...string) []string
The "number-changed" event (NumberChangedEvent constant) is used to track the change in the entered value. The "number-changed" event (NumberChangedEvent constant) is used to track the change in the entered value.
The main event listener has the following format: The main event listener has the following format:
@ -3216,6 +3248,16 @@ You can read the values of these properties using the functions:
func GetDatePickerMax(view View, subviewID ...string) (time.Time, bool) func GetDatePickerMax(view View, subviewID ...string) (time.Time, bool)
func GetDatePickerStep(view View, subviewID ...string) int func GetDatePickerStep(view View, subviewID ...string) int
The "data-list" property (DataList constant) allows you to specify an array of recommended values.
If you set the "data-list" property, the editor may have a drop-down menu with a list of these values. Some browsers may ignore this property, such as Safari for macOS.
The value of this property must be an array of strings in the format "YYYY-MM-DD".
For example
editor := rui.NewDatePicker(session, rui.Params{
rui.DataList: []string{"1990-09-02", "2010-05-24"},
})
The "date-changed" event (DateChangedEvent constant) is used to track the change in the entered value. The "date-changed" event (DateChangedEvent constant) is used to track the change in the entered value.
The main event listener has the following format: The main event listener has the following format:
@ -3271,6 +3313,16 @@ You can read the values of these properties using the functions:
func GetTimePickerMax(view View, subviewID ...string) (time.Time, bool) func GetTimePickerMax(view View, subviewID ...string) (time.Time, bool)
func GetTimePickerStep(view View, subviewID ...string) int func GetTimePickerStep(view View, subviewID ...string) int
The "data-list" property (DataList constant) allows you to specify an array of recommended values.
If you set the "data-list" property, the editor may have a drop-down menu with a list of these values. Some browsers may ignore this property, such as Safari for macOS.
The value of this property must be an array of strings in the format "HH:MM:SS" or "HH:MM".
For example
editor := rui.NewTimePicker(session, rui.Params{
rui.DataList: []string{"1990-09-02", "2010-05-24"},
})
The "time-changed" event (TimeChangedEvent constant) is used to track the change in the entered value. The "time-changed" event (TimeChangedEvent constant) is used to track the change in the entered value.
The main event listener has the following format: The main event listener has the following format:

View File

@ -16,6 +16,7 @@ type ColorPicker interface {
type colorPickerData struct { type colorPickerData struct {
viewData viewData
dataList
colorChangedListeners []func(ColorPicker, Color, Color) colorChangedListeners []func(ColorPicker, Color, Color)
} }
@ -37,6 +38,7 @@ func (picker *colorPickerData) init(session Session) {
picker.hasHtmlDisabled = true picker.hasHtmlDisabled = true
picker.colorChangedListeners = []func(ColorPicker, Color, Color){} picker.colorChangedListeners = []func(ColorPicker, Color, Color){}
picker.properties[Padding] = Px(0) picker.properties[Padding] = Px(0)
picker.dataListInit()
} }
func (picker *colorPickerData) String() string { func (picker *colorPickerData) String() string {
@ -50,7 +52,7 @@ func (picker *colorPickerData) normalizeTag(tag string) string {
return ColorPickerValue return ColorPickerValue
} }
return tag return picker.normalizeDataListTag(tag)
} }
func (picker *colorPickerData) Remove(tag string) { func (picker *colorPickerData) Remove(tag string) {
@ -70,6 +72,11 @@ func (picker *colorPickerData) remove(tag string) {
delete(picker.properties, ColorPickerValue) delete(picker.properties, ColorPickerValue)
picker.colorChanged(oldColor) picker.colorChanged(oldColor)
case DataList:
if len(picker.dataList.dataList) > 0 {
picker.setDataList(picker, []string{}, true)
}
default: default:
picker.viewData.remove(tag) picker.viewData.remove(tag)
} }
@ -105,6 +112,9 @@ func (picker *colorPickerData) set(tag string, value any) bool {
return true return true
} }
case DataList:
return picker.setDataList(picker, value, picker.created)
default: default:
return picker.viewData.set(tag, value) return picker.viewData.set(tag, value)
} }
@ -132,6 +142,9 @@ func (picker *colorPickerData) get(tag string) any {
case ColorChangedEvent: case ColorChangedEvent:
return picker.colorChangedListeners return picker.colorChangedListeners
case DataList:
return picker.dataList.dataList
default: default:
return picker.viewData.get(tag) return picker.viewData.get(tag)
} }
@ -141,6 +154,10 @@ func (picker *colorPickerData) htmlTag() string {
return "input" return "input"
} }
func (picker *colorPickerData) htmlSubviews(self View, buffer *strings.Builder) {
picker.dataListHtmlSubviews(self, buffer)
}
func (picker *colorPickerData) htmlProperties(self View, buffer *strings.Builder) { func (picker *colorPickerData) htmlProperties(self View, buffer *strings.Builder) {
picker.viewData.htmlProperties(self, buffer) picker.viewData.htmlProperties(self, buffer)
@ -152,6 +169,8 @@ func (picker *colorPickerData) htmlProperties(self View, buffer *strings.Builder
if picker.getRaw(ClickEvent) == nil { if picker.getRaw(ClickEvent) == nil {
buffer.WriteString(` onclick="stopEventPropagation(this, event)"`) buffer.WriteString(` onclick="stopEventPropagation(this, event)"`)
} }
picker.dataListHtmlProperies(picker, buffer)
} }
func (picker *colorPickerData) handleCommand(self View, command string, data DataObject) bool { func (picker *colorPickerData) handleCommand(self View, command string, data DataObject) bool {

115
dataList.go Normal file
View File

@ -0,0 +1,115 @@
package rui
import "strings"
const (
// DataList is the constant for the "data-list" property tag.
DataList = "data-list"
)
type dataList struct {
dataList []string
dataListHtml bool
}
func (list *dataList) dataListInit() {
list.dataList = []string{}
}
func (list *dataList) dataListID(view View) string {
return view.htmlID() + "-datalist"
}
func (list *dataList) normalizeDataListTag(tag string) string {
switch tag {
case "datalist":
return DataList
}
return tag
}
func (list *dataList) setDataList(view View, value any, created bool) bool {
items, ok := anyToStringArray(value)
if !ok {
notCompatibleType(DataList, value)
return false
}
list.dataList = items
if created {
session := view.Session()
dataListID := list.dataListID(view)
buffer := allocStringBuilder()
defer freeStringBuilder(buffer)
if list.dataListHtml {
list.dataListItemsHtml(buffer)
session.updateInnerHTML(dataListID, buffer.String())
} else {
list.dataListHtmlCode(view, buffer)
session.appendToInnerHTML(view.parentHTMLID(), buffer.String())
list.dataListHtml = true
session.updateProperty(view.htmlID(), "list", dataListID)
}
}
return true
}
func (list *dataList) dataListHtmlSubviews(view View, buffer *strings.Builder) {
if len(list.dataList) > 0 {
list.dataListHtmlCode(view, buffer)
list.dataListHtml = true
} else {
list.dataListHtml = false
}
}
func (list *dataList) dataListHtmlCode(view View, buffer *strings.Builder) {
buffer.WriteString(`<datalist id="`)
buffer.WriteString(list.dataListID(view))
buffer.WriteString(`">`)
list.dataListItemsHtml(buffer)
buffer.WriteString(`</datalist>`)
}
func (list *dataList) dataListItemsHtml(buffer *strings.Builder) {
for _, text := range list.dataList {
if strings.ContainsRune(text, '"') {
text = strings.ReplaceAll(text, `"`, `&#34;`)
}
if strings.ContainsRune(text, '\n') {
text = strings.ReplaceAll(text, "\n", `\n`)
}
buffer.WriteString(`<option value="`)
buffer.WriteString(text)
buffer.WriteString(`"></option>`)
}
}
func (list *dataList) dataListHtmlProperies(view View, buffer *strings.Builder) {
if len(list.dataList) > 0 {
buffer.WriteString(` list="`)
buffer.WriteString(list.dataListID(view))
buffer.WriteString(`"`)
}
}
// GetDataList returns the data list of an editor.
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
func GetDataList(view View, subviewID ...string) []string {
if len(subviewID) > 0 && subviewID[0] != "" {
view = ViewByID(view, subviewID[0])
}
if view != nil {
if value := view.Get(DataList); value != nil {
if list, ok := value.([]string); ok {
return list
}
}
}
return []string{}
}

View File

@ -22,6 +22,7 @@ type DatePicker interface {
type datePickerData struct { type datePickerData struct {
viewData viewData
dataList
dateChangedListeners []func(DatePicker, time.Time, time.Time) dateChangedListeners []func(DatePicker, time.Time, time.Time)
} }
@ -42,6 +43,7 @@ func (picker *datePickerData) init(session Session) {
picker.tag = "DatePicker" picker.tag = "DatePicker"
picker.hasHtmlDisabled = true picker.hasHtmlDisabled = true
picker.dateChangedListeners = []func(DatePicker, time.Time, time.Time){} picker.dateChangedListeners = []func(DatePicker, time.Time, time.Time){}
picker.dataListInit()
} }
func (picker *datePickerData) String() string { func (picker *datePickerData) String() string {
@ -108,6 +110,11 @@ func (picker *datePickerData) remove(tag string) {
return return
} }
case DataList:
if len(picker.dataList.dataList) > 0 {
picker.setDataList(picker, []string{}, true)
}
default: default:
picker.viewData.remove(tag) picker.viewData.remove(tag)
return return
@ -247,6 +254,9 @@ func (picker *datePickerData) set(tag string, value any) bool {
picker.propertyChangedEvent(tag) picker.propertyChangedEvent(tag)
return true return true
case DataList:
return picker.setDataList(picker, value, picker.created)
default: default:
return picker.viewData.set(tag, value) return picker.viewData.set(tag, value)
} }
@ -262,6 +272,9 @@ func (picker *datePickerData) get(tag string) any {
case DateChangedEvent: case DateChangedEvent:
return picker.dateChangedListeners return picker.dateChangedListeners
case DataList:
return picker.dataList.dataList
default: default:
return picker.viewData.get(tag) return picker.viewData.get(tag)
} }
@ -271,6 +284,10 @@ func (picker *datePickerData) htmlTag() string {
return "input" return "input"
} }
func (picker *datePickerData) htmlSubviews(self View, buffer *strings.Builder) {
picker.dataListHtmlSubviews(self, buffer)
}
func (picker *datePickerData) htmlProperties(self View, buffer *strings.Builder) { func (picker *datePickerData) htmlProperties(self View, buffer *strings.Builder) {
picker.viewData.htmlProperties(self, buffer) picker.viewData.htmlProperties(self, buffer)
@ -302,6 +319,8 @@ func (picker *datePickerData) htmlProperties(self View, buffer *strings.Builder)
if picker.getRaw(ClickEvent) == nil { if picker.getRaw(ClickEvent) == nil {
buffer.WriteString(` onclick="stopEventPropagation(this, event)"`) buffer.WriteString(` onclick="stopEventPropagation(this, event)"`)
} }
picker.dataListHtmlProperies(picker, buffer)
} }
func (picker *datePickerData) handleCommand(self View, command string, data DataObject) bool { func (picker *datePickerData) handleCommand(self View, command string, data DataObject) bool {

View File

@ -147,26 +147,129 @@ func (list *dropDownListData) set(tag string, value any) bool {
} }
func (list *dropDownListData) setItems(value any) bool { func (list *dropDownListData) setItems(value any) bool {
items, ok := anyToStringArray(value)
if !ok {
notCompatibleType(Items, value)
return false
}
list.items = items
if list.created {
updateInnerHTML(list.htmlID(), list.session)
}
list.propertyChangedEvent(Items)
return true
}
func intArrayToStringArray[T int | uint | int8 | uint8 | int16 | uint16 | int32 | uint32 | int64 | uint64](array []T) []string {
items := make([]string, len(array))
for i, val := range array {
items[i] = strconv.Itoa(int(val))
}
return items
}
func anyToStringArray(value any) ([]string, bool) {
switch value := value.(type) { switch value := value.(type) {
case string: case string:
list.items = []string{value} return []string{value}, true
case []string: case []string:
list.items = value return value, true
case []DataValue: case []DataValue:
list.items = make([]string, 0, len(value)) items := make([]string, 0, len(value))
for _, val := range value { for _, val := range value {
if !val.IsObject() { if !val.IsObject() {
list.items = append(list.items, val.Value()) items = append(items, val.Value())
} }
} }
return items, true
case []fmt.Stringer: case []fmt.Stringer:
list.items = make([]string, len(value)) items := make([]string, len(value))
for i, str := range value { for i, str := range value {
list.items[i] = str.String() items[i] = str.String()
} }
return items, true
case []Color:
items := make([]string, len(value))
for i, str := range value {
items[i] = str.String()
}
return items, true
case []SizeUnit:
items := make([]string, len(value))
for i, str := range value {
items[i] = str.String()
}
return items, true
case []AngleUnit:
items := make([]string, len(value))
for i, str := range value {
items[i] = str.String()
}
return items, true
case []float32:
items := make([]string, len(value))
for i, val := range value {
items[i] = fmt.Sprintf("%g", float64(val))
}
return items, true
case []float64:
items := make([]string, len(value))
for i, val := range value {
items[i] = fmt.Sprintf("%g", val)
}
return items, true
case []int:
return intArrayToStringArray(value), true
case []uint:
return intArrayToStringArray(value), true
case []int8:
return intArrayToStringArray(value), true
case []uint8:
return intArrayToStringArray(value), true
case []int16:
return intArrayToStringArray(value), true
case []uint16:
return intArrayToStringArray(value), true
case []int32:
return intArrayToStringArray(value), true
case []uint32:
return intArrayToStringArray(value), true
case []int64:
return intArrayToStringArray(value), true
case []uint64:
return intArrayToStringArray(value), true
case []bool:
items := make([]string, len(value))
for i, val := range value {
if val {
items[i] = "true"
} else {
items[i] = "false"
}
}
return items, true
case []any: case []any:
items := make([]string, 0, len(value)) items := make([]string, 0, len(value))
@ -198,25 +301,15 @@ func (list *dropDownListData) setItems(value any) bool {
if n, ok := isInt(v); ok { if n, ok := isInt(v); ok {
items = append(items, strconv.Itoa(n)) items = append(items, strconv.Itoa(n))
} else { } else {
notCompatibleType(Items, value) return []string{}, false
return false
} }
} }
} }
list.items = items return items, true
default:
notCompatibleType(Items, value)
return false
} }
if list.created { return []string{}, false
updateInnerHTML(list.htmlID(), list.session)
}
list.propertyChangedEvent(Items)
return true
} }
func (list *dropDownListData) setDisabledItems(value any) bool { func (list *dropDownListData) setDisabledItems(value any) bool {

View File

@ -8,10 +8,13 @@ import (
const ( const (
// EditTextChangedEvent is the constant for the "edit-text-changed" property tag. // EditTextChangedEvent is the constant for the "edit-text-changed" property tag.
EditTextChangedEvent = "edit-text-changed" EditTextChangedEvent = "edit-text-changed"
// EditViewType is the constant for the "edit-view-type" property tag. // EditViewType is the constant for the "edit-view-type" property tag.
EditViewType = "edit-view-type" EditViewType = "edit-view-type"
// EditViewPattern is the constant for the "edit-view-pattern" property tag. // EditViewPattern is the constant for the "edit-view-pattern" property tag.
EditViewPattern = "edit-view-pattern" EditViewPattern = "edit-view-pattern"
// Spellcheck is the constant for the "spellcheck" property tag. // Spellcheck is the constant for the "spellcheck" property tag.
Spellcheck = "spellcheck" Spellcheck = "spellcheck"
) )
@ -41,6 +44,7 @@ type EditView interface {
type editViewData struct { type editViewData struct {
viewData viewData
dataList
textChangeListeners []func(EditView, string, string) textChangeListeners []func(EditView, string, string)
} }
@ -61,6 +65,7 @@ func (edit *editViewData) init(session Session) {
edit.hasHtmlDisabled = true edit.hasHtmlDisabled = true
edit.textChangeListeners = []func(EditView, string, string){} edit.textChangeListeners = []func(EditView, string, string){}
edit.tag = "EditView" edit.tag = "EditView"
edit.dataListInit()
} }
func (edit *editViewData) String() string { func (edit *editViewData) String() string {
@ -87,7 +92,7 @@ func (edit *editViewData) normalizeTag(tag string) string {
return EditWrap return EditWrap
} }
return tag return edit.normalizeDataListTag(tag)
} }
func (edit *editViewData) Remove(tag string) { func (edit *editViewData) Remove(tag string) {
@ -184,9 +189,13 @@ func (edit *editViewData) remove(tag string) {
} }
} }
case DataList:
if len(edit.dataList.dataList) > 0 {
edit.setDataList(edit, []string{}, true)
}
default: default:
edit.viewData.remove(tag) edit.viewData.remove(tag)
return
} }
} }
@ -324,6 +333,9 @@ func (edit *editViewData) set(tag string, value any) bool {
} }
return false return false
case DataList:
return edit.setDataList(edit, value, edit.created)
case EditTextChangedEvent: case EditTextChangedEvent:
listeners, ok := valueToEventWithOldListeners[EditView, string](value) listeners, ok := valueToEventWithOldListeners[EditView, string](value)
if !ok { if !ok {
@ -345,8 +357,12 @@ func (edit *editViewData) Get(tag string) any {
} }
func (edit *editViewData) get(tag string) any { func (edit *editViewData) get(tag string) any {
if tag == EditTextChangedEvent { switch tag {
case EditTextChangedEvent:
return edit.textChangeListeners return edit.textChangeListeners
case DataList:
return edit.dataList.dataList
} }
return edit.viewData.get(tag) return edit.viewData.get(tag)
} }
@ -383,6 +399,10 @@ func (edit *editViewData) htmlTag() string {
return "input" return "input"
} }
func (edit *editViewData) htmlSubviews(self View, buffer *strings.Builder) {
edit.dataListHtmlSubviews(self, buffer)
}
func (edit *editViewData) htmlProperties(self View, buffer *strings.Builder) { func (edit *editViewData) htmlProperties(self View, buffer *strings.Builder) {
edit.viewData.htmlProperties(self, buffer) edit.viewData.htmlProperties(self, buffer)
@ -462,6 +482,8 @@ func (edit *editViewData) htmlProperties(self View, buffer *strings.Builder) {
buffer.WriteString(convertText(text)) buffer.WriteString(convertText(text))
buffer.WriteByte('"') buffer.WriteByte('"')
} }
edit.dataListHtmlProperies(edit, buffer)
} }
func (edit *editViewData) handleCommand(self View, command string, data DataObject) bool { func (edit *editViewData) handleCommand(self View, command string, data DataObject) bool {

View File

@ -49,6 +49,7 @@ type NumberPicker interface {
type numberPickerData struct { type numberPickerData struct {
viewData viewData
dataList
numberChangedListeners []func(NumberPicker, float64, float64) numberChangedListeners []func(NumberPicker, float64, float64)
} }
@ -69,6 +70,7 @@ func (picker *numberPickerData) init(session Session) {
picker.tag = "NumberPicker" picker.tag = "NumberPicker"
picker.hasHtmlDisabled = true picker.hasHtmlDisabled = true
picker.numberChangedListeners = []func(NumberPicker, float64, float64){} picker.numberChangedListeners = []func(NumberPicker, float64, float64){}
picker.dataListInit()
} }
func (picker *numberPickerData) String() string { func (picker *numberPickerData) String() string {
@ -86,7 +88,7 @@ func (picker *numberPickerData) normalizeTag(tag string) string {
return "number-picker-" + tag return "number-picker-" + tag
} }
return tag return picker.normalizeDataListTag(tag)
} }
func (picker *numberPickerData) Remove(tag string) { func (picker *numberPickerData) Remove(tag string) {
@ -114,6 +116,11 @@ func (picker *numberPickerData) remove(tag string) {
picker.propertyChangedEvent(tag) picker.propertyChangedEvent(tag)
} }
case DataList:
if len(picker.dataList.dataList) > 0 {
picker.setDataList(picker, []string{}, true)
}
default: default:
picker.viewData.remove(tag) picker.viewData.remove(tag)
picker.propertyChanged(tag) picker.propertyChanged(tag)
@ -160,6 +167,9 @@ func (picker *numberPickerData) set(tag string, value any) bool {
return true return true
} }
case DataList:
return picker.setDataList(picker, value, picker.created)
default: default:
if picker.viewData.set(tag, value) { if picker.viewData.set(tag, value) {
picker.propertyChanged(tag) picker.propertyChanged(tag)
@ -206,6 +216,9 @@ func (picker *numberPickerData) get(tag string) any {
case NumberChangedEvent: case NumberChangedEvent:
return picker.numberChangedListeners return picker.numberChangedListeners
case DataList:
return picker.dataList.dataList
default: default:
return picker.viewData.get(tag) return picker.viewData.get(tag)
} }
@ -215,6 +228,10 @@ func (picker *numberPickerData) htmlTag() string {
return "input" return "input"
} }
func (picker *numberPickerData) htmlSubviews(self View, buffer *strings.Builder) {
picker.dataListHtmlSubviews(self, buffer)
}
func (picker *numberPickerData) htmlProperties(self View, buffer *strings.Builder) { func (picker *numberPickerData) htmlProperties(self View, buffer *strings.Builder) {
picker.viewData.htmlProperties(self, buffer) picker.viewData.htmlProperties(self, buffer)
@ -251,6 +268,8 @@ func (picker *numberPickerData) htmlProperties(self View, buffer *strings.Builde
buffer.WriteByte('"') buffer.WriteByte('"')
buffer.WriteString(` oninput="editViewInputEvent(this)"`) buffer.WriteString(` oninput="editViewInputEvent(this)"`)
picker.dataListHtmlProperies(picker, buffer)
} }
func (picker *numberPickerData) handleCommand(self View, command string, data DataObject) bool { func (picker *numberPickerData) handleCommand(self View, command string, data DataObject) bool {

View File

@ -22,6 +22,7 @@ type TimePicker interface {
type timePickerData struct { type timePickerData struct {
viewData viewData
dataList
timeChangedListeners []func(TimePicker, time.Time, time.Time) timeChangedListeners []func(TimePicker, time.Time, time.Time)
} }
@ -42,6 +43,7 @@ func (picker *timePickerData) init(session Session) {
picker.tag = "TimePicker" picker.tag = "TimePicker"
picker.hasHtmlDisabled = true picker.hasHtmlDisabled = true
picker.timeChangedListeners = []func(TimePicker, time.Time, time.Time){} picker.timeChangedListeners = []func(TimePicker, time.Time, time.Time){}
picker.dataListInit()
} }
func (picker *timePickerData) String() string { func (picker *timePickerData) String() string {
@ -108,6 +110,11 @@ func (picker *timePickerData) remove(tag string) {
return return
} }
case DataList:
if len(picker.dataList.dataList) > 0 {
picker.setDataList(picker, []string{}, true)
}
default: default:
picker.viewData.remove(tag) picker.viewData.remove(tag)
return return
@ -235,6 +242,9 @@ func (picker *timePickerData) set(tag string, value any) bool {
picker.propertyChangedEvent(tag) picker.propertyChangedEvent(tag)
return true return true
case DataList:
return picker.setDataList(picker, value, picker.created)
default: default:
return picker.viewData.set(tag, value) return picker.viewData.set(tag, value)
} }
@ -250,6 +260,9 @@ func (picker *timePickerData) get(tag string) any {
case TimeChangedEvent: case TimeChangedEvent:
return picker.timeChangedListeners return picker.timeChangedListeners
case DataList:
return picker.dataList.dataList
default: default:
return picker.viewData.get(tag) return picker.viewData.get(tag)
} }
@ -259,6 +272,10 @@ func (picker *timePickerData) htmlTag() string {
return "input" return "input"
} }
func (picker *timePickerData) htmlSubviews(self View, buffer *strings.Builder) {
picker.dataListHtmlSubviews(self, buffer)
}
func (picker *timePickerData) htmlProperties(self View, buffer *strings.Builder) { func (picker *timePickerData) htmlProperties(self View, buffer *strings.Builder) {
picker.viewData.htmlProperties(self, buffer) picker.viewData.htmlProperties(self, buffer)
@ -290,6 +307,8 @@ func (picker *timePickerData) htmlProperties(self View, buffer *strings.Builder)
if picker.getRaw(ClickEvent) == nil { if picker.getRaw(ClickEvent) == nil {
buffer.WriteString(` onclick="stopEventPropagation(this, event)"`) buffer.WriteString(` onclick="stopEventPropagation(this, event)"`)
} }
picker.dataListHtmlProperies(picker, buffer)
} }
func (picker *timePickerData) handleCommand(self View, command string, data DataObject) bool { func (picker *timePickerData) handleCommand(self View, command string, data DataObject) bool {