aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Jaros <rjaros@finn.pl>2019-04-24 20:13:17 +0200
committerRobert Jaros <rjaros@finn.pl>2019-04-24 20:13:17 +0200
commit833390a649c633892fbc0d9b6e37d6f7913cabb1 (patch)
treeafe334494ef1ab5265ed53d4f48e6fe389b532ef
parent7bc2dce08659b7cbcb3fd1865c7e3d95e8c42c52 (diff)
downloadkvision-833390a649c633892fbc0d9b6e37d6f7913cabb1.tar.gz
kvision-833390a649c633892fbc0d9b6e37d6f7913cabb1.tar.bz2
kvision-833390a649c633892fbc0d9b6e37d6f7913cabb1.zip
Fix various problems with re-creating DOM nodes.
-rw-r--r--kvision-modules/kvision-chart/src/main/kotlin/pl/treksoft/kvision/chart/ChartCanvas.kt1
-rw-r--r--kvision-modules/kvision-datetime/src/main/kotlin/pl/treksoft/kvision/form/time/DateTimeInput.kt57
-rw-r--r--kvision-modules/kvision-select/src/main/kotlin/pl/treksoft/kvision/form/select/SelectInput.kt3
-rw-r--r--kvision-modules/kvision-spinner/src/main/kotlin/pl/treksoft/kvision/form/spinner/SpinnerInput.kt1
-rw-r--r--kvision-modules/kvision-upload/src/main/kotlin/pl/treksoft/kvision/form/upload/UploadInput.kt4
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/core/Widget.kt19
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/dropdown/DropDown.kt1
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/check/CheckInput.kt8
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/text/AbstractTextInput.kt9
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/html/Canvas.kt9
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/modal/Modal.kt2
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/panel/SplitPanel.kt3
12 files changed, 76 insertions, 41 deletions
diff --git a/kvision-modules/kvision-chart/src/main/kotlin/pl/treksoft/kvision/chart/ChartCanvas.kt b/kvision-modules/kvision-chart/src/main/kotlin/pl/treksoft/kvision/chart/ChartCanvas.kt
index 09b68633..8d7c49a7 100644
--- a/kvision-modules/kvision-chart/src/main/kotlin/pl/treksoft/kvision/chart/ChartCanvas.kt
+++ b/kvision-modules/kvision-chart/src/main/kotlin/pl/treksoft/kvision/chart/ChartCanvas.kt
@@ -53,7 +53,6 @@ internal class ChartCanvas(
}
override fun afterInsert(node: VNode) {
- super.afterInsert(node)
jsChart =
JsChart(this.context2D, configuration.toJs(this::translate))
}
diff --git a/kvision-modules/kvision-datetime/src/main/kotlin/pl/treksoft/kvision/form/time/DateTimeInput.kt b/kvision-modules/kvision-datetime/src/main/kotlin/pl/treksoft/kvision/form/time/DateTimeInput.kt
index 69b84c87..7c1c8d71 100644
--- a/kvision-modules/kvision-datetime/src/main/kotlin/pl/treksoft/kvision/form/time/DateTimeInput.kt
+++ b/kvision-modules/kvision-datetime/src/main/kotlin/pl/treksoft/kvision/form/time/DateTimeInput.kt
@@ -51,7 +51,10 @@ open class DateTimeInput(
classes: Set<String> = setOf()
) : Widget(classes + "form-control"), FormInput {
+ private var initialized = false
+
init {
+ this.vnkey = "kv_datetimeinput_${counter++}"
this.setInternalEventListener<DateTimeInput> {
change = {
self.changeValue()
@@ -78,7 +81,7 @@ open class DateTimeInput(
/**
* Determines if the field is disabled.
*/
- override var disabled by refreshOnUpdate(false)
+ override var disabled by refreshOnUpdate(false) { refresh(); checkDisabled() }
/**
* Determines if the text input is automatically focused.
*/
@@ -160,6 +163,22 @@ open class DateTimeInput(
return sn
}
+ private fun checkDisabled() {
+ if (disabled) {
+ if (initialized) {
+ getElementJQueryD()?.datetimepicker("remove")
+ initialized = false
+ }
+ } else {
+ if (!initialized) {
+ this.initDateTimePicker()
+ this.initEventHandlers()
+ this.refreshState()
+ initialized = true
+ }
+ }
+ }
+
@Suppress("UnsafeCastFromDynamic")
protected open fun refreshState() {
value?.let {
@@ -190,35 +209,31 @@ open class DateTimeInput(
* Open date/time chooser popup.
*/
open fun showPopup() {
- getElementJQueryD()?.datetimepicker("show")
+ if (initialized) getElementJQueryD()?.datetimepicker("show")
}
/**
* Hides date/time chooser popup.
*/
open fun hidePopup() {
- getElementJQueryD()?.datetimepicker("hide")
+ if (initialized) getElementJQueryD()?.datetimepicker("hide")
}
@Suppress("UnsafeCastFromDynamic")
override fun afterInsert(node: VNode) {
if (!this.disabled) {
this.initDateTimePicker()
- this.getElementJQuery()?.on("changeDate") { e, _ ->
- this.dispatchEvent("change", obj { detail = e })
- }
- this.getElementJQuery()?.on("show") { e, _ ->
- this.dispatchEvent("showBsDateTime", obj { detail = e })
- }
- this.getElementJQuery()?.on("hide") { e, _ ->
- this.dispatchEvent("hideBsDateTime", obj { detail = e })
- }
- refreshState()
+ this.initEventHandlers()
+ this.refreshState()
+ initialized = true
}
}
override fun afterDestroy() {
- getElementJQueryD()?.datetimepicker("remove")
+ if (initialized) {
+ getElementJQueryD()?.datetimepicker("remove")
+ initialized = false
+ }
}
private fun initDateTimePicker() {
@@ -244,6 +259,18 @@ open class DateTimeInput(
})
}
+ private fun initEventHandlers() {
+ this.getElementJQuery()?.on("changeDate") { e, _ ->
+ this.dispatchEvent("change", obj { detail = e })
+ }
+ this.getElementJQuery()?.on("show") { e, _ ->
+ this.dispatchEvent("showBsDateTime", obj { detail = e })
+ }
+ this.getElementJQuery()?.on("hide") { e, _ ->
+ this.dispatchEvent("hideBsDateTime", obj { detail = e })
+ }
+ }
+
/**
* Get value of date/time input control as String
* @return value as a String
@@ -267,6 +294,8 @@ open class DateTimeInput(
}
companion object {
+ internal var counter = 0
+
private fun String.toDatePickerFormat(): String {
return this.replace("YY", "yy").replace("m", "i").replace("MMMM", "{----}").replace("MMM", "{---}")
.replace("M", "m").replace("{----}", "MM").replace("{---}", "M").replace("H", "{-}")
diff --git a/kvision-modules/kvision-select/src/main/kotlin/pl/treksoft/kvision/form/select/SelectInput.kt b/kvision-modules/kvision-select/src/main/kotlin/pl/treksoft/kvision/form/select/SelectInput.kt
index e89d4f5e..7ffdf2c2 100644
--- a/kvision-modules/kvision-select/src/main/kotlin/pl/treksoft/kvision/form/select/SelectInput.kt
+++ b/kvision-modules/kvision-select/src/main/kotlin/pl/treksoft/kvision/form/select/SelectInput.kt
@@ -130,6 +130,7 @@ open class SelectInput(
override var size: InputSize? by refreshOnUpdate()
init {
+ this.vnkey = "kv_selectinput_${counter++}"
setChildrenFromOptions()
this.setInternalEventListener<SelectInput> {
change = {
@@ -348,6 +349,8 @@ open class SelectInput(
}
companion object {
+ internal var counter = 0
+
/**
* DSL builder extension function.
*
diff --git a/kvision-modules/kvision-spinner/src/main/kotlin/pl/treksoft/kvision/form/spinner/SpinnerInput.kt b/kvision-modules/kvision-spinner/src/main/kotlin/pl/treksoft/kvision/form/spinner/SpinnerInput.kt
index a887c007..c60aab2f 100644
--- a/kvision-modules/kvision-spinner/src/main/kotlin/pl/treksoft/kvision/form/spinner/SpinnerInput.kt
+++ b/kvision-modules/kvision-spinner/src/main/kotlin/pl/treksoft/kvision/form/spinner/SpinnerInput.kt
@@ -74,6 +74,7 @@ open class SpinnerInput(
) : Widget(classes + "form-control"), FormInput {
init {
+ this.vnkey = "kv_spinnerinput_${counter++}"
this.addSurroundingCssClass("input-group")
if (buttonsType == ButtonsType.NONE) {
this.addSurroundingCssClass("kv-spinner-btn-none")
diff --git a/kvision-modules/kvision-upload/src/main/kotlin/pl/treksoft/kvision/form/upload/UploadInput.kt b/kvision-modules/kvision-upload/src/main/kotlin/pl/treksoft/kvision/form/upload/UploadInput.kt
index ee17949e..a250df42 100644
--- a/kvision-modules/kvision-upload/src/main/kotlin/pl/treksoft/kvision/form/upload/UploadInput.kt
+++ b/kvision-modules/kvision-upload/src/main/kotlin/pl/treksoft/kvision/form/upload/UploadInput.kt
@@ -138,6 +138,10 @@ open class UploadInput(uploadUrl: String? = null, multiple: Boolean = false, cla
private val nativeFiles: MutableMap<KFile, File> = mutableMapOf()
+ init {
+ this.vnkey = "kv_uploadinput_${counter++}"
+ }
+
override fun render(): VNode {
return render("input")
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt b/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt
index 7bbbcca3..3388a011 100644
--- a/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt
@@ -96,7 +96,8 @@ open class Widget(classes: Set<String> = setOf()) : StyledComponent() {
var eventTarget: Widget? = null
- private var vnode: VNode? = null
+ protected var vnkey: String? by refreshOnUpdate()
+ protected var vnode: VNode? = null
private var snAttrsCache: List<StringPair>? = null
private var snClassCache: List<StringBoolPair>? = null
@@ -182,6 +183,7 @@ open class Widget(classes: Set<String> = setOf()) : StyledComponent() {
*/
private fun getSnOpt(): VNodeData {
return snOpt {
+ if (vnkey != null) key = vnkey
attrs = snAttrs(getSnAttrsInternal())
style = snStyle(getSnStyleInternal())
`class` = snClasses(getSnClassInternal())
@@ -325,15 +327,6 @@ open class Widget(classes: Set<String> = setOf()) : StyledComponent() {
afterInsertInternal(v)
afterInsert(v)
}
- postpatch = { ov, v ->
- vnode = v
- if (ov.elm !== v.elm) {
- afterInsertInternal(v)
- afterInsert(v)
- } else {
- afterPostpatch(v)
- }
- }
destroy = {
afterDestroyInternal()
afterDestroy()
@@ -629,12 +622,6 @@ open class Widget(classes: Set<String> = setOf()) : StyledComponent() {
}
/**
- * Method called after updating Snabbdom vnode.
- */
- protected open fun afterPostpatch(node: VNode) {
- }
-
- /**
* Internal method called after destroying Snabbdom vnode.
*/
@Suppress("UnsafeCastFromDynamic")
diff --git a/src/main/kotlin/pl/treksoft/kvision/dropdown/DropDown.kt b/src/main/kotlin/pl/treksoft/kvision/dropdown/DropDown.kt
index a521fe95..b58860ff 100644
--- a/src/main/kotlin/pl/treksoft/kvision/dropdown/DropDown.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/dropdown/DropDown.kt
@@ -149,6 +149,7 @@ open class DropDown(
internal val list: DropDownListTag = DropDownListTag(idc, setOf("dropdown-menu"))
init {
+ this.vnkey = "kv_dropdown_$counter"
setChildrenFromElements()
this.addInternal(button)
this.addInternal(list)
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/check/CheckInput.kt b/src/main/kotlin/pl/treksoft/kvision/form/check/CheckInput.kt
index 0184c779..6973efe9 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/check/CheckInput.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/check/CheckInput.kt
@@ -51,6 +51,7 @@ abstract class CheckInput(
) : Widget(classes), FormInput {
init {
+ this.vnkey = "kv_checkinput_${counter++}"
this.setInternalEventListener<CheckInput> {
click = {
val v = getElementJQuery()?.prop("checked") as Boolean?
@@ -129,10 +130,6 @@ abstract class CheckInput(
refreshState()
}
- override fun afterPostpatch(node: VNode) {
- refreshState()
- }
-
private fun refreshState() {
val v = getElementJQuery()?.prop("checked") as Boolean?
if (this.value != v) {
@@ -166,4 +163,7 @@ abstract class CheckInput(
getElementJQuery()?.blur()
}
+ companion object {
+ internal var counter = 0
+ }
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/text/AbstractTextInput.kt b/src/main/kotlin/pl/treksoft/kvision/form/text/AbstractTextInput.kt
index 3a06f47b..c9ea2dba 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/text/AbstractTextInput.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/text/AbstractTextInput.kt
@@ -41,6 +41,7 @@ abstract class AbstractTextInput(
) : Widget(classes), FormInput {
init {
+ this.vnkey = "kv_textinput_${counter++}"
this.setInternalEventListener<AbstractTextInput> {
input = {
self.changeValue()
@@ -127,10 +128,6 @@ abstract class AbstractTextInput(
refreshState()
}
- override fun afterPostpatch(node: VNode) {
- refreshState()
- }
-
/**
* @suppress
* Internal function
@@ -170,4 +167,8 @@ abstract class AbstractTextInput(
open fun blur() {
getElementJQuery()?.blur()
}
+
+ companion object {
+ internal var counter = 0
+ }
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/html/Canvas.kt b/src/main/kotlin/pl/treksoft/kvision/html/Canvas.kt
index 450042a2..476ee118 100644
--- a/src/main/kotlin/pl/treksoft/kvision/html/Canvas.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/html/Canvas.kt
@@ -53,6 +53,10 @@ open class Canvas(
*/
lateinit var context2D: CanvasRenderingContext2D
+ init {
+ this.vnkey = "kv_canvas_${counter++}"
+ }
+
override fun render(): VNode {
return render("canvas")
}
@@ -68,11 +72,14 @@ open class Canvas(
return pr
}
- override fun afterInsert(node: VNode) {
+ override fun afterInsertInternal(node: VNode) {
+ super.afterInsertInternal(node)
context2D = (node.elm as HTMLCanvasElement).getContext("2d") as CanvasRenderingContext2D
}
companion object {
+ internal var counter = 0
+
/**
* DSL builder extension function.
*
diff --git a/src/main/kotlin/pl/treksoft/kvision/modal/Modal.kt b/src/main/kotlin/pl/treksoft/kvision/modal/Modal.kt
index 5f911539..5d872b08 100644
--- a/src/main/kotlin/pl/treksoft/kvision/modal/Modal.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/modal/Modal.kt
@@ -110,6 +110,7 @@ open class Modal(
private val footer = SimplePanel(setOf("modal-footer"))
init {
+ this.vnkey = "kv_modal_${counter++}"
this.hide()
this.role = "dialog"
this.addInternal(dialog)
@@ -270,6 +271,7 @@ open class Modal(
}
companion object {
+ internal var counter = 0
internal var modals = mutableListOf<Modal>()
}
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/panel/SplitPanel.kt b/src/main/kotlin/pl/treksoft/kvision/panel/SplitPanel.kt
index d3211d7a..7b046e1a 100644
--- a/src/main/kotlin/pl/treksoft/kvision/panel/SplitPanel.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/panel/SplitPanel.kt
@@ -123,8 +123,9 @@ internal class Splitter(private val splitPanel: SplitPanel, direction: Direction
private val idc = "kv_splitter_$counter"
init {
- counter++
+ this.vnkey = "kv_splitter_$counter"
this.id = idc
+ counter++
}
override fun afterInsert(node: VNode) {