Release 0.1.5, add css styles
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
group 'nl.astraeus'
|
group 'nl.astraeus'
|
||||||
version '0.1.5-SNAPSHOT'
|
version '0.1.6-SNAPSHOT'
|
||||||
|
|
||||||
apply plugin: 'kotlin2js'
|
apply plugin: 'kotlin2js'
|
||||||
apply plugin: 'kotlin-dce-js'
|
apply plugin: 'kotlin-dce-js'
|
||||||
|
|||||||
6
komp.iml
6
komp.iml
@@ -34,9 +34,9 @@
|
|||||||
<output-test url="file://$MODULE_DIR$/out/test/classes" />
|
<output-test url="file://$MODULE_DIR$/out/test/classes" />
|
||||||
<exclude-output />
|
<exclude-output />
|
||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/main/kotlin" type="kotlin-source" />
|
<sourceFolder url="file://$MODULE_DIR$/src/main/kotlin" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/test/kotlin" type="kotlin-test" />
|
<sourceFolder url="file://$MODULE_DIR$/src/test/kotlin" isTestSource="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="kotlin-resource" />
|
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
|
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build" />
|
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/out" />
|
<excludeFolder url="file://$MODULE_DIR$/out" />
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import kotlinx.html.Entities
|
|||||||
import kotlinx.html.Tag
|
import kotlinx.html.Tag
|
||||||
import kotlinx.html.TagConsumer
|
import kotlinx.html.TagConsumer
|
||||||
import kotlinx.html.Unsafe
|
import kotlinx.html.Unsafe
|
||||||
|
import org.w3c.dom.HTMLElement
|
||||||
import org.w3c.dom.Node
|
import org.w3c.dom.Node
|
||||||
import org.w3c.dom.events.Event
|
import org.w3c.dom.events.Event
|
||||||
import org.w3c.dom.get
|
import org.w3c.dom.get
|
||||||
@@ -25,20 +26,16 @@ enum class ElementType {
|
|||||||
|
|
||||||
class KompElement(
|
class KompElement(
|
||||||
val type: ElementType,
|
val type: ElementType,
|
||||||
val komponent: Komponent?,
|
val komponent: Komponent,
|
||||||
var text: String,
|
var text: String,
|
||||||
var attributes: MutableMap<String, String>? = null,
|
var attributes: MutableMap<String, String>? = null,
|
||||||
val children: MutableList<KompElement>? = null,
|
val children: MutableList<KompElement>? = null,
|
||||||
val events: MutableMap<String, (Event) -> Unit>? = null
|
val events: MutableMap<String, (Event) -> Unit>? = null
|
||||||
) {
|
) {
|
||||||
|
|
||||||
constructor(text: String, type: ElementType) : this(
|
constructor(komponent: Komponent, text: String, type: ElementType) : this(
|
||||||
type,
|
type,
|
||||||
if (type == ElementType.KOMPONENT) {
|
komponent,
|
||||||
throw IllegalStateException("Type KOMPONENT not allowed in String constructor")
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
},
|
|
||||||
text,
|
text,
|
||||||
if (type == ElementType.TAG) {
|
if (type == ElementType.TAG) {
|
||||||
HashMap()
|
HashMap()
|
||||||
@@ -68,7 +65,7 @@ class KompElement(
|
|||||||
|
|
||||||
/* shallow equals check */
|
/* shallow equals check */
|
||||||
fun equals(other: KompElement): Boolean {
|
fun equals(other: KompElement): Boolean {
|
||||||
if (komponent != null) {
|
if (other.isKomponent() && isKomponent()) {
|
||||||
val result = komponent == other.komponent
|
val result = komponent == other.komponent
|
||||||
if (!result && Komponent.logEquals) {
|
if (!result && Komponent.logEquals) {
|
||||||
console.log("!= komponent", this, other)
|
console.log("!= komponent", this, other)
|
||||||
@@ -129,18 +126,13 @@ class KompElement(
|
|||||||
ElementType.KOMPONENT -> {
|
ElementType.KOMPONENT -> {
|
||||||
val komp = komponent
|
val komp = komponent
|
||||||
|
|
||||||
if (komp == null) {
|
val kompElement = komp.create()
|
||||||
throw IllegalStateException("komponent == null in type Komponent!")
|
val element = kompElement.create()
|
||||||
} else {
|
|
||||||
|
|
||||||
val kompElement = komp.create()
|
komp.kompElement = kompElement
|
||||||
val element = kompElement.create()
|
komp.element = element
|
||||||
|
|
||||||
komp.kompElement = kompElement
|
element
|
||||||
komp.element = element
|
|
||||||
|
|
||||||
element
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ElementType.TEXT -> document.createTextNode(text)
|
ElementType.TEXT -> document.createTextNode(text)
|
||||||
ElementType.UNSAFE -> {
|
ElementType.UNSAFE -> {
|
||||||
@@ -179,7 +171,34 @@ class KompElement(
|
|||||||
}
|
}
|
||||||
|
|
||||||
(attributes?.entries)?.forEach { entry ->
|
(attributes?.entries)?.forEach { entry ->
|
||||||
result.setAttribute(entry.key, entry.value)
|
if (entry.key == "class") {
|
||||||
|
val classes = entry.value.split(" ")
|
||||||
|
val classNames = StringBuilder()
|
||||||
|
|
||||||
|
for (cls in classes) {
|
||||||
|
val cssStyle = komponent?.declaredStyles?.get(cls)
|
||||||
|
|
||||||
|
if (cssStyle != null) {
|
||||||
|
if (result is HTMLElement) {
|
||||||
|
for (index in 0 until cssStyle.length) {
|
||||||
|
val propertyName = cssStyle.item(index)
|
||||||
|
result.style.setProperty(propertyName, cssStyle.getPropertyValue(propertyName))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
classNames.append(cls)
|
||||||
|
classNames.append(" ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result !is HTMLElement) {
|
||||||
|
result.setAttribute(entry.key, entry.value)
|
||||||
|
} else {
|
||||||
|
result.className = classNames.toString()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.setAttribute(entry.key, entry.value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(events?.entries)?.forEach { event ->
|
(events?.entries)?.forEach { event ->
|
||||||
@@ -262,7 +281,9 @@ class UnsafeWrapper: Unsafe {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class KompConsumer : TagConsumer<KompElement> {
|
class KompConsumer(
|
||||||
|
val komponent: Komponent
|
||||||
|
) : TagConsumer<KompElement> {
|
||||||
val stack = ArrayList<KompElement>()
|
val stack = ArrayList<KompElement>()
|
||||||
var currentTag: KompElement? = null
|
var currentTag: KompElement? = null
|
||||||
|
|
||||||
@@ -280,7 +301,7 @@ class KompConsumer : TagConsumer<KompElement> {
|
|||||||
override fun onTagContent(content: CharSequence) {
|
override fun onTagContent(content: CharSequence) {
|
||||||
//console.log("KC.onTagContent", content)
|
//console.log("KC.onTagContent", content)
|
||||||
|
|
||||||
currentTag?.children?.add(KompElement(content.toString(), ElementType.TEXT))
|
currentTag?.children?.add(KompElement(komponent, content.toString(), ElementType.TEXT))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTagContentEntity(entity: Entities) {
|
override fun onTagContentEntity(entity: Entities) {
|
||||||
@@ -294,7 +315,7 @@ class KompConsumer : TagConsumer<KompElement> {
|
|||||||
block.invoke(txt)
|
block.invoke(txt)
|
||||||
|
|
||||||
//console.log("KC.onTagContentUnsafe", txt)
|
//console.log("KC.onTagContentUnsafe", txt)
|
||||||
currentTag?.children?.add(KompElement(txt.text, ElementType.UNSAFE))
|
currentTag?.children?.add(KompElement(komponent, txt.text, ElementType.UNSAFE))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTagEnd(tag: Tag) {
|
override fun onTagEnd(tag: Tag) {
|
||||||
@@ -326,7 +347,7 @@ class KompConsumer : TagConsumer<KompElement> {
|
|||||||
stack.add(this)
|
stack.add(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
currentTag = KompElement(tag.tagName, ElementType.TAG)
|
currentTag = KompElement(komponent, tag.tagName, ElementType.TAG)
|
||||||
|
|
||||||
currentTag?.attributes = tag.attributes
|
currentTag?.attributes = tag.attributes
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
package nl.astraeus.komp
|
package nl.astraeus.komp
|
||||||
|
|
||||||
import kotlinx.html.HtmlBlockTag
|
import kotlinx.html.HtmlBlockTag
|
||||||
|
import org.w3c.dom.HTMLDivElement
|
||||||
import org.w3c.dom.HTMLElement
|
import org.w3c.dom.HTMLElement
|
||||||
import org.w3c.dom.Node
|
import org.w3c.dom.Node
|
||||||
|
import org.w3c.dom.css.CSSStyleDeclaration
|
||||||
|
import kotlin.browser.document
|
||||||
|
|
||||||
fun HtmlBlockTag.include(component: Komponent) {
|
fun HtmlBlockTag.include(component: Komponent) {
|
||||||
val consumer = this.consumer
|
val consumer = this.consumer
|
||||||
@@ -19,48 +22,49 @@ enum class UpdateStrategy {
|
|||||||
abstract class Komponent {
|
abstract class Komponent {
|
||||||
var element: Node? = null
|
var element: Node? = null
|
||||||
var kompElement: KompElement? = null
|
var kompElement: KompElement? = null
|
||||||
var rendered = false
|
val declaredStyles: MutableMap<String, CSSStyleDeclaration> = HashMap()
|
||||||
|
|
||||||
open fun create(): KompElement {
|
open fun create(): KompElement {
|
||||||
val result = render(KompConsumer())
|
val result = render(KompConsumer(this))
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract fun render(consumer: KompConsumer): KompElement
|
abstract fun render(consumer: KompConsumer): KompElement
|
||||||
|
|
||||||
open fun refresh(forceRefresh: Boolean = false) {
|
open fun declareStyle(className: String, block: CSSStyleDeclaration.() -> Unit) {
|
||||||
if (!rendered || forceRefresh) {
|
val style = (document.createElement("div") as HTMLDivElement).style
|
||||||
element?.let { element ->
|
block(style)
|
||||||
if (logRenderEvent) {
|
declaredStyles[className] = style
|
||||||
console.log("Rendering", this)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
val newElement = create()
|
open fun refresh() {
|
||||||
|
element?.let { element ->
|
||||||
val replacedElement = if (updateStrategy == UpdateStrategy.REPLACE) {
|
if (logRenderEvent) {
|
||||||
//val replacedElement = replaceNode(newElement, element)
|
console.log("Rendering", this)
|
||||||
|
|
||||||
replaceNode(newElement, element)
|
|
||||||
} else if (kompElement != null) {
|
|
||||||
kompElement?.let {
|
|
||||||
DomDiffer.replaceDiff(it, newElement, element)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
newElement.create()
|
|
||||||
}
|
|
||||||
|
|
||||||
kompElement = newElement
|
|
||||||
this.element = replacedElement
|
|
||||||
rendered = true
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
update()
|
val newElement = create()
|
||||||
|
|
||||||
|
val replacedElement = if (updateStrategy == UpdateStrategy.REPLACE) {
|
||||||
|
//val replacedElement = replaceNode(newElement, element)
|
||||||
|
|
||||||
|
replaceNode(newElement, element)
|
||||||
|
} else if (kompElement != null) {
|
||||||
|
kompElement?.let {
|
||||||
|
DomDiffer.replaceDiff(it, newElement, element)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
newElement.create()
|
||||||
|
}
|
||||||
|
|
||||||
|
kompElement = newElement
|
||||||
|
this.element = replacedElement
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun update() {
|
open fun update() {
|
||||||
refresh(true)
|
refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
@@ -70,14 +74,12 @@ abstract class Komponent {
|
|||||||
other as Komponent
|
other as Komponent
|
||||||
|
|
||||||
if (kompElement != other.kompElement) return false
|
if (kompElement != other.kompElement) return false
|
||||||
if (rendered != other.rendered) return false
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
var result = kompElement?.hashCode() ?: 0
|
var result = kompElement?.hashCode() ?: 0
|
||||||
result = 31 * result + rendered.hashCode()
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,7 +93,7 @@ abstract class Komponent {
|
|||||||
fun replaceNode(newKomponent: KompElement, oldElement: Node): Node {
|
fun replaceNode(newKomponent: KompElement, oldElement: Node): Node {
|
||||||
val newElement = newKomponent.create()
|
val newElement = newKomponent.create()
|
||||||
|
|
||||||
if (Komponent.logReplaceEvent) {
|
if (logReplaceEvent) {
|
||||||
console.log("Replace", oldElement, newElement)
|
console.log("Replace", oldElement, newElement)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,7 +112,7 @@ abstract class Komponent {
|
|||||||
fun removeElement(element: Node) {
|
fun removeElement(element: Node) {
|
||||||
val parent = element.parentElement ?: throw IllegalArgumentException("Element has no parent!?")
|
val parent = element.parentElement ?: throw IllegalArgumentException("Element has no parent!?")
|
||||||
|
|
||||||
if (Komponent.logReplaceEvent) {
|
if (logReplaceEvent) {
|
||||||
console.log("Remove", element)
|
console.log("Remove", element)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user