Remove replace option

This commit is contained in:
2021-03-31 16:17:01 +02:00
parent e87f7ba540
commit 68fde339a8
3 changed files with 22 additions and 150 deletions

View File

@@ -5,7 +5,7 @@ plugins {
} }
group = "nl.astraeus" group = "nl.astraeus"
version = "0.2.6-SNAPSHOT" version = "0.3.0-SNAPSHOT"
repositories { repositories {
mavenCentral() mavenCentral()

View File

@@ -3,7 +3,6 @@ package nl.astraeus.komp
import kotlinx.browser.document import kotlinx.browser.document
import kotlinx.html.* import kotlinx.html.*
import org.w3c.dom.* import org.w3c.dom.*
import org.w3c.dom.css.CSSStyleDeclaration
import org.w3c.dom.events.Event import org.w3c.dom.events.Event
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
@@ -15,14 +14,11 @@ inline fun HTMLElement.setKompEvent(name: String, noinline callback: (Event) ->
} }
addEventListener(eventName, callback, null) addEventListener(eventName, callback, null)
if (Komponent.updateStrategy == UpdateStrategy.DOM_DIFF) { val events: MutableList<String> = (asDynamic()[EVENT_PROPERTY] as? MutableList<String>) ?: mutableListOf()
//asDynamic()[name] = callback
val events: MutableList<String> = (asDynamic()[EVENT_PROPERTY] as? MutableList<String>) ?: mutableListOf()
events.add(eventName) events.add(eventName)
asDynamic()[EVENT_PROPERTY] = events asDynamic()[EVENT_PROPERTY] = events
asDynamic()["event-$eventName"] = callback asDynamic()["event-$eventName"] = callback
}
} }
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
@@ -35,41 +31,16 @@ inline fun HTMLElement.removeKompEvent(name: String) {
removeEventListener(eventName, asDynamic()["event-$eventName"] as ((Event) -> Unit), null) removeEventListener(eventName, asDynamic()["event-$eventName"] as ((Event) -> Unit), null)
if (Komponent.updateStrategy == UpdateStrategy.DOM_DIFF) { val events: MutableList<String> = (asDynamic()[EVENT_PROPERTY] as? MutableList<String>) ?: mutableListOf()
//asDynamic()[name] = callback
val events: MutableList<String> = (asDynamic()[EVENT_PROPERTY] as? MutableList<String>) ?: mutableListOf()
events.remove(eventName) events.remove(eventName)
asDynamic()["event-$eventName"] = null asDynamic()["event-$eventName"] = null
}
}
fun HTMLElement.clearEvents() {
if (Komponent.updateStrategy == UpdateStrategy.DOM_DIFF) {
//asDynamic()[name] = callback
val events = getAttribute(EVENT_PROPERTY) ?: ""
for (eventName in events.split(",")) {
if (eventName.isNotBlank()) {
val event: (Event) -> Unit = asDynamic()["event-$eventName"]
removeEventListener(eventName, event)
}
}
}
} }
interface HtmlConsumer : TagConsumer<HTMLElement> { interface HtmlConsumer : TagConsumer<HTMLElement> {
fun append(node: Node) fun append(node: Node)
} }
fun HTMLElement.setStyles(cssStyle: CSSStyleDeclaration) {
for (index in 0 until cssStyle.length) {
val propertyName = cssStyle.item(index)
style.setProperty(propertyName, cssStyle.getPropertyValue(propertyName))
}
}
class HtmlBuilder( class HtmlBuilder(
val komponent: Komponent, val komponent: Komponent,
val document: Document, val document: Document,
@@ -121,80 +92,23 @@ class HtmlBuilder(
val element = path.last() val element = path.last()
if (Komponent.updateStrategy == UpdateStrategy.DOM_DIFF) { for (index in 0 until element.childNodes.length) {
for (index in 0 until element.childNodes.length) { val child = element.childNodes[index]
val child = element.childNodes[index] if (child is HTMLElement) {
if (child is HTMLElement) { hash = hash * 37 + child.getKompHash()
hash = hash * 37 + child.getKompHash() } else {
} else { hash = hash * 37 + (child?.textContent?.hashCode() ?: 0)
hash = hash * 37 + (child?.textContent?.hashCode() ?: 0)
}
} }
} }
for ((key, value) in tag.attributesEntries) { for ((key, value) in tag.attributesEntries) {
if (key == "class") { element.setAttribute(key, value)
val classes = value.split(Regex("\\s+"))
val classNames = StringBuilder()
for (cls in classes) { val key_value = "${key}-${value}"
val cssStyle = komponent.declaredStyles[cls] hash = hash * 37 + key_value.hashCode()
if (cssStyle != null) {
if (Komponent.updateStrategy == UpdateStrategy.DOM_DIFF) {
hash = hash * 37 + cssStyle.hashCode()
}
if (cls.endsWith(":hover")) {
val oldOnMouseOver = element.onmouseover
val oldOnMouseOut = element.onmouseout
element.onmouseover = {
element.setStyles(cssStyle)
oldOnMouseOver?.invoke(it)
}
element.onmouseout = {
cls.split(':').firstOrNull()?.let {
komponent.declaredStyles[it]?.let { cssStyle ->
element.setStyles(cssStyle)
}
}
oldOnMouseOut?.invoke(it)
}
} else {
element.setStyles(cssStyle)
}
} else {
if (Komponent.updateStrategy == UpdateStrategy.DOM_DIFF) {
hash = hash * 37 + cls.hashCode()
}
classNames.append(cls)
classNames.append(" ")
}
}
element.className = classNames.toString()
if (Komponent.updateStrategy == UpdateStrategy.DOM_DIFF) {
val key_value = "${key}-${classNames}"
hash = hash * 37 + key_value.hashCode()
}
} else {
element.setAttribute(key, value)
if (Komponent.updateStrategy == UpdateStrategy.DOM_DIFF) {
val key_value = "${key}-${value}"
hash = hash * 37 + key_value.hashCode()
}
}
} }
if (Komponent.updateStrategy == UpdateStrategy.DOM_DIFF) { element.setKompHash(baseHash * 53 + hash)
element.setKompHash(baseHash * 53 + hash)
}
lastLeaved = path.removeAt(path.lastIndex) lastLeaved = path.removeAt(path.lastIndex)
} }

View File

@@ -34,19 +34,7 @@ class StateDelegate<T>(
inline fun <reified T> Komponent.state(initialValue: T): StateDelegate<T> = StateDelegate(this, initialValue) inline fun <reified T> Komponent.state(initialValue: T): StateDelegate<T> = StateDelegate(this, initialValue)
fun HtmlConsumer.include(component: Komponent) { fun HtmlConsumer.include(component: Komponent) {
if (Komponent.updateStrategy == UpdateStrategy.REPLACE) { append(component.create())
if (component.element != null) {
component.update()
} else {
component.refresh()
}
component.element?.also {
append(it)
}
} else {
append(component.create())
}
} }
class DummyKomponent: Komponent() { class DummyKomponent: Komponent() {
@@ -57,11 +45,6 @@ class DummyKomponent: Komponent() {
} }
} }
enum class UpdateStrategy {
REPLACE,
DOM_DIFF
}
abstract class Komponent { abstract class Komponent {
private var createIndex = getNextCreateIndex() private var createIndex = getNextCreateIndex()
private var dirty: Boolean = true private var dirty: Boolean = true
@@ -121,39 +104,15 @@ abstract class Komponent {
val newElement = create() val newElement = create()
if (oldElement != null) { if (oldElement != null) {
element = if (updateStrategy == UpdateStrategy.REPLACE) { if (logReplaceEvent) {
if (logReplaceEvent) { console.log("DomDiffing", oldElement, newElement)
console.log("Replacing", oldElement, newElement)
}
oldElement.parentNode?.replaceChild(newElement, oldElement)
newElement
} else {
if (logReplaceEvent) {
console.log("DomDiffing", oldElement, newElement)
}
DiffPatch.updateNode(oldElement, newElement)
} }
element = DiffPatch.updateNode(oldElement, newElement)
} }
dirty = false dirty = false
} }
@JsName("remove")
fun remove() {
check(updateStrategy == UpdateStrategy.REPLACE) {
"remote only works with UpdateStrategy.REPLACE"
}
element?.let {
val parent = it.parentElement ?: throw IllegalArgumentException("Element has no parent!?")
if (logReplaceEvent) {
console.log("Remove", it)
}
parent.removeChild(it)
}
}
companion object { companion object {
private var nextCreateIndex: Int = 1 private var nextCreateIndex: Int = 1
private var updateCallback: Int? = null private var updateCallback: Int? = null
@@ -161,7 +120,6 @@ abstract class Komponent {
var logRenderEvent = false var logRenderEvent = false
var logReplaceEvent = false var logReplaceEvent = false
var updateStrategy = UpdateStrategy.DOM_DIFF
fun create(parent: HTMLElement, component: Komponent, insertAsFirst: Boolean = false) { fun create(parent: HTMLElement, component: Komponent, insertAsFirst: Boolean = false) {
val element = component.create() val element = component.create()