mirror of https://github.com/anoshenko/rui.git
				
				
				
			Add a listener for changing a property value
This commit is contained in:
		
							parent
							
								
									584983b818
								
							
						
					
					
						commit
						7e2804f002
					
				|  | @ -53,6 +53,7 @@ func (canvasView *canvasViewData) remove(tag string) { | |||
| 	if tag == DrawFunction { | ||||
| 		canvasView.drawer = nil | ||||
| 		canvasView.Redraw() | ||||
| 		canvasView.propertyChangedEvent(tag) | ||||
| 	} else { | ||||
| 		canvasView.viewData.remove(tag) | ||||
| 	} | ||||
|  | @ -73,6 +74,7 @@ func (canvasView *canvasViewData) set(tag string, value interface{}) bool { | |||
| 			return false | ||||
| 		} | ||||
| 		canvasView.Redraw() | ||||
| 		canvasView.propertyChangedEvent(tag) | ||||
| 		return true | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										93
									
								
								checkbox.go
								
								
								
								
							
							
						
						
									
										93
									
								
								checkbox.go
								
								
								
								
							|  | @ -57,13 +57,16 @@ func (button *checkboxData) Get(tag string) interface{} { | |||
| } | ||||
| 
 | ||||
| func (button *checkboxData) Set(tag string, value interface{}) bool { | ||||
| 	switch strings.ToLower(tag) { | ||||
| 	return button.set(tag, value) | ||||
| } | ||||
| 
 | ||||
| func (button *checkboxData) set(tag string, value interface{}) bool { | ||||
| 	switch tag { | ||||
| 	case CheckboxChangedEvent: | ||||
| 		ok := button.setChangedListener(value) | ||||
| 		if !ok { | ||||
| 		if !button.setChangedListener(value) { | ||||
| 			notCompatibleType(tag, value) | ||||
| 			return false | ||||
| 		} | ||||
| 		return ok | ||||
| 
 | ||||
| 	case Checked: | ||||
| 		oldChecked := button.checked() | ||||
|  | @ -76,46 +79,60 @@ func (button *checkboxData) Set(tag string, value interface{}) bool { | |||
| 				button.changedCheckboxState(checked) | ||||
| 			} | ||||
| 		} | ||||
| 		return true | ||||
| 
 | ||||
| 	case CheckboxHorizontalAlign, CheckboxVerticalAlign: | ||||
| 		if button.setEnumProperty(tag, value, enumProperties[tag].values) { | ||||
| 			if button.created { | ||||
| 				htmlID := button.htmlID() | ||||
| 				updateCSSStyle(htmlID, button.session) | ||||
| 				updateInnerHTML(htmlID, button.session) | ||||
| 			} | ||||
| 			return true | ||||
| 		if !button.setEnumProperty(tag, value, enumProperties[tag].values) { | ||||
| 			return false | ||||
| 		} | ||||
| 		if button.created { | ||||
| 			htmlID := button.htmlID() | ||||
| 			updateCSSStyle(htmlID, button.session) | ||||
| 			updateInnerHTML(htmlID, button.session) | ||||
| 		} | ||||
| 		return false | ||||
| 
 | ||||
| 	case VerticalAlign: | ||||
| 		if button.setEnumProperty(tag, value, enumProperties[tag].values) { | ||||
| 			if button.created { | ||||
| 				updateCSSProperty(button.htmlID()+"content", "align-items", button.cssVerticalAlign(), button.session) | ||||
| 			} | ||||
| 			return true | ||||
| 		if !button.setEnumProperty(tag, value, enumProperties[tag].values) { | ||||
| 			return false | ||||
| 		} | ||||
| 		if button.created { | ||||
| 			updateCSSProperty(button.htmlID()+"content", "align-items", button.cssVerticalAlign(), button.session) | ||||
| 		} | ||||
| 		return false | ||||
| 
 | ||||
| 	case HorizontalAlign: | ||||
| 		if button.setEnumProperty(tag, value, enumProperties[tag].values) { | ||||
| 			if button.created { | ||||
| 				updateCSSProperty(button.htmlID()+"content", "justify-items", button.cssHorizontalAlign(), button.session) | ||||
| 			} | ||||
| 			return true | ||||
| 		if !button.setEnumProperty(tag, value, enumProperties[tag].values) { | ||||
| 			return false | ||||
| 		} | ||||
| 		if button.created { | ||||
| 			updateCSSProperty(button.htmlID()+"content", "justify-items", button.cssHorizontalAlign(), button.session) | ||||
| 		} | ||||
| 		return false | ||||
| 
 | ||||
| 	case CellVerticalAlign, CellHorizontalAlign, CellWidth, CellHeight: | ||||
| 		return false | ||||
| 
 | ||||
| 	default: | ||||
| 		return button.viewsContainerData.set(tag, value) | ||||
| 	} | ||||
| 
 | ||||
| 	return button.viewsContainerData.Set(tag, value) | ||||
| 	button.propertyChangedEvent(tag) | ||||
| 	return true | ||||
| } | ||||
| 
 | ||||
| func (button *checkboxData) Remove(tag string) { | ||||
| 	switch strings.ToLower(tag) { | ||||
| 	button.remove(strings.ToLower(tag)) | ||||
| } | ||||
| 
 | ||||
| func (button *checkboxData) remove(tag string) { | ||||
| 	switch tag { | ||||
| 	case ClickEvent: | ||||
| 		if !button.viewsContainerData.set(ClickEvent, checkboxClickListener) { | ||||
| 			delete(button.properties, tag) | ||||
| 		} | ||||
| 
 | ||||
| 	case KeyDownEvent: | ||||
| 		if !button.viewsContainerData.set(KeyDownEvent, checkboxKeyListener) { | ||||
| 			delete(button.properties, tag) | ||||
| 		} | ||||
| 
 | ||||
| 	case CheckboxChangedEvent: | ||||
| 		if len(button.checkedListeners) > 0 { | ||||
| 			button.checkedListeners = []func(Checkbox, bool){} | ||||
|  | @ -124,27 +141,35 @@ func (button *checkboxData) Remove(tag string) { | |||
| 	case Checked: | ||||
| 		oldChecked := button.checked() | ||||
| 		delete(button.properties, tag) | ||||
| 		if oldChecked { | ||||
| 		if button.created && oldChecked { | ||||
| 			button.changedCheckboxState(false) | ||||
| 		} | ||||
| 
 | ||||
| 	case CheckboxHorizontalAlign, CheckboxVerticalAlign: | ||||
| 		delete(button.properties, tag) | ||||
| 		htmlID := button.htmlID() | ||||
| 		updateCSSStyle(htmlID, button.session) | ||||
| 		updateInnerHTML(htmlID, button.session) | ||||
| 		if button.created { | ||||
| 			htmlID := button.htmlID() | ||||
| 			updateCSSStyle(htmlID, button.session) | ||||
| 			updateInnerHTML(htmlID, button.session) | ||||
| 		} | ||||
| 
 | ||||
| 	case VerticalAlign: | ||||
| 		delete(button.properties, tag) | ||||
| 		updateCSSProperty(button.htmlID()+"content", "align-items", button.cssVerticalAlign(), button.session) | ||||
| 		if button.created { | ||||
| 			updateCSSProperty(button.htmlID()+"content", "align-items", button.cssVerticalAlign(), button.session) | ||||
| 		} | ||||
| 
 | ||||
| 	case HorizontalAlign: | ||||
| 		delete(button.properties, tag) | ||||
| 		updateCSSProperty(button.htmlID()+"content", "justify-items", button.cssHorizontalAlign(), button.session) | ||||
| 		if button.created { | ||||
| 			updateCSSProperty(button.htmlID()+"content", "justify-items", button.cssHorizontalAlign(), button.session) | ||||
| 		} | ||||
| 
 | ||||
| 	default: | ||||
| 		button.viewsContainerData.Remove(tag) | ||||
| 		button.viewsContainerData.remove(tag) | ||||
| 		return | ||||
| 	} | ||||
| 	button.propertyChangedEvent(tag) | ||||
| } | ||||
| 
 | ||||
| func (button *checkboxData) checked() bool { | ||||
|  |  | |||
|  | @ -56,7 +56,10 @@ func (picker *colorPickerData) Remove(tag string) { | |||
| func (picker *colorPickerData) remove(tag string) { | ||||
| 	switch tag { | ||||
| 	case ColorChangedEvent: | ||||
| 		picker.colorChangedListeners = []func(ColorPicker, Color){} | ||||
| 		if len(picker.colorChangedListeners) > 0 { | ||||
| 			picker.colorChangedListeners = []func(ColorPicker, Color){} | ||||
| 			picker.propertyChangedEvent(tag) | ||||
| 		} | ||||
| 
 | ||||
| 	case ColorPickerValue: | ||||
| 		oldColor := GetColorPickerValue(picker, "") | ||||
|  | @ -131,15 +134,13 @@ func (picker *colorPickerData) set(tag string, value interface{}) bool { | |||
| 			} | ||||
| 			picker.colorChangedListeners = listeners | ||||
| 		} | ||||
| 		picker.propertyChangedEvent(tag) | ||||
| 		return true | ||||
| 
 | ||||
| 	case ColorPickerValue: | ||||
| 		oldColor := GetColorPickerValue(picker, "") | ||||
| 		if picker.setColorProperty(ColorPickerValue, value) { | ||||
| 			newValue := GetColorPickerValue(picker, "") | ||||
| 			if oldColor != newValue { | ||||
| 				picker.colorChanged(oldColor) | ||||
| 			} | ||||
| 			picker.colorChanged(oldColor) | ||||
| 			return true | ||||
| 		} | ||||
| 
 | ||||
|  | @ -150,12 +151,14 @@ func (picker *colorPickerData) set(tag string, value interface{}) bool { | |||
| } | ||||
| 
 | ||||
| func (picker *colorPickerData) colorChanged(oldColor Color) { | ||||
| 	newColor := GetColorPickerValue(picker, "") | ||||
| 	if oldColor != newColor { | ||||
| 		picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, picker.htmlID(), newColor.rgbString())) | ||||
| 	if newColor := GetColorPickerValue(picker, ""); oldColor != newColor { | ||||
| 		if picker.created { | ||||
| 			picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, picker.htmlID(), newColor.rgbString())) | ||||
| 		} | ||||
| 		for _, listener := range picker.colorChangedListeners { | ||||
| 			listener(picker, newColor) | ||||
| 		} | ||||
| 		picker.propertyChangedEvent(ColorTag) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -188,7 +191,7 @@ func (picker *colorPickerData) htmlProperties(self View, buffer *strings.Builder | |||
| } | ||||
| 
 | ||||
| func (picker *colorPickerData) htmlDisabledProperties(self View, buffer *strings.Builder) { | ||||
| 	if IsDisabled(self) { | ||||
| 	if IsDisabled(self, "") { | ||||
| 		buffer.WriteString(` disabled`) | ||||
| 	} | ||||
| 	picker.viewData.htmlDisabledProperties(self, buffer) | ||||
|  |  | |||
|  | @ -82,12 +82,14 @@ func (columnLayout *columnLayoutData) Remove(tag string) { | |||
| 
 | ||||
| func (columnLayout *columnLayoutData) remove(tag string) { | ||||
| 	columnLayout.viewsContainerData.remove(tag) | ||||
| 	switch tag { | ||||
| 	case ColumnCount, ColumnWidth, ColumnGap: | ||||
| 		updateCSSProperty(columnLayout.htmlID(), tag, "", columnLayout.Session()) | ||||
| 	if columnLayout.created { | ||||
| 		switch tag { | ||||
| 		case ColumnCount, ColumnWidth, ColumnGap: | ||||
| 			updateCSSProperty(columnLayout.htmlID(), tag, "", columnLayout.Session()) | ||||
| 
 | ||||
| 	case ColumnSeparator: | ||||
| 		updateCSSProperty(columnLayout.htmlID(), "column-rule", "", columnLayout.Session()) | ||||
| 		case ColumnSeparator: | ||||
| 			updateCSSProperty(columnLayout.htmlID(), "column-rule", "", columnLayout.Session()) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -101,22 +103,11 @@ func (columnLayout *columnLayoutData) set(tag string, value interface{}) bool { | |||
| 		return true | ||||
| 	} | ||||
| 
 | ||||
| 	switch tag { | ||||
| 	case ColumnCount: | ||||
| 		if columnLayout.setIntProperty(tag, value) { | ||||
| 			session := columnLayout.Session() | ||||
| 			if count, ok := intProperty(columnLayout, tag, session, 0); ok && count > 0 { | ||||
| 				updateCSSProperty(columnLayout.htmlID(), tag, strconv.Itoa(count), session) | ||||
| 			} else { | ||||
| 				updateCSSProperty(columnLayout.htmlID(), tag, "auto", session) | ||||
| 			} | ||||
| 			return true | ||||
| 		} | ||||
| 	if !columnLayout.viewsContainerData.set(tag, value) { | ||||
| 		return false | ||||
| 	} | ||||
| 
 | ||||
| 	ok := columnLayout.viewsContainerData.set(tag, value) | ||||
| 	if ok { | ||||
| 	if columnLayout.created { | ||||
| 		switch tag { | ||||
| 		case ColumnSeparator: | ||||
| 			css := "" | ||||
|  | @ -126,9 +117,17 @@ func (columnLayout *columnLayoutData) set(tag string, value interface{}) bool { | |||
| 				css = separator.cssValue(columnLayout.Session()) | ||||
| 			} | ||||
| 			updateCSSProperty(columnLayout.htmlID(), "column-rule", css, session) | ||||
| 
 | ||||
| 		case ColumnCount: | ||||
| 			session := columnLayout.Session() | ||||
| 			if count, ok := intProperty(columnLayout, tag, session, 0); ok && count > 0 { | ||||
| 				updateCSSProperty(columnLayout.htmlID(), tag, strconv.Itoa(count), session) | ||||
| 			} else { | ||||
| 				updateCSSProperty(columnLayout.htmlID(), tag, "auto", session) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return ok | ||||
| 	return true | ||||
| } | ||||
| 
 | ||||
| // GetColumnCount returns int value which specifies number of columns into which the content of
 | ||||
|  |  | |||
|  | @ -68,6 +68,10 @@ func (customView *CustomViewData) SetAnimated(tag string, value interface{}, ani | |||
| 	return customView.superView.SetAnimated(tag, value, animation) | ||||
| } | ||||
| 
 | ||||
| func (customView *CustomViewData) SetChangeListener(tag string, listener func(View, string)) { | ||||
| 	customView.superView.SetChangeListener(tag, listener) | ||||
| } | ||||
| 
 | ||||
| // Remove removes the property with name defined by the argument
 | ||||
| func (customView *CustomViewData) Remove(tag string) { | ||||
| 	customView.superView.Remove(tag) | ||||
|  |  | |||
|  | @ -63,28 +63,47 @@ func (picker *datePickerData) remove(tag string) { | |||
| 	case DateChangedEvent: | ||||
| 		if len(picker.dateChangedListeners) > 0 { | ||||
| 			picker.dateChangedListeners = []func(DatePicker, time.Time){} | ||||
| 			picker.propertyChangedEvent(tag) | ||||
| 		} | ||||
| 		return | ||||
| 
 | ||||
| 	case DatePickerMin: | ||||
| 		delete(picker.properties, DatePickerMin) | ||||
| 		removeProperty(picker.htmlID(), Min, picker.session) | ||||
| 		if picker.created { | ||||
| 			removeProperty(picker.htmlID(), Min, picker.session) | ||||
| 		} | ||||
| 
 | ||||
| 	case DatePickerMax: | ||||
| 		delete(picker.properties, DatePickerMax) | ||||
| 		removeProperty(picker.htmlID(), Max, picker.session) | ||||
| 		if picker.created { | ||||
| 			removeProperty(picker.htmlID(), Max, picker.session) | ||||
| 		} | ||||
| 
 | ||||
| 	case DatePickerStep: | ||||
| 		delete(picker.properties, DatePickerMax) | ||||
| 		removeProperty(picker.htmlID(), Step, picker.session) | ||||
| 		if picker.created { | ||||
| 			removeProperty(picker.htmlID(), Step, picker.session) | ||||
| 		} | ||||
| 
 | ||||
| 	case DatePickerValue: | ||||
| 		delete(picker.properties, DatePickerValue) | ||||
| 		updateProperty(picker.htmlID(), Value, time.Now().Format(dateFormat), picker.session) | ||||
| 		if _, ok := picker.properties[DatePickerValue]; ok { | ||||
| 			delete(picker.properties, DatePickerValue) | ||||
| 			date := GetDatePickerValue(picker, "") | ||||
| 			if picker.created { | ||||
| 				picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, picker.htmlID(), date.Format(dateFormat))) | ||||
| 			} | ||||
| 			for _, listener := range picker.dateChangedListeners { | ||||
| 				listener(picker, date) | ||||
| 			} | ||||
| 		} else { | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 	default: | ||||
| 		picker.viewData.remove(tag) | ||||
| 		picker.propertyChanged(tag) | ||||
| 		return | ||||
| 	} | ||||
| 	picker.propertyChangedEvent(tag) | ||||
| } | ||||
| 
 | ||||
| func (picker *datePickerData) Set(tag string, value interface{}) bool { | ||||
|  | @ -98,7 +117,6 @@ func (picker *datePickerData) set(tag string, value interface{}) bool { | |||
| 	} | ||||
| 
 | ||||
| 	setTimeValue := func(tag string) (time.Time, bool) { | ||||
| 		//old, oldOK := getDateProperty(picker, tag, shortTag)
 | ||||
| 		switch value := value.(type) { | ||||
| 		case time.Time: | ||||
| 			picker.properties[tag] = value | ||||
|  | @ -122,7 +140,10 @@ func (picker *datePickerData) set(tag string, value interface{}) bool { | |||
| 		old, oldOK := getDateProperty(picker, DatePickerMin, Min) | ||||
| 		if date, ok := setTimeValue(DatePickerMin); ok { | ||||
| 			if !oldOK || date != old { | ||||
| 				updateProperty(picker.htmlID(), Min, date.Format(dateFormat), picker.session) | ||||
| 				if picker.created { | ||||
| 					updateProperty(picker.htmlID(), Min, date.Format(dateFormat), picker.session) | ||||
| 				} | ||||
| 				picker.propertyChangedEvent(tag) | ||||
| 			} | ||||
| 			return true | ||||
| 		} | ||||
|  | @ -131,7 +152,10 @@ func (picker *datePickerData) set(tag string, value interface{}) bool { | |||
| 		old, oldOK := getDateProperty(picker, DatePickerMax, Max) | ||||
| 		if date, ok := setTimeValue(DatePickerMax); ok { | ||||
| 			if !oldOK || date != old { | ||||
| 				updateProperty(picker.htmlID(), Max, date.Format(dateFormat), picker.session) | ||||
| 				if picker.created { | ||||
| 					updateProperty(picker.htmlID(), Max, date.Format(dateFormat), picker.session) | ||||
| 				} | ||||
| 				picker.propertyChangedEvent(tag) | ||||
| 			} | ||||
| 			return true | ||||
| 		} | ||||
|  | @ -139,13 +163,15 @@ func (picker *datePickerData) set(tag string, value interface{}) bool { | |||
| 	case DatePickerStep: | ||||
| 		oldStep := GetDatePickerStep(picker, "") | ||||
| 		if picker.setIntProperty(DatePickerStep, value) { | ||||
| 			step := GetDatePickerStep(picker, "") | ||||
| 			if oldStep != step { | ||||
| 				if step > 0 { | ||||
| 					updateProperty(picker.htmlID(), Step, strconv.Itoa(step), picker.session) | ||||
| 				} else { | ||||
| 					removeProperty(picker.htmlID(), Step, picker.session) | ||||
| 			if step := GetDatePickerStep(picker, ""); oldStep != step { | ||||
| 				if picker.created { | ||||
| 					if step > 0 { | ||||
| 						updateProperty(picker.htmlID(), Step, strconv.Itoa(step), picker.session) | ||||
| 					} else { | ||||
| 						removeProperty(picker.htmlID(), Step, picker.session) | ||||
| 					} | ||||
| 				} | ||||
| 				picker.propertyChangedEvent(tag) | ||||
| 			} | ||||
| 			return true | ||||
| 		} | ||||
|  | @ -153,11 +179,14 @@ func (picker *datePickerData) set(tag string, value interface{}) bool { | |||
| 	case DatePickerValue: | ||||
| 		oldDate := GetDatePickerValue(picker, "") | ||||
| 		if date, ok := setTimeValue(DatePickerMax); ok { | ||||
| 			picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, picker.htmlID(), date.Format(dateFormat))) | ||||
| 			if date != oldDate { | ||||
| 				if picker.created { | ||||
| 					picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, picker.htmlID(), date.Format(dateFormat))) | ||||
| 				} | ||||
| 				for _, listener := range picker.dateChangedListeners { | ||||
| 					listener(picker, date) | ||||
| 				} | ||||
| 				picker.propertyChangedEvent(tag) | ||||
| 			} | ||||
| 			return true | ||||
| 		} | ||||
|  | @ -214,13 +243,11 @@ func (picker *datePickerData) set(tag string, value interface{}) bool { | |||
| 			} | ||||
| 			picker.dateChangedListeners = listeners | ||||
| 		} | ||||
| 		picker.propertyChangedEvent(tag) | ||||
| 		return true | ||||
| 
 | ||||
| 	default: | ||||
| 		if picker.viewData.set(tag, value) { | ||||
| 			picker.propertyChanged(tag) | ||||
| 			return true | ||||
| 		} | ||||
| 		return picker.viewData.set(tag, value) | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
|  | @ -274,7 +301,7 @@ func (picker *datePickerData) htmlProperties(self View, buffer *strings.Builder) | |||
| } | ||||
| 
 | ||||
| func (picker *datePickerData) htmlDisabledProperties(self View, buffer *strings.Builder) { | ||||
| 	if IsDisabled(self) { | ||||
| 	if IsDisabled(self, "") { | ||||
| 		buffer.WriteString(` disabled`) | ||||
| 	} | ||||
| 	picker.viewData.htmlDisabledProperties(self, buffer) | ||||
|  |  | |||
|  | @ -57,14 +57,24 @@ func createTextStyleDemo(session rui.Session) rui.View { | |||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	rui.Set(view, "textStyleFont", rui.DropDownEvent, func(number int) { | ||||
| 	rui.SetChangeListener(view, "textStyleFont", rui.Current, func(v rui.View, tag string) { | ||||
| 		fonts := []string{"", "serif", "sans-serif", "\"Courier new\", monospace", "cursive", "fantasy"} | ||||
| 		if number > 0 && number < len(fonts) { | ||||
| 		if number := rui.GetDropDownCurrent(v, ""); number > 0 && number < len(fonts) { | ||||
| 			rui.Set(view, "textStyleText", rui.FontName, fonts[number]) | ||||
| 		} else { | ||||
| 			rui.Set(view, "textStyleText", rui.FontName, nil) | ||||
| 		} | ||||
| 	}) | ||||
| 	/* | ||||
| 		rui.Set(view, "textStyleFont", rui.DropDownEvent, func(number int) { | ||||
| 			fonts := []string{"", "serif", "sans-serif", "\"Courier new\", monospace", "cursive", "fantasy"} | ||||
| 			if number > 0 && number < len(fonts) { | ||||
| 				rui.Set(view, "textStyleText", rui.FontName, fonts[number]) | ||||
| 			} else { | ||||
| 				rui.Set(view, "textStyleText", rui.FontName, nil) | ||||
| 			} | ||||
| 		}) | ||||
| 	*/ | ||||
| 
 | ||||
| 	rui.Set(view, "textStyleSize", rui.DropDownEvent, func(number int) { | ||||
| 		sizes := []string{"1em", "14pt", "12px", "1.5em"} | ||||
|  |  | |||
|  | @ -2,6 +2,8 @@ package rui | |||
| 
 | ||||
| import "strings" | ||||
| 
 | ||||
| // TODO Expanded event
 | ||||
| 
 | ||||
| const ( | ||||
| 	// Summary is the constant for the "summary" property tag.
 | ||||
| 	// The contents of the "summary" property are used as the label for the disclosure widget.
 | ||||
|  | @ -45,18 +47,14 @@ func (detailsView *detailsViewData) Remove(tag string) { | |||
| } | ||||
| 
 | ||||
| func (detailsView *detailsViewData) remove(tag string) { | ||||
| 	if _, ok := detailsView.properties[tag]; ok { | ||||
| 	detailsView.viewsContainerData.remove(tag) | ||||
| 	if detailsView.created { | ||||
| 		switch tag { | ||||
| 		case Summary: | ||||
| 			delete(detailsView.properties, tag) | ||||
| 			updateInnerHTML(detailsView.htmlID(), detailsView.Session()) | ||||
| 
 | ||||
| 		case Expanded: | ||||
| 			delete(detailsView.properties, tag) | ||||
| 			removeProperty(detailsView.htmlID(), "open", detailsView.Session()) | ||||
| 
 | ||||
| 		default: | ||||
| 			detailsView.viewsContainerData.remove(tag) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -66,6 +64,11 @@ func (detailsView *detailsViewData) Set(tag string, value interface{}) bool { | |||
| } | ||||
| 
 | ||||
| func (detailsView *detailsViewData) set(tag string, value interface{}) bool { | ||||
| 	if value == nil { | ||||
| 		detailsView.remove(tag) | ||||
| 		return true | ||||
| 	} | ||||
| 
 | ||||
| 	switch tag { | ||||
| 	case Summary: | ||||
| 		switch value := value.(type) { | ||||
|  | @ -86,23 +89,29 @@ func (detailsView *detailsViewData) set(tag string, value interface{}) bool { | |||
| 			notCompatibleType(tag, value) | ||||
| 			return false | ||||
| 		} | ||||
| 		updateInnerHTML(detailsView.htmlID(), detailsView.Session()) | ||||
| 		return true | ||||
| 		if detailsView.created { | ||||
| 			updateInnerHTML(detailsView.htmlID(), detailsView.Session()) | ||||
| 		} | ||||
| 
 | ||||
| 	case Expanded: | ||||
| 		if detailsView.setBoolProperty(tag, value) { | ||||
| 		if !detailsView.setBoolProperty(tag, value) { | ||||
| 			notCompatibleType(tag, value) | ||||
| 			return false | ||||
| 		} | ||||
| 		if detailsView.created { | ||||
| 			if IsDetailsExpanded(detailsView, "") { | ||||
| 				updateProperty(detailsView.htmlID(), "open", "", detailsView.Session()) | ||||
| 			} else { | ||||
| 				removeProperty(detailsView.htmlID(), "open", detailsView.Session()) | ||||
| 			} | ||||
| 			return true | ||||
| 		} | ||||
| 		notCompatibleType(tag, value) | ||||
| 		return false | ||||
| 
 | ||||
| 	default: | ||||
| 		return detailsView.viewsContainerData.Set(tag, value) | ||||
| 	} | ||||
| 
 | ||||
| 	return detailsView.viewsContainerData.Set(tag, value) | ||||
| 	detailsView.propertyChangedEvent(tag) | ||||
| 	return true | ||||
| } | ||||
| 
 | ||||
| func (detailsView *detailsViewData) Get(tag string) interface{} { | ||||
|  |  | |||
|  | @ -48,19 +48,31 @@ func (list *dropDownListData) remove(tag string) { | |||
| 	case Items: | ||||
| 		if len(list.items) > 0 { | ||||
| 			list.items = []string{} | ||||
| 			updateInnerHTML(list.htmlID(), list.session) | ||||
| 			if list.created { | ||||
| 				updateInnerHTML(list.htmlID(), list.session) | ||||
| 			} | ||||
| 			list.propertyChangedEvent(tag) | ||||
| 		} | ||||
| 
 | ||||
| 	case Current: | ||||
| 		list.set(Current, 0) | ||||
| 
 | ||||
| 	case DropDownEvent: | ||||
| 		if len(list.dropDownListener) > 0 { | ||||
| 			list.dropDownListener = []func(DropDownList, int){} | ||||
| 			list.propertyChangedEvent(tag) | ||||
| 		} | ||||
| 
 | ||||
| 	case Current: | ||||
| 		oldCurrent := GetDropDownCurrent(list, "") | ||||
| 		delete(list.properties, Current) | ||||
| 		if oldCurrent != 0 { | ||||
| 			if list.created { | ||||
| 				list.session.runScript(fmt.Sprintf(`selectDropDownListItem('%s', %d)`, list.htmlID(), 0)) | ||||
| 			} | ||||
| 			list.onSelectedItemChanged(0) | ||||
| 		} | ||||
| 
 | ||||
| 	default: | ||||
| 		list.viewData.remove(tag) | ||||
| 		return | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -73,23 +85,22 @@ func (list *dropDownListData) set(tag string, value interface{}) bool { | |||
| 	case Items: | ||||
| 		return list.setItems(value) | ||||
| 
 | ||||
| 	case DropDownEvent: | ||||
| 		return list.setDropDownListener(value) | ||||
| 
 | ||||
| 	case Current: | ||||
| 		oldCurrent := GetDropDownCurrent(list, "") | ||||
| 		if !list.setIntProperty(Current, value) { | ||||
| 			return false | ||||
| 		} | ||||
| 
 | ||||
| 		if !list.session.ignoreViewUpdates() { | ||||
| 			current := GetDropDownCurrent(list, "") | ||||
| 			if oldCurrent != current { | ||||
| 		if current := GetDropDownCurrent(list, ""); oldCurrent != current { | ||||
| 			if list.created { | ||||
| 				list.session.runScript(fmt.Sprintf(`selectDropDownListItem('%s', %d)`, list.htmlID(), current)) | ||||
| 				list.onSelectedItemChanged(current) | ||||
| 			} | ||||
| 			list.onSelectedItemChanged(current) | ||||
| 		} | ||||
| 		return true | ||||
| 
 | ||||
| 	case DropDownEvent: | ||||
| 		return list.setDropDownListener(value) | ||||
| 	} | ||||
| 
 | ||||
| 	return list.viewData.set(tag, value) | ||||
|  | @ -160,9 +171,11 @@ func (list *dropDownListData) setItems(value interface{}) bool { | |||
| 		return false | ||||
| 	} | ||||
| 
 | ||||
| 	if !list.session.ignoreViewUpdates() { | ||||
| 	if list.created { | ||||
| 		updateInnerHTML(list.htmlID(), list.session) | ||||
| 	} | ||||
| 
 | ||||
| 	list.propertyChangedEvent(Items) | ||||
| 	return true | ||||
| } | ||||
| 
 | ||||
|  | @ -170,17 +183,14 @@ func (list *dropDownListData) setDropDownListener(value interface{}) bool { | |||
| 	switch value := value.(type) { | ||||
| 	case func(DropDownList, int): | ||||
| 		list.dropDownListener = []func(DropDownList, int){value} | ||||
| 		return true | ||||
| 
 | ||||
| 	case func(int): | ||||
| 		list.dropDownListener = []func(DropDownList, int){func(list DropDownList, index int) { | ||||
| 			value(index) | ||||
| 		}} | ||||
| 		return true | ||||
| 
 | ||||
| 	case []func(DropDownList, int): | ||||
| 		list.dropDownListener = value | ||||
| 		return true | ||||
| 
 | ||||
| 	case []func(int): | ||||
| 		listeners := make([]func(DropDownList, int), len(value)) | ||||
|  | @ -194,7 +204,6 @@ func (list *dropDownListData) setDropDownListener(value interface{}) bool { | |||
| 			} | ||||
| 		} | ||||
| 		list.dropDownListener = listeners | ||||
| 		return true | ||||
| 
 | ||||
| 	case []interface{}: | ||||
| 		listeners := make([]func(DropDownList, int), len(value)) | ||||
|  | @ -216,13 +225,16 @@ func (list *dropDownListData) setDropDownListener(value interface{}) bool { | |||
| 				notCompatibleType(DropDownEvent, value) | ||||
| 				return false | ||||
| 			} | ||||
| 			list.dropDownListener = listeners | ||||
| 		} | ||||
| 		return true | ||||
| 		list.dropDownListener = listeners | ||||
| 
 | ||||
| 	default: | ||||
| 		notCompatibleType(DropDownEvent, value) | ||||
| 		return false | ||||
| 	} | ||||
| 
 | ||||
| 	notCompatibleType(DropDownEvent, value) | ||||
| 	return false | ||||
| 	list.propertyChangedEvent(DropDownEvent) | ||||
| 	return true | ||||
| } | ||||
| 
 | ||||
| func (list *dropDownListData) Get(tag string) interface{} { | ||||
|  | @ -280,7 +292,7 @@ func (list *dropDownListData) htmlProperties(self View, buffer *strings.Builder) | |||
| 
 | ||||
| func (list *dropDownListData) htmlDisabledProperties(self View, buffer *strings.Builder) { | ||||
| 	list.viewData.htmlDisabledProperties(self, buffer) | ||||
| 	if IsDisabled(list) { | ||||
| 	if IsDisabled(list, "") { | ||||
| 		buffer.WriteString(`disabled`) | ||||
| 	} | ||||
| } | ||||
|  | @ -289,6 +301,7 @@ func (list *dropDownListData) onSelectedItemChanged(number int) { | |||
| 	for _, listener := range list.dropDownListener { | ||||
| 		listener(list, number) | ||||
| 	} | ||||
| 	list.propertyChangedEvent(Current) | ||||
| } | ||||
| 
 | ||||
| func (list *dropDownListData) handleCommand(self View, command string, data DataObject) bool { | ||||
|  |  | |||
							
								
								
									
										182
									
								
								editView.go
								
								
								
								
							
							
						
						
									
										182
									
								
								editView.go
								
								
								
								
							|  | @ -84,63 +84,98 @@ func (edit *editViewData) Remove(tag string) { | |||
| } | ||||
| 
 | ||||
| func (edit *editViewData) remove(tag string) { | ||||
| 	if _, ok := edit.properties[tag]; ok { | ||||
| 		switch tag { | ||||
| 		case Hint: | ||||
| 	_, exists := edit.properties[tag] | ||||
| 	switch tag { | ||||
| 	case Hint: | ||||
| 		if exists { | ||||
| 			delete(edit.properties, Hint) | ||||
| 			removeProperty(edit.htmlID(), "placeholder", edit.session) | ||||
| 
 | ||||
| 		case MaxLength: | ||||
| 			delete(edit.properties, MaxLength) | ||||
| 			removeProperty(edit.htmlID(), "maxlength", edit.session) | ||||
| 
 | ||||
| 		case ReadOnly, Spellcheck: | ||||
| 			delete(edit.properties, tag) | ||||
| 			updateBoolProperty(edit.htmlID(), tag, false, edit.session) | ||||
| 
 | ||||
| 		case EditTextChangedEvent: | ||||
| 			if len(edit.textChangeListeners) > 0 { | ||||
| 				edit.textChangeListeners = []func(EditView, string){} | ||||
| 			if edit.created { | ||||
| 				removeProperty(edit.htmlID(), "placeholder", edit.session) | ||||
| 			} | ||||
| 			edit.propertyChangedEvent(tag) | ||||
| 		} | ||||
| 
 | ||||
| 		case Text: | ||||
| 	case MaxLength: | ||||
| 		if exists { | ||||
| 			delete(edit.properties, MaxLength) | ||||
| 			if edit.created { | ||||
| 				removeProperty(edit.htmlID(), "maxlength", edit.session) | ||||
| 			} | ||||
| 			edit.propertyChangedEvent(tag) | ||||
| 		} | ||||
| 
 | ||||
| 	case ReadOnly, Spellcheck: | ||||
| 		if exists { | ||||
| 			delete(edit.properties, tag) | ||||
| 			if edit.created { | ||||
| 				updateBoolProperty(edit.htmlID(), tag, false, edit.session) | ||||
| 			} | ||||
| 			edit.propertyChangedEvent(tag) | ||||
| 		} | ||||
| 
 | ||||
| 	case EditTextChangedEvent: | ||||
| 		if len(edit.textChangeListeners) > 0 { | ||||
| 			edit.textChangeListeners = []func(EditView, string){} | ||||
| 			edit.propertyChangedEvent(tag) | ||||
| 		} | ||||
| 
 | ||||
| 	case Text: | ||||
| 		if exists { | ||||
| 			oldText := GetText(edit, "") | ||||
| 			delete(edit.properties, tag) | ||||
| 			if oldText != "" { | ||||
| 				edit.textChanged("") | ||||
| 				edit.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, edit.htmlID(), "")) | ||||
| 				if edit.created { | ||||
| 					edit.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, edit.htmlID(), "")) | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		case EditViewPattern: | ||||
| 	case EditViewPattern: | ||||
| 		if exists { | ||||
| 			oldText := GetEditViewPattern(edit, "") | ||||
| 			delete(edit.properties, tag) | ||||
| 			if oldText != "" { | ||||
| 				removeProperty(edit.htmlID(), Pattern, edit.session) | ||||
| 				if edit.created { | ||||
| 					removeProperty(edit.htmlID(), Pattern, edit.session) | ||||
| 				} | ||||
| 				edit.propertyChangedEvent(tag) | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		case EditViewType: | ||||
| 	case EditViewType: | ||||
| 		if exists { | ||||
| 			oldType := GetEditViewType(edit, "") | ||||
| 			delete(edit.properties, tag) | ||||
| 			if oldType != 0 { | ||||
| 				updateInnerHTML(edit.parentHTMLID(), edit.session) | ||||
| 				if edit.created { | ||||
| 					updateInnerHTML(edit.parentHTMLID(), edit.session) | ||||
| 				} | ||||
| 				edit.propertyChangedEvent(tag) | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		case Wrap: | ||||
| 	case Wrap: | ||||
| 		if exists { | ||||
| 			oldWrap := IsEditViewWrap(edit, "") | ||||
| 			delete(edit.properties, tag) | ||||
| 			if GetEditViewType(edit, "") == MultiLineText { | ||||
| 				if wrap := IsEditViewWrap(edit, ""); wrap != oldWrap { | ||||
| 					if wrap { | ||||
| 						updateProperty(edit.htmlID(), "wrap", "soft", edit.session) | ||||
| 					} else { | ||||
| 						updateProperty(edit.htmlID(), "wrap", "off", edit.session) | ||||
| 					if edit.created { | ||||
| 						if wrap { | ||||
| 							updateProperty(edit.htmlID(), "wrap", "soft", edit.session) | ||||
| 						} else { | ||||
| 							updateProperty(edit.htmlID(), "wrap", "off", edit.session) | ||||
| 						} | ||||
| 					} | ||||
| 					edit.propertyChangedEvent(tag) | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 		default: | ||||
| 			edit.viewData.remove(tag) | ||||
| 		} | ||||
| 
 | ||||
| 	default: | ||||
| 		edit.viewData.remove(tag) | ||||
| 		return | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -161,14 +196,16 @@ func (edit *editViewData) set(tag string, value interface{}) bool { | |||
| 			edit.properties[Text] = text | ||||
| 			if text = GetText(edit, ""); oldText != text { | ||||
| 				edit.textChanged(text) | ||||
| 				if GetEditViewType(edit, "") == MultiLineText { | ||||
| 					updateInnerHTML(edit.htmlID(), edit.Session()) | ||||
| 				} else { | ||||
| 					text = strings.ReplaceAll(text, `"`, `\"`) | ||||
| 					text = strings.ReplaceAll(text, `'`, `\'`) | ||||
| 					text = strings.ReplaceAll(text, "\n", `\n`) | ||||
| 					text = strings.ReplaceAll(text, "\r", `\r`) | ||||
| 					edit.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, edit.htmlID(), text)) | ||||
| 				if edit.created { | ||||
| 					if GetEditViewType(edit, "") == MultiLineText { | ||||
| 						updateInnerHTML(edit.htmlID(), edit.Session()) | ||||
| 					} else { | ||||
| 						text = strings.ReplaceAll(text, `"`, `\"`) | ||||
| 						text = strings.ReplaceAll(text, `'`, `\'`) | ||||
| 						text = strings.ReplaceAll(text, "\n", `\n`) | ||||
| 						text = strings.ReplaceAll(text, "\r", `\r`) | ||||
| 						edit.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, edit.htmlID(), text)) | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			return true | ||||
|  | @ -180,11 +217,14 @@ func (edit *editViewData) set(tag string, value interface{}) bool { | |||
| 		if text, ok := value.(string); ok { | ||||
| 			edit.properties[Hint] = text | ||||
| 			if text = GetHint(edit, ""); oldText != text { | ||||
| 				if text != "" { | ||||
| 					updateProperty(edit.htmlID(), "placeholder", text, edit.session) | ||||
| 				} else { | ||||
| 					removeProperty(edit.htmlID(), "placeholder", edit.session) | ||||
| 				if edit.created { | ||||
| 					if text != "" { | ||||
| 						updateProperty(edit.htmlID(), "placeholder", text, edit.session) | ||||
| 					} else { | ||||
| 						removeProperty(edit.htmlID(), "placeholder", edit.session) | ||||
| 					} | ||||
| 				} | ||||
| 				edit.propertyChangedEvent(tag) | ||||
| 			} | ||||
| 			return true | ||||
| 		} | ||||
|  | @ -194,11 +234,14 @@ func (edit *editViewData) set(tag string, value interface{}) bool { | |||
| 		oldMaxLength := GetMaxLength(edit, "") | ||||
| 		if edit.setIntProperty(MaxLength, value) { | ||||
| 			if maxLength := GetMaxLength(edit, ""); maxLength != oldMaxLength { | ||||
| 				if maxLength > 0 { | ||||
| 					updateProperty(edit.htmlID(), "maxlength", strconv.Itoa(maxLength), edit.session) | ||||
| 				} else { | ||||
| 					removeProperty(edit.htmlID(), "maxlength", edit.session) | ||||
| 				if edit.created { | ||||
| 					if maxLength > 0 { | ||||
| 						updateProperty(edit.htmlID(), "maxlength", strconv.Itoa(maxLength), edit.session) | ||||
| 					} else { | ||||
| 						removeProperty(edit.htmlID(), "maxlength", edit.session) | ||||
| 					} | ||||
| 				} | ||||
| 				edit.propertyChangedEvent(tag) | ||||
| 			} | ||||
| 			return true | ||||
| 		} | ||||
|  | @ -206,18 +249,24 @@ func (edit *editViewData) set(tag string, value interface{}) bool { | |||
| 
 | ||||
| 	case ReadOnly: | ||||
| 		if edit.setBoolProperty(ReadOnly, value) { | ||||
| 			if IsReadOnly(edit, "") { | ||||
| 				updateProperty(edit.htmlID(), ReadOnly, "", edit.session) | ||||
| 			} else { | ||||
| 				removeProperty(edit.htmlID(), ReadOnly, edit.session) | ||||
| 			if edit.created { | ||||
| 				if IsReadOnly(edit, "") { | ||||
| 					updateProperty(edit.htmlID(), ReadOnly, "", edit.session) | ||||
| 				} else { | ||||
| 					removeProperty(edit.htmlID(), ReadOnly, edit.session) | ||||
| 				} | ||||
| 			} | ||||
| 			edit.propertyChangedEvent(tag) | ||||
| 			return true | ||||
| 		} | ||||
| 		return false | ||||
| 
 | ||||
| 	case Spellcheck: | ||||
| 		if edit.setBoolProperty(Spellcheck, value) { | ||||
| 			updateBoolProperty(edit.htmlID(), Spellcheck, IsSpellcheck(edit, ""), edit.session) | ||||
| 			if edit.created { | ||||
| 				updateBoolProperty(edit.htmlID(), Spellcheck, IsSpellcheck(edit, ""), edit.session) | ||||
| 			} | ||||
| 			edit.propertyChangedEvent(tag) | ||||
| 			return true | ||||
| 		} | ||||
| 		return false | ||||
|  | @ -227,11 +276,14 @@ func (edit *editViewData) set(tag string, value interface{}) bool { | |||
| 		if text, ok := value.(string); ok { | ||||
| 			edit.properties[Pattern] = text | ||||
| 			if text = GetEditViewPattern(edit, ""); oldText != text { | ||||
| 				if text != "" { | ||||
| 					updateProperty(edit.htmlID(), Pattern, text, edit.session) | ||||
| 				} else { | ||||
| 					removeProperty(edit.htmlID(), Pattern, edit.session) | ||||
| 				if edit.created { | ||||
| 					if text != "" { | ||||
| 						updateProperty(edit.htmlID(), Pattern, text, edit.session) | ||||
| 					} else { | ||||
| 						removeProperty(edit.htmlID(), Pattern, edit.session) | ||||
| 					} | ||||
| 				} | ||||
| 				edit.propertyChangedEvent(tag) | ||||
| 			} | ||||
| 			return true | ||||
| 		} | ||||
|  | @ -241,7 +293,10 @@ func (edit *editViewData) set(tag string, value interface{}) bool { | |||
| 		oldType := GetEditViewType(edit, "") | ||||
| 		if edit.setEnumProperty(EditViewType, value, enumProperties[EditViewType].values) { | ||||
| 			if GetEditViewType(edit, "") != oldType { | ||||
| 				updateInnerHTML(edit.parentHTMLID(), edit.session) | ||||
| 				if edit.created { | ||||
| 					updateInnerHTML(edit.parentHTMLID(), edit.session) | ||||
| 				} | ||||
| 				edit.propertyChangedEvent(tag) | ||||
| 			} | ||||
| 			return true | ||||
| 		} | ||||
|  | @ -252,11 +307,14 @@ func (edit *editViewData) set(tag string, value interface{}) bool { | |||
| 		if edit.setBoolProperty(Wrap, value) { | ||||
| 			if GetEditViewType(edit, "") == MultiLineText { | ||||
| 				if wrap := IsEditViewWrap(edit, ""); wrap != oldWrap { | ||||
| 					if wrap { | ||||
| 						updateProperty(edit.htmlID(), "wrap", "soft", edit.session) | ||||
| 					} else { | ||||
| 						updateProperty(edit.htmlID(), "wrap", "off", edit.session) | ||||
| 					if edit.created { | ||||
| 						if wrap { | ||||
| 							updateProperty(edit.htmlID(), "wrap", "soft", edit.session) | ||||
| 						} else { | ||||
| 							updateProperty(edit.htmlID(), "wrap", "off", edit.session) | ||||
| 						} | ||||
| 					} | ||||
| 					edit.propertyChangedEvent(tag) | ||||
| 				} | ||||
| 			} | ||||
| 			return true | ||||
|  | @ -268,6 +326,7 @@ func (edit *editViewData) set(tag string, value interface{}) bool { | |||
| 		if !ok { | ||||
| 			notCompatibleType(tag, value) | ||||
| 		} | ||||
| 		edit.propertyChangedEvent(tag) | ||||
| 		return ok | ||||
| 	} | ||||
| 
 | ||||
|  | @ -363,6 +422,7 @@ func (edit *editViewData) textChanged(newText string) { | |||
| 	for _, listener := range edit.textChangeListeners { | ||||
| 		listener(edit, newText) | ||||
| 	} | ||||
| 	edit.propertyChangedEvent(Text) | ||||
| } | ||||
| 
 | ||||
| func (edit *editViewData) htmlTag() string { | ||||
|  | @ -446,7 +506,7 @@ func (edit *editViewData) htmlProperties(self View, buffer *strings.Builder) { | |||
| } | ||||
| 
 | ||||
| func (edit *editViewData) htmlDisabledProperties(self View, buffer *strings.Builder) { | ||||
| 	if IsDisabled(self) { | ||||
| 	if IsDisabled(self, "") { | ||||
| 		buffer.WriteString(` disabled`) | ||||
| 	} | ||||
| 	edit.viewData.htmlDisabledProperties(self, buffer) | ||||
|  |  | |||
|  | @ -114,7 +114,17 @@ func (picker *filePickerData) Remove(tag string) { | |||
| func (picker *filePickerData) remove(tag string) { | ||||
| 	switch tag { | ||||
| 	case FileSelectedEvent: | ||||
| 		picker.fileSelectedListeners = []func(FilePicker, []FileInfo){} | ||||
| 		if len(picker.fileSelectedListeners) > 0 { | ||||
| 			picker.fileSelectedListeners = []func(FilePicker, []FileInfo){} | ||||
| 			picker.propertyChangedEvent(tag) | ||||
| 		} | ||||
| 
 | ||||
| 	case Accept: | ||||
| 		delete(picker.properties, tag) | ||||
| 		if picker.created { | ||||
| 			removeProperty(picker.htmlID(), "accept", picker.Session()) | ||||
| 		} | ||||
| 		picker.propertyChangedEvent(tag) | ||||
| 
 | ||||
| 	default: | ||||
| 		picker.viewData.remove(tag) | ||||
|  | @ -184,6 +194,7 @@ func (picker *filePickerData) set(tag string, value interface{}) bool { | |||
| 			} | ||||
| 			picker.fileSelectedListeners = listeners | ||||
| 		} | ||||
| 		picker.propertyChangedEvent(tag) | ||||
| 		return true | ||||
| 
 | ||||
| 	case Accept: | ||||
|  | @ -218,6 +229,15 @@ func (picker *filePickerData) set(tag string, value interface{}) bool { | |||
| 			notCompatibleType(tag, value) | ||||
| 			return false | ||||
| 		} | ||||
| 
 | ||||
| 		if picker.created { | ||||
| 			if css := picker.acceptCSS(); css != "" { | ||||
| 				updateProperty(picker.htmlID(), "accept", css, picker.Session()) | ||||
| 			} else { | ||||
| 				removeProperty(picker.htmlID(), "accept", picker.Session()) | ||||
| 			} | ||||
| 		} | ||||
| 		picker.propertyChangedEvent(tag) | ||||
| 		return true | ||||
| 
 | ||||
| 	default: | ||||
|  | @ -271,7 +291,7 @@ func (picker *filePickerData) htmlProperties(self View, buffer *strings.Builder) | |||
| } | ||||
| 
 | ||||
| func (picker *filePickerData) htmlDisabledProperties(self View, buffer *strings.Builder) { | ||||
| 	if IsDisabled(self) { | ||||
| 	if IsDisabled(self, "") { | ||||
| 		buffer.WriteString(` disabled`) | ||||
| 	} | ||||
| 	picker.viewData.htmlDisabledProperties(self, buffer) | ||||
|  |  | |||
|  | @ -216,19 +216,22 @@ func (gridLayout *gridLayoutData) remove(tag string) { | |||
| 	if tag == Gap { | ||||
| 		gridLayout.remove(GridRowGap) | ||||
| 		gridLayout.remove(GridColumnGap) | ||||
| 		gridLayout.propertyChangedEvent(Gap) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	gridLayout.viewsContainerData.remove(tag) | ||||
| 	switch tag { | ||||
| 	case CellWidth: | ||||
| 		updateCSSProperty(gridLayout.htmlID(), `grid-template-columns`, | ||||
| 			gridLayout.gridCellSizesCSS(CellWidth, gridLayout.session), gridLayout.session) | ||||
| 	if gridLayout.created { | ||||
| 		switch tag { | ||||
| 		case CellWidth: | ||||
| 			updateCSSProperty(gridLayout.htmlID(), `grid-template-columns`, | ||||
| 				gridLayout.gridCellSizesCSS(CellWidth, gridLayout.session), gridLayout.session) | ||||
| 
 | ||||
| 	case CellHeight: | ||||
| 		updateCSSProperty(gridLayout.htmlID(), `grid-template-rows`, | ||||
| 			gridLayout.gridCellSizesCSS(CellHeight, gridLayout.session), gridLayout.session) | ||||
| 		case CellHeight: | ||||
| 			updateCSSProperty(gridLayout.htmlID(), `grid-template-rows`, | ||||
| 				gridLayout.gridCellSizesCSS(CellHeight, gridLayout.session), gridLayout.session) | ||||
| 
 | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -243,19 +246,25 @@ func (gridLayout *gridLayoutData) set(tag string, value interface{}) bool { | |||
| 	} | ||||
| 
 | ||||
| 	if tag == Gap { | ||||
| 		return gridLayout.set(GridRowGap, value) && gridLayout.set(GridColumnGap, value) | ||||
| 		if gridLayout.set(GridRowGap, value) && gridLayout.set(GridColumnGap, value) { | ||||
| 			gridLayout.propertyChangedEvent(Gap) | ||||
| 			return true | ||||
| 		} | ||||
| 		return false | ||||
| 	} | ||||
| 
 | ||||
| 	if gridLayout.viewsContainerData.set(tag, value) { | ||||
| 		switch tag { | ||||
| 		case CellWidth: | ||||
| 			updateCSSProperty(gridLayout.htmlID(), `grid-template-columns`, | ||||
| 				gridLayout.gridCellSizesCSS(CellWidth, gridLayout.session), gridLayout.session) | ||||
| 		if gridLayout.created { | ||||
| 			switch tag { | ||||
| 			case CellWidth: | ||||
| 				updateCSSProperty(gridLayout.htmlID(), `grid-template-columns`, | ||||
| 					gridLayout.gridCellSizesCSS(CellWidth, gridLayout.session), gridLayout.session) | ||||
| 
 | ||||
| 		case CellHeight: | ||||
| 			updateCSSProperty(gridLayout.htmlID(), `grid-template-rows`, | ||||
| 				gridLayout.gridCellSizesCSS(CellHeight, gridLayout.session), gridLayout.session) | ||||
| 			case CellHeight: | ||||
| 				updateCSSProperty(gridLayout.htmlID(), `grid-template-rows`, | ||||
| 					gridLayout.gridCellSizesCSS(CellHeight, gridLayout.session), gridLayout.session) | ||||
| 
 | ||||
| 			} | ||||
| 		} | ||||
| 		return true | ||||
| 	} | ||||
|  |  | |||
							
								
								
									
										48
									
								
								imageView.go
								
								
								
								
							
							
						
						
									
										48
									
								
								imageView.go
								
								
								
								
							|  | @ -67,7 +67,7 @@ func (imageView *imageViewData) normalizeTag(tag string) string { | |||
| 	case HorizontalAlign: | ||||
| 		tag = ImageHorizontalAlign | ||||
| 
 | ||||
| 	case altProperty: | ||||
| 	case altTag: | ||||
| 		tag = AltText | ||||
| 	} | ||||
| 	return tag | ||||
|  | @ -79,16 +79,18 @@ func (imageView *imageViewData) Remove(tag string) { | |||
| 
 | ||||
| func (imageView *imageViewData) remove(tag string) { | ||||
| 	imageView.viewData.remove(tag) | ||||
| 	switch tag { | ||||
| 	case Source: | ||||
| 		updateProperty(imageView.htmlID(), "src", "", imageView.session) | ||||
| 		removeProperty(imageView.htmlID(), "srcset", imageView.session) | ||||
| 	if imageView.created { | ||||
| 		switch tag { | ||||
| 		case Source: | ||||
| 			updateProperty(imageView.htmlID(), "src", "", imageView.session) | ||||
| 			removeProperty(imageView.htmlID(), "srcset", imageView.session) | ||||
| 
 | ||||
| 	case AltText: | ||||
| 		updateInnerHTML(imageView.htmlID(), imageView.session) | ||||
| 		case AltText: | ||||
| 			updateInnerHTML(imageView.htmlID(), imageView.session) | ||||
| 
 | ||||
| 	case ImageVerticalAlign, ImageHorizontalAlign: | ||||
| 		updateCSSStyle(imageView.htmlID(), imageView.session) | ||||
| 		case ImageVerticalAlign, ImageHorizontalAlign: | ||||
| 			updateCSSStyle(imageView.htmlID(), imageView.session) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -106,29 +108,37 @@ func (imageView *imageViewData) set(tag string, value interface{}) bool { | |||
| 	case Source: | ||||
| 		if text, ok := value.(string); ok { | ||||
| 			imageView.properties[Source] = text | ||||
| 			updateProperty(imageView.htmlID(), "src", text, imageView.session) | ||||
| 			if srcset := imageView.srcSet(text); srcset != "" { | ||||
| 				updateProperty(imageView.htmlID(), "srcset", srcset, imageView.session) | ||||
| 			} else { | ||||
| 				removeProperty(imageView.htmlID(), "srcset", imageView.session) | ||||
| 			if imageView.created { | ||||
| 				updateProperty(imageView.htmlID(), "src", text, imageView.session) | ||||
| 				if srcset := imageView.srcSet(text); srcset != "" { | ||||
| 					updateProperty(imageView.htmlID(), "srcset", srcset, imageView.session) | ||||
| 				} else { | ||||
| 					removeProperty(imageView.htmlID(), "srcset", imageView.session) | ||||
| 				} | ||||
| 			} | ||||
| 			imageView.propertyChangedEvent(Source) | ||||
| 			return true | ||||
| 		} | ||||
| 		notCompatibleType(tag, value) | ||||
| 		notCompatibleType(Source, value) | ||||
| 
 | ||||
| 	case AltText: | ||||
| 		if text, ok := value.(string); ok { | ||||
| 			imageView.properties[AltText] = text | ||||
| 			updateInnerHTML(imageView.htmlID(), imageView.session) | ||||
| 			if imageView.created { | ||||
| 				updateInnerHTML(imageView.htmlID(), imageView.session) | ||||
| 			} | ||||
| 			imageView.propertyChangedEvent(Source) | ||||
| 			return true | ||||
| 		} | ||||
| 		notCompatibleType(tag, value) | ||||
| 
 | ||||
| 	default: | ||||
| 		if imageView.viewData.set(tag, value) { | ||||
| 			switch tag { | ||||
| 			case ImageVerticalAlign, ImageHorizontalAlign: | ||||
| 				updateCSSStyle(imageView.htmlID(), imageView.session) | ||||
| 			if imageView.created { | ||||
| 				switch tag { | ||||
| 				case ImageVerticalAlign, ImageHorizontalAlign: | ||||
| 					updateCSSStyle(imageView.htmlID(), imageView.session) | ||||
| 				} | ||||
| 			} | ||||
| 			return true | ||||
| 		} | ||||
|  |  | |||
|  | @ -77,7 +77,7 @@ func (adapter *viewListAdapter) ListItem(index int, session Session) View { | |||
| 
 | ||||
| func (adapter *viewListAdapter) IsListItemEnabled(index int) bool { | ||||
| 	if index >= 0 && index < len(adapter.items) { | ||||
| 		return !IsDisabled(adapter.items[index]) | ||||
| 		return !IsDisabled(adapter.items[index], "") | ||||
| 	} | ||||
| 	return true | ||||
| } | ||||
|  |  | |||
|  | @ -55,9 +55,11 @@ func (listLayout *listLayoutData) Remove(tag string) { | |||
| 
 | ||||
| func (listLayout *listLayoutData) remove(tag string) { | ||||
| 	listLayout.viewsContainerData.remove(tag) | ||||
| 	switch tag { | ||||
| 	case Orientation, Wrap, HorizontalAlign, VerticalAlign: | ||||
| 		updateCSSStyle(listLayout.htmlID(), listLayout.session) | ||||
| 	if listLayout.created { | ||||
| 		switch tag { | ||||
| 		case Orientation, Wrap, HorizontalAlign, VerticalAlign: | ||||
| 			updateCSSStyle(listLayout.htmlID(), listLayout.session) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -72,9 +74,11 @@ func (listLayout *listLayoutData) set(tag string, value interface{}) bool { | |||
| 	} | ||||
| 
 | ||||
| 	if listLayout.viewsContainerData.set(tag, value) { | ||||
| 		switch tag { | ||||
| 		case Orientation, Wrap, HorizontalAlign, VerticalAlign: | ||||
| 			updateCSSStyle(listLayout.htmlID(), listLayout.session) | ||||
| 		if listLayout.created { | ||||
| 			switch tag { | ||||
| 			case Orientation, Wrap, HorizontalAlign, VerticalAlign: | ||||
| 				updateCSSStyle(listLayout.htmlID(), listLayout.session) | ||||
| 			} | ||||
| 		} | ||||
| 		return true | ||||
| 	} | ||||
|  |  | |||
							
								
								
									
										114
									
								
								listView.go
								
								
								
								
							
							
						
						
									
										114
									
								
								listView.go
								
								
								
								
							|  | @ -114,46 +114,71 @@ func (listView *listViewData) Remove(tag string) { | |||
| func (listView *listViewData) remove(tag string) { | ||||
| 	switch tag { | ||||
| 	case Checked: | ||||
| 		listView.checkedItem = []int{} | ||||
| 		updateInnerHTML(listView.htmlID(), listView.session) | ||||
| 		if len(listView.checkedItem) > 0 { | ||||
| 			listView.checkedItem = []int{} | ||||
| 			if listView.created { | ||||
| 				updateInnerHTML(listView.htmlID(), listView.session) | ||||
| 			} | ||||
| 			listView.propertyChangedEvent(tag) | ||||
| 		} | ||||
| 
 | ||||
| 	case Items: | ||||
| 		listView.adapter = nil | ||||
| 		updateInnerHTML(listView.htmlID(), listView.session) | ||||
| 		if listView.adapter != nil { | ||||
| 			listView.adapter = nil | ||||
| 			if listView.created { | ||||
| 				updateInnerHTML(listView.htmlID(), listView.session) | ||||
| 			} | ||||
| 			listView.propertyChangedEvent(tag) | ||||
| 		} | ||||
| 
 | ||||
| 	case Orientation, Wrap: | ||||
| 		delete(listView.properties, tag) | ||||
| 		updateCSSStyle(listView.htmlID(), listView.session) | ||||
| 		if _, ok := listView.properties[tag]; ok { | ||||
| 			delete(listView.properties, tag) | ||||
| 			if listView.created { | ||||
| 				updateCSSStyle(listView.htmlID(), listView.session) | ||||
| 			} | ||||
| 			listView.propertyChangedEvent(tag) | ||||
| 		} | ||||
| 
 | ||||
| 	case Current: | ||||
| 		current := GetListViewCurrent(listView, "") | ||||
| 		delete(listView.properties, tag) | ||||
| 		updateInnerHTML(listView.htmlID(), listView.session) | ||||
| 		if listView.created { | ||||
| 			updateInnerHTML(listView.htmlID(), listView.session) | ||||
| 		} | ||||
| 		if current != -1 { | ||||
| 			for _, listener := range listView.selectedListeners { | ||||
| 				listener(listView, -1) | ||||
| 			} | ||||
| 			listView.propertyChangedEvent(tag) | ||||
| 		} | ||||
| 
 | ||||
| 	case ItemWidth, ItemHeight, ItemHorizontalAlign, ItemVerticalAlign, ItemCheckbox, | ||||
| 		CheckboxHorizontalAlign, CheckboxVerticalAlign, ListItemStyle, CurrentStyle, CurrentInactiveStyle: | ||||
| 
 | ||||
| 		delete(listView.properties, tag) | ||||
| 		updateInnerHTML(listView.htmlID(), listView.session) | ||||
| 		if _, ok := listView.properties[tag]; ok { | ||||
| 			delete(listView.properties, tag) | ||||
| 			if listView.created { | ||||
| 				updateInnerHTML(listView.htmlID(), listView.session) | ||||
| 			} | ||||
| 			listView.propertyChangedEvent(tag) | ||||
| 		} | ||||
| 
 | ||||
| 	case ListItemClickedEvent: | ||||
| 		if len(listView.clickedListeners) > 0 { | ||||
| 			listView.clickedListeners = []func(ListView, int){} | ||||
| 			listView.propertyChangedEvent(tag) | ||||
| 		} | ||||
| 
 | ||||
| 	case ListItemSelectedEvent: | ||||
| 		if len(listView.selectedListeners) > 0 { | ||||
| 			listView.selectedListeners = []func(ListView, int){} | ||||
| 			listView.propertyChangedEvent(tag) | ||||
| 		} | ||||
| 
 | ||||
| 	case ListItemCheckedEvent: | ||||
| 		if len(listView.checkedListeners) > 0 { | ||||
| 			listView.checkedListeners = []func(ListView, []int){} | ||||
| 			listView.propertyChangedEvent(tag) | ||||
| 		} | ||||
| 
 | ||||
| 	default: | ||||
|  | @ -171,10 +196,7 @@ func (listView *listViewData) set(tag string, value interface{}) bool { | |||
| 		return true | ||||
| 	} | ||||
| 
 | ||||
| 	result := false | ||||
| 
 | ||||
| 	switch tag { | ||||
| 
 | ||||
| 	case ListItemClickedEvent: | ||||
| 		listeners := listView.valueToItemListeners(value) | ||||
| 		if listeners == nil { | ||||
|  | @ -182,6 +204,7 @@ func (listView *listViewData) set(tag string, value interface{}) bool { | |||
| 			return false | ||||
| 		} | ||||
| 		listView.clickedListeners = listeners | ||||
| 		listView.propertyChangedEvent(tag) | ||||
| 		return true | ||||
| 
 | ||||
| 	case ListItemSelectedEvent: | ||||
|  | @ -191,44 +214,56 @@ func (listView *listViewData) set(tag string, value interface{}) bool { | |||
| 			return false | ||||
| 		} | ||||
| 		listView.selectedListeners = listeners | ||||
| 		listView.propertyChangedEvent(tag) | ||||
| 		return true | ||||
| 
 | ||||
| 	case ListItemCheckedEvent: | ||||
| 		return listView.setItemCheckedEvent(value) | ||||
| 		if !listView.setItemCheckedEvent(value) { | ||||
| 			return false | ||||
| 		} | ||||
| 		listView.propertyChangedEvent(tag) | ||||
| 		return true | ||||
| 
 | ||||
| 	case Checked: | ||||
| 		return listView.setChecked(value) | ||||
| 		if !listView.setChecked(value) { | ||||
| 			return false | ||||
| 		} | ||||
| 
 | ||||
| 	case Items: | ||||
| 		result = listView.setItems(value) | ||||
| 		if !listView.setItems(value) { | ||||
| 			return false | ||||
| 		} | ||||
| 
 | ||||
| 	case Current: | ||||
| 		oldCurrent := GetListViewCurrent(listView, "") | ||||
| 		if listView.setIntProperty(Current, value) { | ||||
| 			current := GetListViewCurrent(listView, "") | ||||
| 			if oldCurrent != current { | ||||
| 				updateInnerHTML(listView.htmlID(), listView.session) | ||||
| 				for _, listener := range listView.selectedListeners { | ||||
| 					listener(listView, current) | ||||
| 				} | ||||
| 			} | ||||
| 		if !listView.setIntProperty(Current, value) { | ||||
| 			return false | ||||
| 		} | ||||
| 		current := GetListViewCurrent(listView, "") | ||||
| 		if oldCurrent == current { | ||||
| 			return true | ||||
| 		} | ||||
| 
 | ||||
| 	case Orientation, Wrap, VerticalAlign, HorizontalAlign, Style, StyleDisabled: | ||||
| 		result = listView.viewData.set(tag, value) | ||||
| 		for _, listener := range listView.selectedListeners { | ||||
| 			listener(listView, current) | ||||
| 		} | ||||
| 
 | ||||
| 	case ItemWidth, ItemHeight: | ||||
| 		result = listView.setSizeProperty(tag, value) | ||||
| 	case Orientation, Wrap, VerticalAlign, HorizontalAlign, Style, StyleDisabled, ItemWidth, ItemHeight: | ||||
| 		result := listView.viewData.set(tag, value) | ||||
| 		if result && listView.created { | ||||
| 			updateInnerHTML(listView.htmlID(), listView.session) | ||||
| 		} | ||||
| 		return result | ||||
| 
 | ||||
| 	case ItemHorizontalAlign, ItemVerticalAlign, ItemCheckbox, CheckboxHorizontalAlign, CheckboxVerticalAlign: | ||||
| 		result = listView.setEnumProperty(tag, value, enumProperties[tag].values) | ||||
| 		if !listView.setEnumProperty(tag, value, enumProperties[tag].values) { | ||||
| 			return false | ||||
| 		} | ||||
| 
 | ||||
| 	case ListItemStyle, CurrentStyle, CurrentInactiveStyle: | ||||
| 		switch value := value.(type) { | ||||
| 		case string: | ||||
| 			listView.properties[tag] = value | ||||
| 			result = true | ||||
| 
 | ||||
| 		default: | ||||
| 			notCompatibleType(tag, value) | ||||
|  | @ -239,11 +274,11 @@ func (listView *listViewData) set(tag string, value interface{}) bool { | |||
| 		return listView.viewData.set(tag, value) | ||||
| 	} | ||||
| 
 | ||||
| 	if result { | ||||
| 	if listView.created { | ||||
| 		updateInnerHTML(listView.htmlID(), listView.session) | ||||
| 	} | ||||
| 
 | ||||
| 	return result | ||||
| 	listView.propertyChangedEvent(tag) | ||||
| 	return true | ||||
| } | ||||
| 
 | ||||
| func (listView *listViewData) setItemCheckedEvent(value interface{}) bool { | ||||
|  | @ -1054,13 +1089,17 @@ func (listView *listViewData) handleCommand(self View, command string, data Data | |||
| 				for _, listener := range listView.selectedListeners { | ||||
| 					listener(listView, number) | ||||
| 				} | ||||
| 				listView.propertyChangedEvent(Current) | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 	case "itemUnselected": | ||||
| 		delete(listView.properties, Current) | ||||
| 		for _, listener := range listView.selectedListeners { | ||||
| 			listener(listView, -1) | ||||
| 		if _, ok := listView.properties[Current]; ok { | ||||
| 			delete(listView.properties, Current) | ||||
| 			for _, listener := range listView.selectedListeners { | ||||
| 				listener(listView, -1) | ||||
| 			} | ||||
| 			listView.propertyChangedEvent(Current) | ||||
| 		} | ||||
| 
 | ||||
| 	case "itemClick": | ||||
|  | @ -1075,7 +1114,7 @@ func (listView *listViewData) handleCommand(self View, command string, data Data | |||
| 
 | ||||
| func (listView *listViewData) onItemClick() { | ||||
| 	current := GetListViewCurrent(listView, "") | ||||
| 	if current >= 0 && !IsDisabled(listView) { | ||||
| 	if current >= 0 && !IsDisabled(listView, "") { | ||||
| 		checkbox := GetListViewCheckbox(listView, "") | ||||
| 	m: | ||||
| 		switch checkbox { | ||||
|  | @ -1115,6 +1154,7 @@ func (listView *listViewData) onItemClick() { | |||
| 			for _, listener := range listView.checkedListeners { | ||||
| 				listener(listView, listView.checkedItem) | ||||
| 			} | ||||
| 			listView.propertyChangedEvent(Checked) | ||||
| 		} | ||||
| 		for _, listener := range listView.clickedListeners { | ||||
| 			listener(listView, current) | ||||
|  |  | |||
							
								
								
									
										182
									
								
								mediaPlayer.go
								
								
								
								
							
							
						
						
									
										182
									
								
								mediaPlayer.go
								
								
								
								
							|  | @ -173,20 +173,8 @@ func (player *mediaPlayerData) Remove(tag string) { | |||
| } | ||||
| 
 | ||||
| func (player *mediaPlayerData) remove(tag string) { | ||||
| 	switch tag { | ||||
| 
 | ||||
| 	case Controls, Loop, Muted, Preload, AbortEvent, LoadStartEvent, PlayerErrorEvent, | ||||
| 		CanPlayEvent, CanPlayThroughEvent, CompleteEvent, DurationChangedEvent, | ||||
| 		EmptiedEvent, EndedEvent, LoadedDataEvent, LoadedMetadataEvent, PauseEvent, PlayEvent, | ||||
| 		PlayingEvent, RateChangedEvent, SeekedEvent, SeekingEvent, StalledEvent, SuspendEvent, | ||||
| 		ProgressEvent, TimeUpdateEvent, VolumeChangedEvent, WaitingEvent: | ||||
| 
 | ||||
| 		player.viewData.remove(tag) | ||||
| 		player.propertyChanged(tag) | ||||
| 
 | ||||
| 	default: | ||||
| 		player.viewData.remove(tag) | ||||
| 	} | ||||
| 	player.viewData.remove(tag) | ||||
| 	player.propertyChanged(tag) | ||||
| } | ||||
| 
 | ||||
| func (player *mediaPlayerData) Set(tag string, value interface{}) bool { | ||||
|  | @ -216,6 +204,7 @@ func (player *mediaPlayerData) set(tag string, value interface{}) bool { | |||
| 				player.properties[tag] = listeners | ||||
| 			} | ||||
| 			player.propertyChanged(tag) | ||||
| 			player.propertyChangedEvent(tag) | ||||
| 			return true | ||||
| 		} | ||||
| 		notCompatibleType(tag, value) | ||||
|  | @ -228,6 +217,7 @@ func (player *mediaPlayerData) set(tag string, value interface{}) bool { | |||
| 				player.properties[tag] = listeners | ||||
| 			} | ||||
| 			player.propertyChanged(tag) | ||||
| 			player.propertyChangedEvent(tag) | ||||
| 			return true | ||||
| 		} | ||||
| 		notCompatibleType(tag, value) | ||||
|  | @ -240,6 +230,7 @@ func (player *mediaPlayerData) set(tag string, value interface{}) bool { | |||
| 				player.properties[tag] = listeners | ||||
| 			} | ||||
| 			player.propertyChanged(tag) | ||||
| 			player.propertyChangedEvent(tag) | ||||
| 			return true | ||||
| 		} | ||||
| 		notCompatibleType(tag, value) | ||||
|  | @ -247,14 +238,14 @@ func (player *mediaPlayerData) set(tag string, value interface{}) bool { | |||
| 	case Source: | ||||
| 		if player.setSource(value) { | ||||
| 			player.propertyChanged(tag) | ||||
| 			player.propertyChangedEvent(tag) | ||||
| 			return true | ||||
| 		} | ||||
| 
 | ||||
| 	default: | ||||
| 		if player.viewData.set(tag, value) { | ||||
| 			return true | ||||
| 		} | ||||
| 		return player.viewData.set(tag, value) | ||||
| 	} | ||||
| 
 | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
|  | @ -657,89 +648,88 @@ func playerEvents() []struct{ tag, cssTag string } { | |||
| } | ||||
| 
 | ||||
| func (player *mediaPlayerData) propertyChanged(tag string) { | ||||
| 	switch tag { | ||||
| 	case Controls, Loop: | ||||
| 		value, _ := boolProperty(player, tag, player.Session()) | ||||
| 		if value { | ||||
| 			updateBoolProperty(player.htmlID(), tag, value, player.Session()) | ||||
| 		} else { | ||||
| 			removeProperty(player.htmlID(), tag, player.Session()) | ||||
| 		} | ||||
| 
 | ||||
| 	case Muted: | ||||
| 		value, _ := boolProperty(player, tag, player.Session()) | ||||
| 		if value { | ||||
| 			player.Session().runScript("setMediaMuted('" + player.htmlID() + "', true)") | ||||
| 		} else { | ||||
| 			player.Session().runScript("setMediaMuted('" + player.htmlID() + "', false)") | ||||
| 		} | ||||
| 
 | ||||
| 	case Preload: | ||||
| 		value, _ := enumProperty(player, tag, player.Session(), 0) | ||||
| 		values := enumProperties[Preload].values | ||||
| 		updateProperty(player.htmlID(), tag, values[value], player.Session()) | ||||
| 
 | ||||
| 	case AbortEvent, CanPlayEvent, CanPlayThroughEvent, CompleteEvent, EmptiedEvent, | ||||
| 		EndedEvent, LoadedDataEvent, LoadedMetadataEvent, PauseEvent, PlayEvent, PlayingEvent, ProgressEvent, | ||||
| 		LoadStartEvent, SeekedEvent, SeekingEvent, StalledEvent, SuspendEvent, WaitingEvent: | ||||
| 
 | ||||
| 		for _, event := range playerEvents() { | ||||
| 			if event.tag == tag { | ||||
| 				if value := player.getRaw(event.tag); value != nil { | ||||
| 					switch value := value.(type) { | ||||
| 					case []func(MediaPlayer): | ||||
| 						if len(value) > 0 { | ||||
| 							fn := fmt.Sprintf(`playerEvent(this, "%s")`, event.tag) | ||||
| 							updateProperty(player.htmlID(), event.cssTag, fn, player.Session()) | ||||
| 							return | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 				updateProperty(player.htmlID(), tag, "", player.Session()) | ||||
| 				break | ||||
| 	if player.created { | ||||
| 		switch tag { | ||||
| 		case Controls, Loop: | ||||
| 			value, _ := boolProperty(player, tag, player.Session()) | ||||
| 			if value { | ||||
| 				updateBoolProperty(player.htmlID(), tag, value, player.Session()) | ||||
| 			} else { | ||||
| 				removeProperty(player.htmlID(), tag, player.Session()) | ||||
| 			} | ||||
| 
 | ||||
| 		} | ||||
| 	case TimeUpdateEvent: | ||||
| 		if value := player.getRaw(tag); value != nil { | ||||
| 			updateProperty(player.htmlID(), "ontimeupdate", "playerTimeUpdatedEvent(this)", player.Session()) | ||||
| 		} else { | ||||
| 			updateProperty(player.htmlID(), "ontimeupdate", "", player.Session()) | ||||
| 		} | ||||
| 		case Muted: | ||||
| 			value, _ := boolProperty(player, tag, player.Session()) | ||||
| 			if value { | ||||
| 				player.Session().runScript("setMediaMuted('" + player.htmlID() + "', true)") | ||||
| 			} else { | ||||
| 				player.Session().runScript("setMediaMuted('" + player.htmlID() + "', false)") | ||||
| 			} | ||||
| 
 | ||||
| 	case VolumeChangedEvent: | ||||
| 		if value := player.getRaw(tag); value != nil { | ||||
| 			updateProperty(player.htmlID(), "onvolumechange", "playerVolumeChangedEvent(this)", player.Session()) | ||||
| 		} else { | ||||
| 			updateProperty(player.htmlID(), "onvolumechange", "", player.Session()) | ||||
| 		case Preload: | ||||
| 			value, _ := enumProperty(player, tag, player.Session(), 0) | ||||
| 			values := enumProperties[Preload].values | ||||
| 			updateProperty(player.htmlID(), tag, values[value], player.Session()) | ||||
| 
 | ||||
| 		case AbortEvent, CanPlayEvent, CanPlayThroughEvent, CompleteEvent, EmptiedEvent, | ||||
| 			EndedEvent, LoadedDataEvent, LoadedMetadataEvent, PauseEvent, PlayEvent, PlayingEvent, ProgressEvent, | ||||
| 			LoadStartEvent, SeekedEvent, SeekingEvent, StalledEvent, SuspendEvent, WaitingEvent: | ||||
| 
 | ||||
| 			for _, event := range playerEvents() { | ||||
| 				if event.tag == tag { | ||||
| 					if value := player.getRaw(event.tag); value != nil { | ||||
| 						switch value := value.(type) { | ||||
| 						case []func(MediaPlayer): | ||||
| 							if len(value) > 0 { | ||||
| 								fn := fmt.Sprintf(`playerEvent(this, "%s")`, event.tag) | ||||
| 								updateProperty(player.htmlID(), event.cssTag, fn, player.Session()) | ||||
| 								return | ||||
| 							} | ||||
| 						} | ||||
| 					} | ||||
| 					updateProperty(player.htmlID(), tag, "", player.Session()) | ||||
| 					break | ||||
| 				} | ||||
| 
 | ||||
| 			} | ||||
| 		case TimeUpdateEvent: | ||||
| 			if value := player.getRaw(tag); value != nil { | ||||
| 				updateProperty(player.htmlID(), "ontimeupdate", "playerTimeUpdatedEvent(this)", player.Session()) | ||||
| 			} else { | ||||
| 				updateProperty(player.htmlID(), "ontimeupdate", "", player.Session()) | ||||
| 			} | ||||
| 
 | ||||
| 		case VolumeChangedEvent: | ||||
| 			if value := player.getRaw(tag); value != nil { | ||||
| 				updateProperty(player.htmlID(), "onvolumechange", "playerVolumeChangedEvent(this)", player.Session()) | ||||
| 			} else { | ||||
| 				updateProperty(player.htmlID(), "onvolumechange", "", player.Session()) | ||||
| 			} | ||||
| 
 | ||||
| 		case DurationChangedEvent: | ||||
| 			if value := player.getRaw(tag); value != nil { | ||||
| 				updateProperty(player.htmlID(), "ondurationchange", "playerDurationChangedEvent(this)", player.Session()) | ||||
| 			} else { | ||||
| 				updateProperty(player.htmlID(), "ondurationchange", "", player.Session()) | ||||
| 			} | ||||
| 
 | ||||
| 		case RateChangedEvent: | ||||
| 			if value := player.getRaw(tag); value != nil { | ||||
| 				updateProperty(player.htmlID(), "onratechange", "playerRateChangedEvent(this)", player.Session()) | ||||
| 			} else { | ||||
| 				updateProperty(player.htmlID(), "onratechange", "", player.Session()) | ||||
| 			} | ||||
| 
 | ||||
| 		case PlayerErrorEvent: | ||||
| 			if value := player.getRaw(tag); value != nil { | ||||
| 				updateProperty(player.htmlID(), "onerror", "playerErrorEvent(this)", player.Session()) | ||||
| 			} else { | ||||
| 				updateProperty(player.htmlID(), "onerror", "", player.Session()) | ||||
| 			} | ||||
| 
 | ||||
| 		case Source: | ||||
| 			updateInnerHTML(player.htmlID(), player.Session()) | ||||
| 		} | ||||
| 
 | ||||
| 	case DurationChangedEvent: | ||||
| 		if value := player.getRaw(tag); value != nil { | ||||
| 			updateProperty(player.htmlID(), "ondurationchange", "playerDurationChangedEvent(this)", player.Session()) | ||||
| 		} else { | ||||
| 			updateProperty(player.htmlID(), "ondurationchange", "", player.Session()) | ||||
| 		} | ||||
| 
 | ||||
| 	case RateChangedEvent: | ||||
| 		if value := player.getRaw(tag); value != nil { | ||||
| 			updateProperty(player.htmlID(), "onratechange", "playerRateChangedEvent(this)", player.Session()) | ||||
| 		} else { | ||||
| 			updateProperty(player.htmlID(), "onratechange", "", player.Session()) | ||||
| 		} | ||||
| 
 | ||||
| 	case PlayerErrorEvent: | ||||
| 		if value := player.getRaw(tag); value != nil { | ||||
| 			updateProperty(player.htmlID(), "onerror", "playerErrorEvent(this)", player.Session()) | ||||
| 		} else { | ||||
| 			updateProperty(player.htmlID(), "onerror", "", player.Session()) | ||||
| 		} | ||||
| 
 | ||||
| 	case Source: | ||||
| 		updateInnerHTML(player.htmlID(), player.Session()) | ||||
| 
 | ||||
| 	default: | ||||
| 		player.viewData.propertyChanged(tag) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -69,6 +69,7 @@ func (picker *numberPickerData) remove(tag string) { | |||
| 	case NumberChangedEvent: | ||||
| 		if len(picker.numberChangedListeners) > 0 { | ||||
| 			picker.numberChangedListeners = []func(NumberPicker, float64){} | ||||
| 			picker.propertyChangedEvent(tag) | ||||
| 		} | ||||
| 
 | ||||
| 	default: | ||||
|  | @ -135,18 +136,21 @@ func (picker *numberPickerData) set(tag string, value interface{}) bool { | |||
| 			} | ||||
| 			picker.numberChangedListeners = listeners | ||||
| 		} | ||||
| 		picker.propertyChangedEvent(tag) | ||||
| 		return true | ||||
| 
 | ||||
| 	case NumberPickerValue: | ||||
| 		oldValue := GetNumberPickerValue(picker, "") | ||||
| 		min, max := GetNumberPickerMinMax(picker, "") | ||||
| 		if picker.setFloatProperty(NumberPickerValue, value, min, max) { | ||||
| 			newValue := GetNumberPickerValue(picker, "") | ||||
| 			if oldValue != newValue { | ||||
| 				picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%f')`, picker.htmlID(), newValue)) | ||||
| 			if newValue := GetNumberPickerValue(picker, ""); oldValue != newValue { | ||||
| 				if picker.created { | ||||
| 					picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%f')`, picker.htmlID(), newValue)) | ||||
| 				} | ||||
| 				for _, listener := range picker.numberChangedListeners { | ||||
| 					listener(picker, newValue) | ||||
| 				} | ||||
| 				picker.propertyChangedEvent(tag) | ||||
| 			} | ||||
| 			return true | ||||
| 		} | ||||
|  | @ -161,34 +165,36 @@ func (picker *numberPickerData) set(tag string, value interface{}) bool { | |||
| } | ||||
| 
 | ||||
| func (picker *numberPickerData) propertyChanged(tag string) { | ||||
| 	switch tag { | ||||
| 	case NumberPickerType: | ||||
| 		if GetNumberPickerType(picker, "") == NumberSlider { | ||||
| 			updateProperty(picker.htmlID(), "type", "range", picker.session) | ||||
| 		} else { | ||||
| 			updateProperty(picker.htmlID(), "type", "number", picker.session) | ||||
| 		} | ||||
| 	if picker.created { | ||||
| 		switch tag { | ||||
| 		case NumberPickerType: | ||||
| 			if GetNumberPickerType(picker, "") == NumberSlider { | ||||
| 				updateProperty(picker.htmlID(), "type", "range", picker.session) | ||||
| 			} else { | ||||
| 				updateProperty(picker.htmlID(), "type", "number", picker.session) | ||||
| 			} | ||||
| 
 | ||||
| 	case NumberPickerMin: | ||||
| 		min, _ := GetNumberPickerMinMax(picker, "") | ||||
| 		updateProperty(picker.htmlID(), Min, strconv.FormatFloat(min, 'f', -1, 32), picker.session) | ||||
| 		case NumberPickerMin: | ||||
| 			min, _ := GetNumberPickerMinMax(picker, "") | ||||
| 			updateProperty(picker.htmlID(), Min, strconv.FormatFloat(min, 'f', -1, 32), picker.session) | ||||
| 
 | ||||
| 	case NumberPickerMax: | ||||
| 		_, max := GetNumberPickerMinMax(picker, "") | ||||
| 		updateProperty(picker.htmlID(), Max, strconv.FormatFloat(max, 'f', -1, 32), picker.session) | ||||
| 		case NumberPickerMax: | ||||
| 			_, max := GetNumberPickerMinMax(picker, "") | ||||
| 			updateProperty(picker.htmlID(), Max, strconv.FormatFloat(max, 'f', -1, 32), picker.session) | ||||
| 
 | ||||
| 	case NumberPickerStep: | ||||
| 		if step := GetNumberPickerStep(picker, ""); step > 0 { | ||||
| 			updateProperty(picker.htmlID(), Step, strconv.FormatFloat(step, 'f', -1, 32), picker.session) | ||||
| 		} else { | ||||
| 			updateProperty(picker.htmlID(), Step, "any", picker.session) | ||||
| 		} | ||||
| 		case NumberPickerStep: | ||||
| 			if step := GetNumberPickerStep(picker, ""); step > 0 { | ||||
| 				updateProperty(picker.htmlID(), Step, strconv.FormatFloat(step, 'f', -1, 32), picker.session) | ||||
| 			} else { | ||||
| 				updateProperty(picker.htmlID(), Step, "any", picker.session) | ||||
| 			} | ||||
| 
 | ||||
| 	case NumberPickerValue: | ||||
| 		value := GetNumberPickerValue(picker, "") | ||||
| 		picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%f')`, picker.htmlID(), value)) | ||||
| 		for _, listener := range picker.numberChangedListeners { | ||||
| 			listener(picker, value) | ||||
| 		case NumberPickerValue: | ||||
| 			value := GetNumberPickerValue(picker, "") | ||||
| 			picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%f')`, picker.htmlID(), value)) | ||||
| 			for _, listener := range picker.numberChangedListeners { | ||||
| 				listener(picker, value) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -246,7 +252,7 @@ func (picker *numberPickerData) htmlProperties(self View, buffer *strings.Builde | |||
| } | ||||
| 
 | ||||
| func (picker *numberPickerData) htmlDisabledProperties(self View, buffer *strings.Builder) { | ||||
| 	if IsDisabled(self) { | ||||
| 	if IsDisabled(self, "") { | ||||
| 		buffer.WriteString(` disabled`) | ||||
| 	} | ||||
| 	picker.viewData.htmlDisabledProperties(self, buffer) | ||||
|  |  | |||
|  | @ -58,12 +58,14 @@ func (progress *progressBarData) remove(tag string) { | |||
| } | ||||
| 
 | ||||
| func (progress *progressBarData) propertyChanged(tag string) { | ||||
| 	switch tag { | ||||
| 	case ProgressBarMax: | ||||
| 		updateProperty(progress.htmlID(), Max, strconv.FormatFloat(GetProgressBarMax(progress, ""), 'f', -1, 32), progress.session) | ||||
| 	if progress.created { | ||||
| 		switch tag { | ||||
| 		case ProgressBarMax: | ||||
| 			updateProperty(progress.htmlID(), Max, strconv.FormatFloat(GetProgressBarMax(progress, ""), 'f', -1, 32), progress.session) | ||||
| 
 | ||||
| 	case ProgressBarValue: | ||||
| 		updateProperty(progress.htmlID(), Value, strconv.FormatFloat(GetProgressBarValue(progress, ""), 'f', -1, 32), progress.session) | ||||
| 		case ProgressBarValue: | ||||
| 			updateProperty(progress.htmlID(), Value, strconv.FormatFloat(GetProgressBarValue(progress, ""), 'f', -1, 32), progress.session) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -367,8 +367,8 @@ const ( | |||
| 	// CenterY is the constant for the "center-x" property tag.
 | ||||
| 	CenterY = "center-y" | ||||
| 	// AltText is the constant for the "alt-text" property tag.
 | ||||
| 	AltText     = "alt-text" | ||||
| 	altProperty = "alt" | ||||
| 	AltText = "alt-text" | ||||
| 	altTag  = "alt" | ||||
| 	// AvoidBreak is the constant for the "avoid-break" property tag.
 | ||||
| 	// The "avoid-break" bool property sets how region breaks should behave inside a generated box.
 | ||||
| 	// If the property value is "true" then fvoids any break from being inserted within the principal box.
 | ||||
|  |  | |||
|  | @ -65,6 +65,7 @@ var intProperties = []string{ | |||
| 	FootHeight, | ||||
| 	RowSpan, | ||||
| 	ColumnSpan, | ||||
| 	ColumnCount, | ||||
| } | ||||
| 
 | ||||
| var floatProperties = map[string]struct{ min, max float64 }{ | ||||
|  |  | |||
							
								
								
									
										65
									
								
								resizable.go
								
								
								
								
							
							
						
						
									
										65
									
								
								resizable.go
								
								
								
								
							|  | @ -75,8 +75,11 @@ func (resizable *resizableData) remove(tag string) { | |||
| 		oldSide := resizable.getSide() | ||||
| 		delete(resizable.properties, Side) | ||||
| 		if oldSide != resizable.getSide() { | ||||
| 			updateInnerHTML(resizable.htmlID(), resizable.Session()) | ||||
| 			resizable.updateResizeBorderWidth() | ||||
| 			if resizable.created { | ||||
| 				updateInnerHTML(resizable.htmlID(), resizable.Session()) | ||||
| 				resizable.updateResizeBorderWidth() | ||||
| 			} | ||||
| 			resizable.propertyChangedEvent(tag) | ||||
| 		} | ||||
| 
 | ||||
| 	case ResizeBorderWidth: | ||||
|  | @ -84,12 +87,16 @@ func (resizable *resizableData) remove(tag string) { | |||
| 		delete(resizable.properties, ResizeBorderWidth) | ||||
| 		if !w.Equal(resizable.resizeBorderWidth()) { | ||||
| 			resizable.updateResizeBorderWidth() | ||||
| 			resizable.propertyChangedEvent(tag) | ||||
| 		} | ||||
| 
 | ||||
| 	case Content: | ||||
| 		if len(resizable.content) > 0 { | ||||
| 			resizable.content = []View{} | ||||
| 			updateInnerHTML(resizable.htmlID(), resizable.Session()) | ||||
| 			if resizable.created { | ||||
| 				updateInnerHTML(resizable.htmlID(), resizable.Session()) | ||||
| 			} | ||||
| 			resizable.propertyChangedEvent(tag) | ||||
| 		} | ||||
| 
 | ||||
| 	default: | ||||
|  | @ -110,20 +117,25 @@ func (resizable *resizableData) set(tag string, value interface{}) bool { | |||
| 	switch tag { | ||||
| 	case Side: | ||||
| 		oldSide := resizable.getSide() | ||||
| 		ok := resizable.setSide(value) | ||||
| 		if ok && oldSide != resizable.getSide() { | ||||
| 			updateInnerHTML(resizable.htmlID(), resizable.Session()) | ||||
| 			resizable.updateResizeBorderWidth() | ||||
| 		} else { | ||||
| 		if !resizable.setSide(value) { | ||||
| 			notCompatibleType(tag, value) | ||||
| 			return false | ||||
| 		} | ||||
| 		return ok | ||||
| 		if oldSide != resizable.getSide() { | ||||
| 			if resizable.created { | ||||
| 				updateInnerHTML(resizable.htmlID(), resizable.Session()) | ||||
| 				resizable.updateResizeBorderWidth() | ||||
| 			} | ||||
| 			resizable.propertyChangedEvent(tag) | ||||
| 		} | ||||
| 		return true | ||||
| 
 | ||||
| 	case ResizeBorderWidth: | ||||
| 		w := resizable.resizeBorderWidth() | ||||
| 		ok := resizable.setSizeProperty(tag, value) | ||||
| 		if ok && !w.Equal(resizable.resizeBorderWidth()) { | ||||
| 			resizable.updateResizeBorderWidth() | ||||
| 			resizable.propertyChangedEvent(tag) | ||||
| 		} | ||||
| 		return ok | ||||
| 
 | ||||
|  | @ -139,18 +151,25 @@ func (resizable *resizableData) set(tag string, value interface{}) bool { | |||
| 		case DataObject: | ||||
| 			if view := CreateViewFromObject(resizable.Session(), value); view != nil { | ||||
| 				newContent = view | ||||
| 			} else { | ||||
| 				return false | ||||
| 			} | ||||
| 
 | ||||
| 		default: | ||||
| 			notCompatibleType(tag, value) | ||||
| 			return false | ||||
| 		} | ||||
| 
 | ||||
| 		if newContent != nil { | ||||
| 			if len(resizable.content) == 0 { | ||||
| 				resizable.content = []View{newContent} | ||||
| 			} else { | ||||
| 				resizable.content[0] = newContent | ||||
| 			} | ||||
| 			updateInnerHTML(resizable.htmlID(), resizable.Session()) | ||||
| 			return true | ||||
| 		if len(resizable.content) == 0 { | ||||
| 			resizable.content = []View{newContent} | ||||
| 		} else { | ||||
| 			resizable.content[0] = newContent | ||||
| 		} | ||||
| 		if resizable.created { | ||||
| 			updateInnerHTML(resizable.htmlID(), resizable.Session()) | ||||
| 		} | ||||
| 		resizable.propertyChangedEvent(tag) | ||||
| 		return true | ||||
| 
 | ||||
| 	case CellWidth, CellHeight, GridRowGap, GridColumnGap, CellVerticalAlign, CellHorizontalAlign: | ||||
| 		ErrorLogF(`Not supported "%s" property`, tag) | ||||
|  | @ -306,12 +325,14 @@ func (resizable *resizableData) resizeBorderWidth() SizeUnit { | |||
| } | ||||
| 
 | ||||
| func (resizable *resizableData) updateResizeBorderWidth() { | ||||
| 	htmlID := resizable.htmlID() | ||||
| 	session := resizable.Session() | ||||
| 	column, row := resizable.cellSizeCSS() | ||||
| 	if resizable.created { | ||||
| 		htmlID := resizable.htmlID() | ||||
| 		session := resizable.Session() | ||||
| 		column, row := resizable.cellSizeCSS() | ||||
| 
 | ||||
| 	updateCSSProperty(htmlID, "grid-template-columns", column, session) | ||||
| 	updateCSSProperty(htmlID, "grid-template-rows", row, session) | ||||
| 		updateCSSProperty(htmlID, "grid-template-columns", column, session) | ||||
| 		updateCSSProperty(htmlID, "grid-template-rows", row, session) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (resizable *resizableData) cellSizeCSS() (string, string) { | ||||
|  |  | |||
|  | @ -6,6 +6,8 @@ import ( | |||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| // TODO PeekChangedEvent
 | ||||
| 
 | ||||
| const ( | ||||
| 	// DefaultAnimation - default animation of StackLayout push
 | ||||
| 	DefaultAnimation = 0 | ||||
|  | @ -93,23 +95,33 @@ func (layout *stackLayoutData) popFinished(view View, tag string) { | |||
| } | ||||
| 
 | ||||
| func (layout *stackLayoutData) Set(tag string, value interface{}) bool { | ||||
| 	if strings.ToLower(tag) == TransitionEndEvent { | ||||
| 	return layout.set(strings.ToLower(tag), value) | ||||
| } | ||||
| 
 | ||||
| func (layout *stackLayoutData) set(tag string, value interface{}) bool { | ||||
| 	if tag == TransitionEndEvent { | ||||
| 		listeners, ok := valueToAnimationListeners(value) | ||||
| 		if ok { | ||||
| 			listeners = append(listeners, layout.pushFinished) | ||||
| 			listeners = append(listeners, layout.popFinished) | ||||
| 			layout.properties[TransitionEndEvent] = listeners | ||||
| 			layout.propertyChangedEvent(TransitionEndEvent) | ||||
| 		} | ||||
| 		return ok | ||||
| 	} | ||||
| 	return layout.viewsContainerData.Set(tag, value) | ||||
| 	return layout.viewsContainerData.set(tag, value) | ||||
| } | ||||
| 
 | ||||
| func (layout *stackLayoutData) Remove(tag string) { | ||||
| 	if strings.ToLower(tag) == TransitionEndEvent { | ||||
| 	layout.remove(strings.ToLower(tag)) | ||||
| } | ||||
| 
 | ||||
| func (layout *stackLayoutData) remove(tag string) { | ||||
| 	if tag == TransitionEndEvent { | ||||
| 		layout.properties[TransitionEndEvent] = []func(View, string){layout.pushFinished, layout.popFinished} | ||||
| 		layout.propertyChangedEvent(TransitionEndEvent) | ||||
| 	} else { | ||||
| 		layout.viewsContainerData.Remove(tag) | ||||
| 		layout.viewsContainerData.remove(tag) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -238,6 +250,7 @@ func (layout *stackLayoutData) Push(view View, animation int, onPushFinished fun | |||
| 
 | ||||
| 	layout.views = append(layout.views, view) | ||||
| 	view.setParentID(htmlID) | ||||
| 	layout.propertyChangedEvent(Content) | ||||
| } | ||||
| 
 | ||||
| func (layout *stackLayoutData) Pop(animation int, onPopFinished func(View)) bool { | ||||
|  | @ -286,6 +299,7 @@ func (layout *stackLayoutData) Pop(animation int, onPopFinished func(View)) bool | |||
| 	} | ||||
| 
 | ||||
| 	updateCSSProperty(htmlID+"pop", "transform", value, layout.session) | ||||
| 	layout.propertyChangedEvent(Content) | ||||
| 	return true | ||||
| } | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										74
									
								
								tableView.go
								
								
								
								
							
							
						
						
									
										74
									
								
								tableView.go
								
								
								
								
							|  | @ -168,35 +168,51 @@ func (table *tableViewData) Init(session Session) { | |||
| 	table.tag = "TableView" | ||||
| } | ||||
| 
 | ||||
| func (table *tableViewData) normalizeTag(tag string) string { | ||||
| 	switch tag = strings.ToLower(tag); tag { | ||||
| 	case "top-cell-padding": | ||||
| 		tag = CellPaddingTop | ||||
| 
 | ||||
| 	case "right-cell-padding": | ||||
| 		tag = CellPaddingRight | ||||
| 
 | ||||
| 	case "bottom-cell-padding": | ||||
| 		tag = CellPaddingBottom | ||||
| 
 | ||||
| 	case "left-cell-padding": | ||||
| 		tag = CellPaddingLeft | ||||
| 	} | ||||
| 	return tag | ||||
| } | ||||
| 
 | ||||
| func (table *tableViewData) Get(tag string) interface{} { | ||||
| 	return table.get(strings.ToLower(tag)) | ||||
| 	return table.get(table.normalizeTag(tag)) | ||||
| } | ||||
| 
 | ||||
| func (table *tableViewData) Remove(tag string) { | ||||
| 	table.remove(strings.ToLower(tag)) | ||||
| 	table.remove(table.normalizeTag(tag)) | ||||
| } | ||||
| 
 | ||||
| func (table *tableViewData) remove(tag string) { | ||||
| 	switch tag { | ||||
| 
 | ||||
| 	case CellPaddingTop, CellPaddingRight, CellPaddingBottom, CellPaddingLeft, | ||||
| 		"top-cell-padding", "right-cell-padding", "bottom-cell-padding", "left-cell-padding": | ||||
| 	case CellPaddingTop, CellPaddingRight, CellPaddingBottom, CellPaddingLeft: | ||||
| 		table.removeBoundsSide(CellPadding, tag) | ||||
| 		table.propertyChanged(tag) | ||||
| 
 | ||||
| 	case Gap, CellBorder, CellPadding, RowStyle, ColumnStyle, CellStyle, | ||||
| 		HeadHeight, HeadStyle, FootHeight, FootStyle: | ||||
| 		delete(table.properties, tag) | ||||
| 		if _, ok := table.properties[tag]; ok { | ||||
| 			delete(table.properties, tag) | ||||
| 			table.propertyChanged(tag) | ||||
| 		} | ||||
| 
 | ||||
| 	default: | ||||
| 		table.viewData.remove(tag) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	table.propertyChanged(tag) | ||||
| } | ||||
| 
 | ||||
| func (table *tableViewData) Set(tag string, value interface{}) bool { | ||||
| 	return table.set(strings.ToLower(tag), value) | ||||
| 	return table.set(table.normalizeTag(tag), value) | ||||
| } | ||||
| 
 | ||||
| func (table *tableViewData) set(tag string, value interface{}) bool { | ||||
|  | @ -307,8 +323,7 @@ func (table *tableViewData) set(tag string, value interface{}) bool { | |||
| 			return false | ||||
| 		} | ||||
| 
 | ||||
| 	case CellPaddingTop, CellPaddingRight, CellPaddingBottom, CellPaddingLeft, | ||||
| 		"top-cell-padding", "right-cell-padding", "bottom-cell-padding", "left-cell-padding": | ||||
| 	case CellPaddingTop, CellPaddingRight, CellPaddingBottom, CellPaddingLeft: | ||||
| 		if !table.setBoundsSide(CellPadding, tag, value) { | ||||
| 			return false | ||||
| 		} | ||||
|  | @ -336,26 +351,27 @@ func (table *tableViewData) set(tag string, value interface{}) bool { | |||
| } | ||||
| 
 | ||||
| func (table *tableViewData) propertyChanged(tag string) { | ||||
| 	switch tag { | ||||
| 	case Content, RowStyle, ColumnStyle, CellStyle, CellPadding, CellBorder, | ||||
| 		HeadHeight, HeadStyle, FootHeight, FootStyle, | ||||
| 		CellPaddingTop, CellPaddingRight, CellPaddingBottom, CellPaddingLeft, | ||||
| 		"top-cell-padding", "right-cell-padding", "bottom-cell-padding", "left-cell-padding": | ||||
| 		table.ReloadTableData() | ||||
| 	if table.created { | ||||
| 		switch tag { | ||||
| 		case Content, RowStyle, ColumnStyle, CellStyle, CellPadding, CellBorder, | ||||
| 			HeadHeight, HeadStyle, FootHeight, FootStyle, | ||||
| 			CellPaddingTop, CellPaddingRight, CellPaddingBottom, CellPaddingLeft: | ||||
| 			table.ReloadTableData() | ||||
| 
 | ||||
| 	case Gap: | ||||
| 		htmlID := table.htmlID() | ||||
| 		session := table.Session() | ||||
| 		gap, ok := sizeProperty(table, Gap, session) | ||||
| 		if !ok || gap.Type == Auto || gap.Value <= 0 { | ||||
| 			updateCSSProperty(htmlID, "border-spacing", "0", session) | ||||
| 			updateCSSProperty(htmlID, "border-collapse", "collapse", session) | ||||
| 		} else { | ||||
| 			updateCSSProperty(htmlID, "border-spacing", gap.cssString("0"), session) | ||||
| 			updateCSSProperty(htmlID, "border-collapse", "separate", session) | ||||
| 		case Gap: | ||||
| 			htmlID := table.htmlID() | ||||
| 			session := table.Session() | ||||
| 			gap, ok := sizeProperty(table, Gap, session) | ||||
| 			if !ok || gap.Type == Auto || gap.Value <= 0 { | ||||
| 				updateCSSProperty(htmlID, "border-spacing", "0", session) | ||||
| 				updateCSSProperty(htmlID, "border-collapse", "collapse", session) | ||||
| 			} else { | ||||
| 				updateCSSProperty(htmlID, "border-spacing", gap.cssString("0"), session) | ||||
| 				updateCSSProperty(htmlID, "border-collapse", "separate", session) | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 	} | ||||
| 	table.propertyChangedEvent(tag) | ||||
| } | ||||
| 
 | ||||
| func (table *tableViewData) htmlTag() string { | ||||
|  |  | |||
|  | @ -123,15 +123,26 @@ func (tabsLayout *tabsLayoutData) Remove(tag string) { | |||
| func (tabsLayout *tabsLayoutData) remove(tag string) { | ||||
| 	switch tag { | ||||
| 	case CurrentTabChangedEvent: | ||||
| 		tabsLayout.tabListener = []func(TabsLayout, int, int){} | ||||
| 		if len(tabsLayout.tabListener) > 0 { | ||||
| 			tabsLayout.tabListener = []func(TabsLayout, int, int){} | ||||
| 			tabsLayout.propertyChangedEvent(tag) | ||||
| 		} | ||||
| 		return | ||||
| 
 | ||||
| 	case TabCloseEvent: | ||||
| 		tabsLayout.tabCloseListener = []func(TabsLayout, int){} | ||||
| 		if len(tabsLayout.tabCloseListener) > 0 { | ||||
| 			tabsLayout.tabCloseListener = []func(TabsLayout, int){} | ||||
| 			tabsLayout.propertyChangedEvent(tag) | ||||
| 		} | ||||
| 		return | ||||
| 
 | ||||
| 	case Current: | ||||
| 		oldCurrent := tabsLayout.currentItem() | ||||
| 		delete(tabsLayout.properties, Current) | ||||
| 		if !tabsLayout.session.ignoreViewUpdates() && oldCurrent != 0 { | ||||
| 		if oldCurrent == 0 { | ||||
| 			return | ||||
| 		} | ||||
| 		if tabsLayout.created { | ||||
| 			tabsLayout.session.runScript(fmt.Sprintf("activateTab(%v, %d);", tabsLayout.htmlID(), 0)) | ||||
| 			for _, listener := range tabsLayout.tabListener { | ||||
| 				listener(tabsLayout, 0, oldCurrent) | ||||
|  | @ -140,7 +151,7 @@ func (tabsLayout *tabsLayoutData) remove(tag string) { | |||
| 
 | ||||
| 	case Tabs: | ||||
| 		delete(tabsLayout.properties, Tabs) | ||||
| 		if !tabsLayout.session.ignoreViewUpdates() { | ||||
| 		if tabsLayout.created { | ||||
| 			htmlID := tabsLayout.htmlID() | ||||
| 			updateProperty(htmlID, inactiveTabStyle, tabsLayout.inactiveTabStyle(), tabsLayout.session) | ||||
| 			updateProperty(htmlID, activeTabStyle, tabsLayout.activeTabStyle(), tabsLayout.session) | ||||
|  | @ -150,7 +161,7 @@ func (tabsLayout *tabsLayoutData) remove(tag string) { | |||
| 
 | ||||
| 	case TabStyle, CurrentTabStyle: | ||||
| 		delete(tabsLayout.properties, tag) | ||||
| 		if !tabsLayout.session.ignoreViewUpdates() { | ||||
| 		if tabsLayout.created { | ||||
| 			htmlID := tabsLayout.htmlID() | ||||
| 			updateProperty(htmlID, inactiveTabStyle, tabsLayout.inactiveTabStyle(), tabsLayout.session) | ||||
| 			updateProperty(htmlID, activeTabStyle, tabsLayout.activeTabStyle(), tabsLayout.session) | ||||
|  | @ -159,13 +170,16 @@ func (tabsLayout *tabsLayoutData) remove(tag string) { | |||
| 
 | ||||
| 	case TabCloseButton: | ||||
| 		delete(tabsLayout.properties, tag) | ||||
| 		if !tabsLayout.session.ignoreViewUpdates() { | ||||
| 		if tabsLayout.created { | ||||
| 			updateInnerHTML(tabsLayout.htmlID(), tabsLayout.session) | ||||
| 		} | ||||
| 
 | ||||
| 	default: | ||||
| 		tabsLayout.viewsContainerData.remove(tag) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	tabsLayout.propertyChangedEvent(tag) | ||||
| } | ||||
| 
 | ||||
| func (tabsLayout *tabsLayoutData) Set(tag string, value interface{}) bool { | ||||
|  | @ -201,13 +215,14 @@ func (tabsLayout *tabsLayoutData) set(tag string, value interface{}) bool { | |||
| 			return false | ||||
| 		} | ||||
| 
 | ||||
| 		if !tabsLayout.session.ignoreViewUpdates() { | ||||
| 			current := tabsLayout.currentItem() | ||||
| 			if oldCurrent != current { | ||||
| 				tabsLayout.session.runScript(fmt.Sprintf("activateTab(%v, %d);", tabsLayout.htmlID(), current)) | ||||
| 				for _, listener := range tabsLayout.tabListener { | ||||
| 					listener(tabsLayout, current, oldCurrent) | ||||
| 				} | ||||
| 		current := tabsLayout.currentItem() | ||||
| 		if oldCurrent == current { | ||||
| 			return true | ||||
| 		} | ||||
| 		if tabsLayout.created { | ||||
| 			tabsLayout.session.runScript(fmt.Sprintf("activateTab(%v, %d);", tabsLayout.htmlID(), current)) | ||||
| 			for _, listener := range tabsLayout.tabListener { | ||||
| 				listener(tabsLayout, current, oldCurrent) | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
|  | @ -215,7 +230,7 @@ func (tabsLayout *tabsLayoutData) set(tag string, value interface{}) bool { | |||
| 		if !tabsLayout.setEnumProperty(Tabs, value, enumProperties[Tabs].values) { | ||||
| 			return false | ||||
| 		} | ||||
| 		if !tabsLayout.session.ignoreViewUpdates() { | ||||
| 		if tabsLayout.created { | ||||
| 			htmlID := tabsLayout.htmlID() | ||||
| 			updateProperty(htmlID, inactiveTabStyle, tabsLayout.inactiveTabStyle(), tabsLayout.session) | ||||
| 			updateProperty(htmlID, activeTabStyle, tabsLayout.activeTabStyle(), tabsLayout.session) | ||||
|  | @ -235,7 +250,7 @@ func (tabsLayout *tabsLayoutData) set(tag string, value interface{}) bool { | |||
| 			return false | ||||
| 		} | ||||
| 
 | ||||
| 		if !tabsLayout.session.ignoreViewUpdates() { | ||||
| 		if tabsLayout.created { | ||||
| 			htmlID := tabsLayout.htmlID() | ||||
| 			updateProperty(htmlID, inactiveTabStyle, tabsLayout.inactiveTabStyle(), tabsLayout.session) | ||||
| 			updateProperty(htmlID, activeTabStyle, tabsLayout.activeTabStyle(), tabsLayout.session) | ||||
|  | @ -246,7 +261,7 @@ func (tabsLayout *tabsLayoutData) set(tag string, value interface{}) bool { | |||
| 		if !tabsLayout.setBoolProperty(tag, value) { | ||||
| 			return false | ||||
| 		} | ||||
| 		if !tabsLayout.session.ignoreViewUpdates() { | ||||
| 		if tabsLayout.created { | ||||
| 			updateInnerHTML(tabsLayout.htmlID(), tabsLayout.session) | ||||
| 		} | ||||
| 
 | ||||
|  | @ -254,6 +269,7 @@ func (tabsLayout *tabsLayoutData) set(tag string, value interface{}) bool { | |||
| 		return tabsLayout.viewsContainerData.set(tag, value) | ||||
| 	} | ||||
| 
 | ||||
| 	tabsLayout.propertyChangedEvent(tag) | ||||
| 	return true | ||||
| } | ||||
| 
 | ||||
|  | @ -905,6 +921,7 @@ func (tabsLayout *tabsLayoutData) handleCommand(self View, command string, data | |||
| 					for _, listener := range tabsLayout.tabListener { | ||||
| 						listener(tabsLayout, number, current) | ||||
| 					} | ||||
| 					tabsLayout.propertyChangedEvent(Current) | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  |  | |||
							
								
								
									
										28
									
								
								textView.go
								
								
								
								
							
							
						
						
									
										28
									
								
								textView.go
								
								
								
								
							|  | @ -43,12 +43,14 @@ func (textView *textViewData) Remove(tag string) { | |||
| 
 | ||||
| func (textView *textViewData) remove(tag string) { | ||||
| 	textView.viewData.remove(tag) | ||||
| 	switch tag { | ||||
| 	case Text: | ||||
| 		updateInnerHTML(textView.htmlID(), textView.session) | ||||
| 	if textView.created { | ||||
| 		switch tag { | ||||
| 		case Text: | ||||
| 			updateInnerHTML(textView.htmlID(), textView.session) | ||||
| 
 | ||||
| 	case TextOverflow: | ||||
| 		textView.textOverflowUpdated() | ||||
| 		case TextOverflow: | ||||
| 			textView.textOverflowUpdated() | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -90,16 +92,24 @@ func (textView *textViewData) set(tag string, value interface{}) bool { | |||
| 				return false | ||||
| 			} | ||||
| 		} | ||||
| 		updateInnerHTML(textView.htmlID(), textView.session) | ||||
| 		return true | ||||
| 		if textView.created { | ||||
| 			updateInnerHTML(textView.htmlID(), textView.session) | ||||
| 		} | ||||
| 
 | ||||
| 	case TextOverflow: | ||||
| 		if textView.viewData.set(tag, value) { | ||||
| 		if !textView.viewData.set(tag, value) { | ||||
| 			return false | ||||
| 		} | ||||
| 		if textView.created { | ||||
| 			textView.textOverflowUpdated() | ||||
| 		} | ||||
| 
 | ||||
| 	default: | ||||
| 		return textView.viewData.set(tag, value) | ||||
| 	} | ||||
| 
 | ||||
| 	return textView.viewData.set(tag, value) | ||||
| 	textView.propertyChangedEvent(tag) | ||||
| 	return true | ||||
| } | ||||
| 
 | ||||
| func (textView *textViewData) textOverflowUpdated() { | ||||
|  |  | |||
|  | @ -63,28 +63,47 @@ func (picker *timePickerData) remove(tag string) { | |||
| 	case TimeChangedEvent: | ||||
| 		if len(picker.timeChangedListeners) > 0 { | ||||
| 			picker.timeChangedListeners = []func(TimePicker, time.Time){} | ||||
| 			picker.propertyChangedEvent(tag) | ||||
| 		} | ||||
| 		return | ||||
| 
 | ||||
| 	case TimePickerMin: | ||||
| 		delete(picker.properties, TimePickerMin) | ||||
| 		removeProperty(picker.htmlID(), Min, picker.session) | ||||
| 		if picker.created { | ||||
| 			removeProperty(picker.htmlID(), Min, picker.session) | ||||
| 		} | ||||
| 
 | ||||
| 	case TimePickerMax: | ||||
| 		delete(picker.properties, TimePickerMax) | ||||
| 		removeProperty(picker.htmlID(), Max, picker.session) | ||||
| 		if picker.created { | ||||
| 			removeProperty(picker.htmlID(), Max, picker.session) | ||||
| 		} | ||||
| 
 | ||||
| 	case TimePickerStep: | ||||
| 		delete(picker.properties, TimePickerMax) | ||||
| 		removeProperty(picker.htmlID(), Step, picker.session) | ||||
| 		if picker.created { | ||||
| 			removeProperty(picker.htmlID(), Step, picker.session) | ||||
| 		} | ||||
| 
 | ||||
| 	case TimePickerValue: | ||||
| 		delete(picker.properties, TimePickerValue) | ||||
| 		updateProperty(picker.htmlID(), Value, time.Now().Format(timeFormat), picker.session) | ||||
| 		if _, ok := picker.properties[TimePickerValue]; ok { | ||||
| 			delete(picker.properties, TimePickerValue) | ||||
| 			time := GetTimePickerValue(picker, "") | ||||
| 			if picker.created { | ||||
| 				picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, picker.htmlID(), time.Format(timeFormat))) | ||||
| 			} | ||||
| 			for _, listener := range picker.timeChangedListeners { | ||||
| 				listener(picker, time) | ||||
| 			} | ||||
| 		} else { | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 	default: | ||||
| 		picker.viewData.remove(tag) | ||||
| 		picker.propertyChanged(tag) | ||||
| 		return | ||||
| 	} | ||||
| 	picker.propertyChangedEvent(tag) | ||||
| } | ||||
| 
 | ||||
| func (picker *timePickerData) Set(tag string, value interface{}) bool { | ||||
|  | @ -121,7 +140,10 @@ func (picker *timePickerData) set(tag string, value interface{}) bool { | |||
| 		old, oldOK := getTimeProperty(picker, TimePickerMin, Min) | ||||
| 		if time, ok := setTimeValue(TimePickerMin); ok { | ||||
| 			if !oldOK || time != old { | ||||
| 				updateProperty(picker.htmlID(), Min, time.Format(timeFormat), picker.session) | ||||
| 				if picker.created { | ||||
| 					updateProperty(picker.htmlID(), Min, time.Format(timeFormat), picker.session) | ||||
| 				} | ||||
| 				picker.propertyChangedEvent(tag) | ||||
| 			} | ||||
| 			return true | ||||
| 		} | ||||
|  | @ -130,7 +152,10 @@ func (picker *timePickerData) set(tag string, value interface{}) bool { | |||
| 		old, oldOK := getTimeProperty(picker, TimePickerMax, Max) | ||||
| 		if time, ok := setTimeValue(TimePickerMax); ok { | ||||
| 			if !oldOK || time != old { | ||||
| 				updateProperty(picker.htmlID(), Max, time.Format(timeFormat), picker.session) | ||||
| 				if picker.created { | ||||
| 					updateProperty(picker.htmlID(), Max, time.Format(timeFormat), picker.session) | ||||
| 				} | ||||
| 				picker.propertyChangedEvent(tag) | ||||
| 			} | ||||
| 			return true | ||||
| 		} | ||||
|  | @ -138,13 +163,15 @@ func (picker *timePickerData) set(tag string, value interface{}) bool { | |||
| 	case TimePickerStep: | ||||
| 		oldStep := GetTimePickerStep(picker, "") | ||||
| 		if picker.setIntProperty(TimePickerStep, value) { | ||||
| 			step := GetTimePickerStep(picker, "") | ||||
| 			if oldStep != step { | ||||
| 				if step > 0 { | ||||
| 					updateProperty(picker.htmlID(), Step, strconv.Itoa(step), picker.session) | ||||
| 				} else { | ||||
| 					removeProperty(picker.htmlID(), Step, picker.session) | ||||
| 			if step := GetTimePickerStep(picker, ""); oldStep != step { | ||||
| 				if picker.created { | ||||
| 					if step > 0 { | ||||
| 						updateProperty(picker.htmlID(), Step, strconv.Itoa(step), picker.session) | ||||
| 					} else { | ||||
| 						removeProperty(picker.htmlID(), Step, picker.session) | ||||
| 					} | ||||
| 				} | ||||
| 				picker.propertyChangedEvent(tag) | ||||
| 			} | ||||
| 			return true | ||||
| 		} | ||||
|  | @ -152,11 +179,14 @@ func (picker *timePickerData) set(tag string, value interface{}) bool { | |||
| 	case TimePickerValue: | ||||
| 		oldTime := GetTimePickerValue(picker, "") | ||||
| 		if time, ok := setTimeValue(TimePickerMax); ok { | ||||
| 			picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, picker.htmlID(), time.Format(timeFormat))) | ||||
| 			if time != oldTime { | ||||
| 				if picker.created { | ||||
| 					picker.session.runScript(fmt.Sprintf(`setInputValue('%s', '%s')`, picker.htmlID(), time.Format(timeFormat))) | ||||
| 				} | ||||
| 				for _, listener := range picker.timeChangedListeners { | ||||
| 					listener(picker, time) | ||||
| 				} | ||||
| 				picker.propertyChangedEvent(tag) | ||||
| 			} | ||||
| 			return true | ||||
| 		} | ||||
|  | @ -167,8 +197,8 @@ func (picker *timePickerData) set(tag string, value interface{}) bool { | |||
| 			picker.timeChangedListeners = []func(TimePicker, time.Time){value} | ||||
| 
 | ||||
| 		case func(time.Time): | ||||
| 			fn := func(view TimePicker, date time.Time) { | ||||
| 				value(date) | ||||
| 			fn := func(view TimePicker, time time.Time) { | ||||
| 				value(time) | ||||
| 			} | ||||
| 			picker.timeChangedListeners = []func(TimePicker, time.Time){fn} | ||||
| 
 | ||||
|  | @ -183,8 +213,8 @@ func (picker *timePickerData) set(tag string, value interface{}) bool { | |||
| 					return false | ||||
| 				} | ||||
| 
 | ||||
| 				listeners[i] = func(view TimePicker, date time.Time) { | ||||
| 					val(date) | ||||
| 				listeners[i] = func(view TimePicker, time time.Time) { | ||||
| 					val(time) | ||||
| 				} | ||||
| 			} | ||||
| 			picker.timeChangedListeners = listeners | ||||
|  | @ -202,8 +232,8 @@ func (picker *timePickerData) set(tag string, value interface{}) bool { | |||
| 					listeners[i] = val | ||||
| 
 | ||||
| 				case func(time.Time): | ||||
| 					listeners[i] = func(view TimePicker, date time.Time) { | ||||
| 						val(date) | ||||
| 					listeners[i] = func(view TimePicker, time time.Time) { | ||||
| 						val(time) | ||||
| 					} | ||||
| 
 | ||||
| 				default: | ||||
|  | @ -213,13 +243,11 @@ func (picker *timePickerData) set(tag string, value interface{}) bool { | |||
| 			} | ||||
| 			picker.timeChangedListeners = listeners | ||||
| 		} | ||||
| 		picker.propertyChangedEvent(tag) | ||||
| 		return true | ||||
| 
 | ||||
| 	default: | ||||
| 		if picker.viewData.set(tag, value) { | ||||
| 			picker.propertyChanged(tag) | ||||
| 			return true | ||||
| 		} | ||||
| 		return picker.viewData.set(tag, value) | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
|  | @ -273,7 +301,7 @@ func (picker *timePickerData) htmlProperties(self View, buffer *strings.Builder) | |||
| } | ||||
| 
 | ||||
| func (picker *timePickerData) htmlDisabledProperties(self View, buffer *strings.Builder) { | ||||
| 	if IsDisabled(self) { | ||||
| 	if IsDisabled(self, "") { | ||||
| 		buffer.WriteString(` disabled`) | ||||
| 	} | ||||
| 	picker.viewData.htmlDisabledProperties(self, buffer) | ||||
|  |  | |||
							
								
								
									
										150
									
								
								view.go
								
								
								
								
							
							
						
						
									
										150
									
								
								view.go
								
								
								
								
							|  | @ -57,6 +57,8 @@ type View interface { | |||
| 	// a description of the error is written to the log
 | ||||
| 	SetAnimated(tag string, value interface{}, animation Animation) bool | ||||
| 
 | ||||
| 	SetChangeListener(tag string, listener func(View, string)) | ||||
| 
 | ||||
| 	handleCommand(self View, command string, data DataObject) bool | ||||
| 	//updateEventHandlers()
 | ||||
| 	htmlClass(disabled bool) string | ||||
|  | @ -87,6 +89,7 @@ type viewData struct { | |||
| 	_htmlID          string | ||||
| 	parentID         string | ||||
| 	systemClass      string | ||||
| 	changeListener   map[string]func(View, string) | ||||
| 	singleTransition map[string]Animation | ||||
| 	addCSS           map[string]string | ||||
| 	frame            Frame | ||||
|  | @ -129,6 +132,7 @@ func (view *viewData) Init(session Session) { | |||
| 	view.viewStyle.init() | ||||
| 	view.tag = "View" | ||||
| 	view.session = session | ||||
| 	view.changeListener = map[string]func(View, string){} | ||||
| 	view.addCSS = map[string]string{} | ||||
| 	//view.animation = map[string]AnimationEndListener{}
 | ||||
| 	view.singleTransition = map[string]Animation{} | ||||
|  | @ -186,7 +190,7 @@ func (view *viewData) remove(tag string) { | |||
| 	case Style, StyleDisabled: | ||||
| 		if _, ok := view.properties[tag]; ok { | ||||
| 			delete(view.properties, tag) | ||||
| 			updateProperty(view.htmlID(), "class", view.htmlClass(IsDisabled(view)), view.session) | ||||
| 			updateProperty(view.htmlID(), "class", view.htmlClass(IsDisabled(view, "")), view.session) | ||||
| 		} | ||||
| 
 | ||||
| 	case FocusEvent, LostFocusEvent: | ||||
|  | @ -221,8 +225,62 @@ func (view *viewData) remove(tag string) { | |||
| 
 | ||||
| 	default: | ||||
| 		view.viewStyle.remove(tag) | ||||
| 		view.propertyChanged(tag) | ||||
| 		viewPropertyChanged(view, tag) | ||||
| 	} | ||||
| 
 | ||||
| 	view.propertyChangedEvent(tag) | ||||
| } | ||||
| 
 | ||||
| func (view *viewData) propertyChangedEvent(tag string) { | ||||
| 	if listener, ok := view.changeListener[tag]; ok { | ||||
| 		listener(view, tag) | ||||
| 	} | ||||
| 
 | ||||
| 	switch tag { | ||||
| 	case BorderLeft, BorderRight, BorderTop, BorderBottom, | ||||
| 		BorderStyle, BorderLeftStyle, BorderRightStyle, BorderTopStyle, BorderBottomStyle, | ||||
| 		BorderColor, BorderLeftColor, BorderRightColor, BorderTopColor, BorderBottomColor, | ||||
| 		BorderWidth, BorderLeftWidth, BorderRightWidth, BorderTopWidth, BorderBottomWidth: | ||||
| 		tag = Border | ||||
| 
 | ||||
| 	case CellBorderStyle, CellBorderColor, CellBorderWidth, | ||||
| 		CellBorderLeft, CellBorderLeftStyle, CellBorderLeftColor, CellBorderLeftWidth, | ||||
| 		CellBorderRight, CellBorderRightStyle, CellBorderRightColor, CellBorderRightWidth, | ||||
| 		CellBorderTop, CellBorderTopStyle, CellBorderTopColor, CellBorderTopWidth, | ||||
| 		CellBorderBottom, CellBorderBottomStyle, CellBorderBottomColor, CellBorderBottomWidth: | ||||
| 		tag = CellBorder | ||||
| 
 | ||||
| 	case OutlineColor, OutlineStyle, OutlineWidth: | ||||
| 		tag = Outline | ||||
| 
 | ||||
| 	case RadiusX, RadiusY, RadiusTopLeft, RadiusTopLeftX, RadiusTopLeftY, | ||||
| 		RadiusTopRight, RadiusTopRightX, RadiusTopRightY, | ||||
| 		RadiusBottomLeft, RadiusBottomLeftX, RadiusBottomLeftY, | ||||
| 		RadiusBottomRight, RadiusBottomRightX, RadiusBottomRightY: | ||||
| 		tag = Radius | ||||
| 
 | ||||
| 	case MarginTop, MarginRight, MarginBottom, MarginLeft, | ||||
| 		"top-margin", "right-margin", "bottom-margin", "left-margin": | ||||
| 		tag = Margin | ||||
| 
 | ||||
| 	case PaddingTop, PaddingRight, PaddingBottom, PaddingLeft, | ||||
| 		"top-padding", "right-padding", "bottom-padding", "left-padding": | ||||
| 		tag = Padding | ||||
| 
 | ||||
| 	case CellPaddingTop, CellPaddingRight, CellPaddingBottom, CellPaddingLeft: | ||||
| 		tag = CellPadding | ||||
| 
 | ||||
| 	case ColumnSeparatorStyle, ColumnSeparatorWidth, ColumnSeparatorColor: | ||||
| 		tag = ColumnSeparator | ||||
| 
 | ||||
| 	default: | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	if listener, ok := view.changeListener[tag]; ok { | ||||
| 		listener(view, tag) | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| func (view *viewData) Set(tag string, value interface{}) bool { | ||||
|  | @ -235,64 +293,71 @@ func (view *viewData) set(tag string, value interface{}) bool { | |||
| 		return true | ||||
| 	} | ||||
| 
 | ||||
| 	result := func(res bool) bool { | ||||
| 		if res { | ||||
| 			view.propertyChangedEvent(tag) | ||||
| 		} | ||||
| 		return res | ||||
| 	} | ||||
| 
 | ||||
| 	switch tag { | ||||
| 	case ID: | ||||
| 		if text, ok := value.(string); ok { | ||||
| 			view.viewID = text | ||||
| 			return true | ||||
| 		text, ok := value.(string) | ||||
| 		if !ok { | ||||
| 			notCompatibleType(ID, value) | ||||
| 			return false | ||||
| 		} | ||||
| 		notCompatibleType(ID, value) | ||||
| 		return false | ||||
| 		view.viewID = text | ||||
| 
 | ||||
| 	case Style, StyleDisabled: | ||||
| 		if text, ok := value.(string); ok { | ||||
| 			view.properties[tag] = text | ||||
| 			//updateInnerHTML(view.parentID, view.session)
 | ||||
| 			if view.created { | ||||
| 				updateProperty(view.htmlID(), "class", view.htmlClass(IsDisabled(view)), view.session) | ||||
| 			} | ||||
| 			return true | ||||
| 		text, ok := value.(string) | ||||
| 		if !ok { | ||||
| 			notCompatibleType(ID, value) | ||||
| 			return false | ||||
| 		} | ||||
| 		view.properties[tag] = text | ||||
| 		if view.created { | ||||
| 			updateProperty(view.htmlID(), "class", view.htmlClass(IsDisabled(view, "")), view.session) | ||||
| 		} | ||||
| 		notCompatibleType(ID, value) | ||||
| 		return false | ||||
| 
 | ||||
| 	case FocusEvent, LostFocusEvent: | ||||
| 		return view.setFocusListener(tag, value) | ||||
| 		return result(view.setFocusListener(tag, value)) | ||||
| 
 | ||||
| 	case KeyDownEvent, KeyUpEvent: | ||||
| 		return view.setKeyListener(tag, value) | ||||
| 		return result(view.setKeyListener(tag, value)) | ||||
| 
 | ||||
| 	case ClickEvent, DoubleClickEvent, MouseDown, MouseUp, MouseMove, MouseOut, MouseOver, ContextMenuEvent: | ||||
| 		return view.setMouseListener(tag, value) | ||||
| 		return result(view.setMouseListener(tag, value)) | ||||
| 
 | ||||
| 	case PointerDown, PointerUp, PointerMove, PointerOut, PointerOver, PointerCancel: | ||||
| 		return view.setPointerListener(tag, value) | ||||
| 		return result(view.setPointerListener(tag, value)) | ||||
| 
 | ||||
| 	case TouchStart, TouchEnd, TouchMove, TouchCancel: | ||||
| 		return view.setTouchListener(tag, value) | ||||
| 		return result(view.setTouchListener(tag, value)) | ||||
| 
 | ||||
| 	case TransitionRunEvent, TransitionStartEvent, TransitionEndEvent, TransitionCancelEvent: | ||||
| 		return view.setTransitionListener(tag, value) | ||||
| 		return result(view.setTransitionListener(tag, value)) | ||||
| 
 | ||||
| 	case AnimationStartEvent, AnimationEndEvent, AnimationIterationEvent, AnimationCancelEvent: | ||||
| 		return view.setAnimationListener(tag, value) | ||||
| 		return result(view.setAnimationListener(tag, value)) | ||||
| 
 | ||||
| 	case ResizeEvent, ScrollEvent: | ||||
| 		return view.setFrameListener(tag, value) | ||||
| 	} | ||||
| 		return result(view.setFrameListener(tag, value)) | ||||
| 
 | ||||
| 	if view.viewStyle.set(tag, value) { | ||||
| 		if view.created { | ||||
| 			view.propertyChanged(tag) | ||||
| 	default: | ||||
| 		if !view.viewStyle.set(tag, value) { | ||||
| 			return false | ||||
| 		} | ||||
| 		if view.created { | ||||
| 			viewPropertyChanged(view, tag) | ||||
| 		} | ||||
| 		return true | ||||
| 	} | ||||
| 
 | ||||
| 	return false | ||||
| 	view.propertyChangedEvent(tag) | ||||
| 	return true | ||||
| } | ||||
| 
 | ||||
| func (view *viewData) propertyChanged(tag string) { | ||||
| 
 | ||||
| func viewPropertyChanged(view *viewData, tag string) { | ||||
| 	if view.updateTransformProperty(tag) { | ||||
| 		return | ||||
| 	} | ||||
|  | @ -446,7 +511,7 @@ func (view *viewData) propertyChanged(tag string) { | |||
| 	case Strikethrough, Overline, Underline: | ||||
| 		updateCSSProperty(htmlID, "text-decoration", view.cssTextDecoration(session), session) | ||||
| 		for _, tag2 := range []string{TextLineColor, TextLineStyle, TextLineThickness} { | ||||
| 			view.propertyChanged(tag2) | ||||
| 			viewPropertyChanged(view, tag2) | ||||
| 		} | ||||
| 		return | ||||
| 
 | ||||
|  | @ -568,7 +633,7 @@ func (view *viewData) htmlProperties(self View, buffer *strings.Builder) { | |||
| } | ||||
| 
 | ||||
| func (view *viewData) htmlDisabledProperties(self View, buffer *strings.Builder) { | ||||
| 	if IsDisabled(self) { | ||||
| 	if IsDisabled(self, "") { | ||||
| 		buffer.WriteString(` data-disabled="1"`) | ||||
| 	} else { | ||||
| 		buffer.WriteString(` data-disabled="0"`) | ||||
|  | @ -583,7 +648,7 @@ func viewHTML(view View, buffer *strings.Builder) { | |||
| 	buffer.WriteString(view.htmlID()) | ||||
| 	buffer.WriteRune('"') | ||||
| 
 | ||||
| 	disabled := IsDisabled(view) | ||||
| 	disabled := IsDisabled(view, "") | ||||
| 
 | ||||
| 	if cls := view.htmlClass(disabled); cls != "" { | ||||
| 		buffer.WriteString(` class="`) | ||||
|  | @ -660,7 +725,7 @@ func (view *viewData) handleCommand(self View, command string, data DataObject) | |||
| 	switch command { | ||||
| 
 | ||||
| 	case KeyDownEvent, KeyUpEvent: | ||||
| 		if !IsDisabled(self) { | ||||
| 		if !IsDisabled(self, "") { | ||||
| 			handleKeyEvents(self, command, data) | ||||
| 		} | ||||
| 
 | ||||
|  | @ -767,13 +832,10 @@ func (view *viewData) String() string { | |||
| 	return writer.finish() | ||||
| } | ||||
| 
 | ||||
| // IsDisabled returns "true" if the view is disabled
 | ||||
| func IsDisabled(view View) bool { | ||||
| 	if disabled, _ := boolProperty(view, Disabled, view.Session()); disabled { | ||||
| 		return true | ||||
| func (view *viewData) SetChangeListener(tag string, listener func(View, string)) { | ||||
| 	if listener == nil { | ||||
| 		delete(view.changeListener, tag) | ||||
| 	} else { | ||||
| 		view.changeListener[tag] = listener | ||||
| 	} | ||||
| 	if parent := view.Parent(); parent != nil { | ||||
| 		return IsDisabled(parent) | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
|  |  | |||
							
								
								
									
										45
									
								
								viewUtils.go
								
								
								
								
							
							
						
						
									
										45
									
								
								viewUtils.go
								
								
								
								
							|  | @ -4,7 +4,13 @@ package rui | |||
| // The type of return value depends on the property.
 | ||||
| // If the subview don't exists or the property is not set then nil is returned.
 | ||||
| func Get(rootView View, viewID, tag string) interface{} { | ||||
| 	if view := ViewByID(rootView, viewID); view != nil { | ||||
| 	var view View | ||||
| 	if viewID != "" { | ||||
| 		view = ViewByID(rootView, viewID) | ||||
| 	} else { | ||||
| 		view = rootView | ||||
| 	} | ||||
| 	if view != nil { | ||||
| 		return view.Get(tag) | ||||
| 	} | ||||
| 	return nil | ||||
|  | @ -14,12 +20,29 @@ func Get(rootView View, viewID, tag string) interface{} { | |||
| // true - success,
 | ||||
| // false - error (incompatible type or invalid format of a string value, see AppLog).
 | ||||
| func Set(rootView View, viewID, tag string, value interface{}) bool { | ||||
| 	if view := ViewByID(rootView, viewID); view != nil { | ||||
| 	var view View | ||||
| 	if viewID != "" { | ||||
| 		view = ViewByID(rootView, viewID) | ||||
| 	} else { | ||||
| 		view = rootView | ||||
| 	} | ||||
| 	if view != nil { | ||||
| 		return view.Set(tag, value) | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| // SetChangeListener sets a listener for changing a subview property value.
 | ||||
| // If the second argument (subviewID) is "" then a listener for the first argument (view) is set
 | ||||
| func SetChangeListener(view View, viewID, tag string, listener func(View, string)) { | ||||
| 	if viewID != "" { | ||||
| 		view = ViewByID(view, viewID) | ||||
| 	} | ||||
| 	if view != nil { | ||||
| 		view.SetChangeListener(tag, listener) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // SetParams sets properties with name "tag" of the "rootView" subview. Result:
 | ||||
| // true - all properties were set successful,
 | ||||
| // false - error (incompatible type or invalid format of a string value, see AppLog).
 | ||||
|  | @ -36,6 +59,22 @@ func SetParams(rootView View, viewID string, params Params) bool { | |||
| 	return result | ||||
| } | ||||
| 
 | ||||
| // IsDisabled returns "true" if the subview is disabled
 | ||||
| // If the second argument (subviewID) is "" then a state of the first argument (view) is returned
 | ||||
| func IsDisabled(view View, subviewID string) bool { | ||||
| 	if subviewID != "" { | ||||
| 		view = ViewByID(view, subviewID) | ||||
| 	} | ||||
| 
 | ||||
| 	if disabled, _ := boolProperty(view, Disabled, view.Session()); disabled { | ||||
| 		return true | ||||
| 	} | ||||
| 	if parent := view.Parent(); parent != nil { | ||||
| 		return IsDisabled(parent, "") | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| // GetSemantics returns the subview semantics.  Valid semantics values are
 | ||||
| // DefaultSemantics (0), ArticleSemantics (1), SectionSemantics (2), AsideSemantics (3),
 | ||||
| // HeaderSemantics (4), MainSemantics (5), FooterSemantics (6), NavigationSemantics (7),
 | ||||
|  | @ -926,7 +965,7 @@ func valueFromStyle(view View, tag string) (string, bool) { | |||
| 		return "", false | ||||
| 	} | ||||
| 
 | ||||
| 	if IsDisabled(view) { | ||||
| 	if IsDisabled(view, "") { | ||||
| 		if value, ok := getValue(StyleDisabled); ok { | ||||
| 			return value, true | ||||
| 		} | ||||
|  |  | |||
|  | @ -39,16 +39,6 @@ func (container *viewsContainerData) setParentID(parentID string) { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| // SetDisabled set the View disabled state
 | ||||
| func (container *viewsContainerData) SetDisabled(disabled bool) { | ||||
| 	container.viewData.Set(Disabled, disabled) | ||||
| 	if container.views != nil { | ||||
| 		for _, view := range container.views { | ||||
| 			view.Set(Disabled, disabled) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Views return a list of child views
 | ||||
| func (container *viewsContainerData) Views() []View { | ||||
| 	if container.views == nil { | ||||
|  | @ -68,6 +58,7 @@ func (container *viewsContainerData) Append(view View) { | |||
| 			container.views = append(container.views, view) | ||||
| 		} | ||||
| 		updateInnerHTML(container.htmlID(), container.session) | ||||
| 		container.propertyChangedEvent(Content) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -81,10 +72,12 @@ func (container *viewsContainerData) Insert(view View, index uint) { | |||
| 			view.setParentID(htmlID) | ||||
| 			container.views = append(container.views[:index], append([]View{view}, container.views[index:]...)...) | ||||
| 			updateInnerHTML(container.htmlID(), container.session) | ||||
| 			container.propertyChangedEvent(Content) | ||||
| 		} else { | ||||
| 			view.setParentID(htmlID) | ||||
| 			container.views = append([]View{view}, container.views...) | ||||
| 			updateInnerHTML(container.htmlID(), container.session) | ||||
| 			container.propertyChangedEvent(Content) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -112,6 +105,7 @@ func (container *viewsContainerData) RemoveView(index uint) View { | |||
| 
 | ||||
| 	view.setParentID("") | ||||
| 	updateInnerHTML(container.htmlID(), container.session) | ||||
| 	container.propertyChangedEvent(Content) | ||||
| 	return view | ||||
| } | ||||
| 
 | ||||
|  | @ -151,6 +145,18 @@ func (container *viewsContainerData) remove(tag string) { | |||
| 			container.views = []View{} | ||||
| 			updateInnerHTML(container.htmlID(), container.Session()) | ||||
| 		} | ||||
| 		container.propertyChangedEvent(Content) | ||||
| 
 | ||||
| 	case Disabled: | ||||
| 		if _, ok := container.properties[Disabled]; ok { | ||||
| 			delete(container.properties, Disabled) | ||||
| 			if container.views != nil { | ||||
| 				for _, view := range container.views { | ||||
| 					view.Remove(Disabled) | ||||
| 				} | ||||
| 			} | ||||
| 			container.propertyChangedEvent(tag) | ||||
| 		} | ||||
| 
 | ||||
| 	default: | ||||
| 		container.viewData.remove(tag) | ||||
|  | @ -167,7 +173,27 @@ func (container *viewsContainerData) set(tag string, value interface{}) bool { | |||
| 		return true | ||||
| 	} | ||||
| 
 | ||||
| 	if tag != Content { | ||||
| 	switch tag { | ||||
| 	case Content: | ||||
| 		// do nothing
 | ||||
| 
 | ||||
| 	case Disabled: | ||||
| 		oldDisabled := IsDisabled(container, "") | ||||
| 		if container.viewData.Set(Disabled, value) { | ||||
| 			disabled := IsDisabled(container, "") | ||||
| 			if oldDisabled != disabled { | ||||
| 				if container.views != nil { | ||||
| 					for _, view := range container.views { | ||||
| 						view.Set(Disabled, disabled) | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			container.propertyChangedEvent(tag) | ||||
| 			return true | ||||
| 		} | ||||
| 		return false | ||||
| 
 | ||||
| 	default: | ||||
| 		return container.viewData.set(tag, value) | ||||
| 	} | ||||
| 
 | ||||
|  | @ -239,6 +265,8 @@ func (container *viewsContainerData) set(tag string, value interface{}) bool { | |||
| 	if container.created { | ||||
| 		updateInnerHTML(htmlID, container.session) | ||||
| 	} | ||||
| 
 | ||||
| 	container.propertyChangedEvent(Content) | ||||
| 	return true | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue