summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/Main.kt3
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/Showcase.kt16
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/core/Container.kt1
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/core/KVManager.kt5
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/core/Root.kt6
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/core/Widget.kt51
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/dropdown/DropDown.kt32
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/snabbdom/Types.kt22
-rw-r--r--src/test/kotlin/test/pl/treksoft/kvision/core/WidgetSpec.kt17
-rw-r--r--src/test/kotlin/test/pl/treksoft/kvision/dropdown/DropDownSpec.kt17
10 files changed, 159 insertions, 11 deletions
diff --git a/src/main/kotlin/pl/treksoft/kvision/Main.kt b/src/main/kotlin/pl/treksoft/kvision/Main.kt
index 385d23e8..e4816888 100644
--- a/src/main/kotlin/pl/treksoft/kvision/Main.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/Main.kt
@@ -1,5 +1,6 @@
package pl.treksoft.kvision
+import pl.treksoft.kvision.core.KVManager
import kotlin.browser.document
fun main(args: Array<String>) {
@@ -10,6 +11,7 @@ fun main(args: Array<String>) {
hot.dispose { data ->
data.appState = application?.dispose()
+ KVManager.shutdown()
application = null
}
@@ -19,6 +21,7 @@ fun main(args: Array<String>) {
if (document.body != null) {
application = start(state)
} else {
+ KVManager.init()
application = null
document.addEventListener("DOMContentLoaded", { application = start(state) })
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/Showcase.kt b/src/main/kotlin/pl/treksoft/kvision/Showcase.kt
index b2e6d764..6275fe88 100644
--- a/src/main/kotlin/pl/treksoft/kvision/Showcase.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/Showcase.kt
@@ -3,7 +3,6 @@ package pl.treksoft.kvision
import pl.treksoft.kvision.basic.Label
import pl.treksoft.kvision.core.Container
import pl.treksoft.kvision.core.Img
-import pl.treksoft.kvision.core.KVManager
import pl.treksoft.kvision.core.Root
import pl.treksoft.kvision.dropdown.DD.*
import pl.treksoft.kvision.dropdown.DropDown
@@ -32,11 +31,21 @@ class Showcase : ApplicationBase() {
val dd = DropDown("Dropdown", listOf("abc" to "#!/x", "def" to "#!/y"), "flag")
root.add(dd)
+ dd.setEventListener<Button> {
+ showBsDropdown = { e -> println("show" + (e.detail)?.text) }
+ shownBsDropdown = { e -> println("shown" + e.detail) }
+ hideBsDropdown = { e -> println("hide" + e.detail) }
+ hiddenBsDropdown = { e -> println("hidden" + e.detail) }
+ }
val dd2 = DropDown("Dropdown2", listOf("abc" to "#!/abc", "def" to "#!/def", "xyz" to DISABLED.POS,
"Header" to HEADER.POS, "Separtatorek" to SEPARATOR.POS
), "flag", dropup = true)
root.add(dd2)
+ dd2.setEventListener<Button> {
+ hideBsDropdown = { e -> println("hide" + e.detail) }
+ hiddenBsDropdown = { e -> println("hidden" + e.detail) }
+ }
val p = Tag(TAG.P, "To jest prawo", align = ALIGN.RIGHT)
p.title = "Tytuł"
@@ -65,6 +74,7 @@ class Showcase : ApplicationBase() {
val button2 = Button("To jest przycisk", "flag", BUTTONSTYLE.DANGER)
button2.setEventListener {
click = { e ->
+ dd.hide()
println("2" + e)
button.setEventListener {
click = null
@@ -75,6 +85,7 @@ class Showcase : ApplicationBase() {
val button3 = Button("To jest przycisk IMG", image = Img("kotlin.png"))
button3.setEventListener {
click = { e ->
+ dd.show()
println("3" + e)
button.setEventListener<Button> {
click = { _ -> println(self.text) }
@@ -90,6 +101,8 @@ class Showcase : ApplicationBase() {
.on("/test", { -> println("test") })
.resolve()
+// jQuery(document).off(".data-api")
+
// routing.on(RegExp("/abc/def/(.*)/(.*)/(.*)"), { x,y,z,u,v -> println(x) })
// router.on("/test", { -> println("test") })
@@ -113,7 +126,6 @@ class Showcase : ApplicationBase() {
}
override fun dispose(): Map<String, Any> {
- KVManager.shutdown()
return mapOf<String, Any>()
}
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/core/Container.kt b/src/main/kotlin/pl/treksoft/kvision/core/Container.kt
index e8d277dc..028c55ce 100644
--- a/src/main/kotlin/pl/treksoft/kvision/core/Container.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/core/Container.kt
@@ -35,4 +35,5 @@ open class Container(classes: Set<String> = setOf()) : Widget(classes) {
children.removeAt(index).clearParent()
refresh()
}
+
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/core/KVManager.kt b/src/main/kotlin/pl/treksoft/kvision/core/KVManager.kt
index ab95a162..1d937511 100644
--- a/src/main/kotlin/pl/treksoft/kvision/core/KVManager.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/core/KVManager.kt
@@ -8,6 +8,7 @@ import com.github.snabbdom.datasetModule
import com.github.snabbdom.eventListenersModule
import com.github.snabbdom.propsModule
import com.github.snabbdom.styleModule
+import pl.treksoft.jquery.jQuery
import pl.treksoft.kvision.require
import pl.treksoft.kvision.routing.routing
import kotlin.browser.document
@@ -36,6 +37,10 @@ object KVManager {
return sdVirtualize(html)
}
+ fun init() {
+ jQuery(document).off(".data-api")
+ }
+
fun shutdown() {
routing.destroy()
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/core/Root.kt b/src/main/kotlin/pl/treksoft/kvision/core/Root.kt
index bea4db5e..c5f4a2d6 100644
--- a/src/main/kotlin/pl/treksoft/kvision/core/Root.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/core/Root.kt
@@ -4,10 +4,10 @@ import com.github.snabbdom.VNode
import pl.treksoft.kvision.snabbdom.StringBoolPair
class Root(id: String, private val fluid: Boolean = false) : Container() {
- private var vnode: VNode = render()
+ private var rootVnode: VNode = render()
init {
- vnode = KVManager.patch(id, this.render())
+ rootVnode = KVManager.patch(id, this.render())
this.id = id
}
@@ -21,7 +21,7 @@ class Root(id: String, private val fluid: Boolean = false) : Container() {
}
override fun refresh() {
- vnode = KVManager.patch(vnode, render())
+ rootVnode = KVManager.patch(rootVnode, render())
}
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt b/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt
index a1405135..142c3069 100644
--- a/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt
@@ -3,10 +3,14 @@ package pl.treksoft.kvision.core
import com.github.snabbdom.VNode
import com.github.snabbdom.VNodeData
import com.github.snabbdom.h
-import pl.treksoft.kvision.snabbdom.on
+import org.w3c.dom.Node
+import pl.treksoft.jquery.JQuery
+import pl.treksoft.jquery.jQuery
import pl.treksoft.kvision.snabbdom.SnOn
import pl.treksoft.kvision.snabbdom.StringBoolPair
import pl.treksoft.kvision.snabbdom.StringPair
+import pl.treksoft.kvision.snabbdom.hooks
+import pl.treksoft.kvision.snabbdom.on
import pl.treksoft.kvision.snabbdom.snAttrs
import pl.treksoft.kvision.snabbdom.snClasses
import pl.treksoft.kvision.snabbdom.snOpt
@@ -42,6 +46,8 @@ open class Widget(classes: Set<String> = setOf()) : KVObject {
refresh()
}
+ private var vnode: VNode? = null
+
internal open fun render(): VNode {
return kvh("div")
}
@@ -60,6 +66,7 @@ open class Widget(classes: Set<String> = setOf()) : KVObject {
style = snStyle(getSnStyle())
`class` = snClasses(getSnClass())
on = getSnOn()
+ hook = getSnHooks()
}
}
@@ -86,10 +93,29 @@ open class Widget(classes: Set<String> = setOf()) : KVObject {
return snattrs
}
- protected open fun getSnOn(): com.github.snabbdom.On {
- val handlers = on(this)
- listeners.forEach { on -> (handlers::apply)(on) }
- return handlers
+ protected open fun getSnOn(): com.github.snabbdom.On? {
+ if (listeners.size > 0) {
+ val handlers = on(this)
+ listeners.forEach { l -> (handlers::apply)(l) }
+ return handlers
+ } else {
+ return null
+ }
+ }
+
+ protected open fun getSnHooks(): com.github.snabbdom.Hooks? {
+ val hooks = hooks()
+ hooks.apply {
+ insert = { v ->
+ vnode = v
+ afterInsert(v)
+ }
+ postpatch = { ov, v ->
+ vnode = v
+ if (ov.elm !== v.elm) afterInsert(v)
+ }
+ }
+ return hooks
}
@Suppress("UNCHECKED_CAST")
@@ -126,6 +152,18 @@ open class Widget(classes: Set<String> = setOf()) : KVObject {
refresh()
}
+ open fun getElement(): Node? {
+ return this.vnode?.elm
+ }
+
+ open fun getElementJQuery(): JQuery? {
+ return getElement()?.let { jQuery(it) }
+ }
+
+ open fun getElementJQueryD(): dynamic {
+ return getElement()?.let { jQuery(it).asDynamic() }
+ }
+
internal fun clearParent() {
this.parent = null
}
@@ -133,4 +171,7 @@ open class Widget(classes: Set<String> = setOf()) : KVObject {
protected open fun refresh() {
this.parent?.refresh()
}
+
+ protected open fun afterInsert(node: VNode) {
+ }
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/dropdown/DropDown.kt b/src/main/kotlin/pl/treksoft/kvision/dropdown/DropDown.kt
index 18946b27..d33b53d9 100644
--- a/src/main/kotlin/pl/treksoft/kvision/dropdown/DropDown.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/dropdown/DropDown.kt
@@ -1,5 +1,7 @@
package pl.treksoft.kvision.dropdown
+import com.github.snabbdom.VNode
+import org.w3c.dom.CustomEvent
import pl.treksoft.kvision.core.Container
import pl.treksoft.kvision.core.ResString
import pl.treksoft.kvision.html.BUTTONSIZE
@@ -11,6 +13,7 @@ import pl.treksoft.kvision.html.ListTag
import pl.treksoft.kvision.html.TAG
import pl.treksoft.kvision.html.Tag
import pl.treksoft.kvision.snabbdom.StringPair
+import pl.treksoft.kvision.snabbdom.obj
enum class DD(val POS: String) {
HEADER("DD#HEADER"),
@@ -45,6 +48,12 @@ open class DropDown(text: String, elements: List<StringPair>, icon: String? = nu
else -> Link(it.first, it.second)
}
}
+ button.setEventListener {
+ click = {
+ list.getElementJQueryD().dropdown("toggle")
+ }
+ }
+
list.addAll(children)
this.add(button)
this.add(list)
@@ -54,6 +63,29 @@ open class DropDown(text: String, elements: List<StringPair>, icon: String? = nu
companion object {
var counter = 0
}
+
+ override fun afterInsert(node: VNode) {
+ this.getElementJQuery()?.on("show.bs.dropdown", { e, _ ->
+ val event = CustomEvent("showBsDropdown", obj({ detail = button }))
+ this.getElement()?.dispatchEvent(event) as Any
+ })
+ this.getElementJQuery()?.on("shown.bs.dropdown", { e, _ ->
+ val event = CustomEvent("shownBsDropdown", obj({ detail = button }))
+ this.getElement()?.dispatchEvent(event) as Any
+ })
+ this.getElementJQuery()?.on("hide.bs.dropdown", { e, _ ->
+ val event = CustomEvent("hideBsDropdown", obj({ detail = button }))
+ this.getElement()?.dispatchEvent(event) as Any
+ })
+ this.getElementJQuery()?.on("hidden.bs.dropdown", { e, _ ->
+ val event = CustomEvent("hiddenBsDropdown", obj({ detail = button }))
+ this.getElement()?.dispatchEvent(event) as Any
+ })
+ }
+
+ open fun toggle() {
+ list.getElementJQueryD().dropdown("toggle")
+ }
}
open class DropDownButton(id: String, text: String, icon: String? = null, style: BUTTONSTYLE = BUTTONSTYLE.DEFAULT,
diff --git a/src/main/kotlin/pl/treksoft/kvision/snabbdom/Types.kt b/src/main/kotlin/pl/treksoft/kvision/snabbdom/Types.kt
index 3bf68003..8a292910 100644
--- a/src/main/kotlin/pl/treksoft/kvision/snabbdom/Types.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/snabbdom/Types.kt
@@ -2,11 +2,15 @@ package pl.treksoft.kvision.snabbdom
import com.github.snabbdom.Attrs
import com.github.snabbdom.Classes
+import com.github.snabbdom.Hooks
import com.github.snabbdom.On
import com.github.snabbdom.Props
import com.github.snabbdom.VNodeData
import com.github.snabbdom.VNodeStyle
+import org.w3c.dom.CustomEvent
+import org.w3c.dom.CustomEventInit
import pl.treksoft.kvision.core.Widget
+import pl.treksoft.kvision.html.Button
external class Object
@@ -17,7 +21,18 @@ fun obj(init: dynamic.() -> Unit): dynamic {
@Suppress("UnsafeCastFromDynamic")
private fun vNodeData(): VNodeData = js("({})")
-interface SnOn<T> : On {
+class DropDownEvent(type: String, eventInitDict: CustomEventInit) : CustomEvent(type, eventInitDict) {
+ override val detail: Button? = null
+}
+
+interface BtOn : On {
+ var showBsDropdown: ((DropDownEvent) -> kotlin.Unit)?
+ var shownBsDropdown: ((DropDownEvent) -> kotlin.Unit)?
+ var hideBsDropdown: ((DropDownEvent) -> kotlin.Unit)?
+ var hiddenBsDropdown: ((DropDownEvent) -> kotlin.Unit)?
+}
+
+interface SnOn<T> : BtOn {
var self: T
}
@@ -30,6 +45,11 @@ internal fun on(widget: Widget): SnOn<Widget> {
return obj
}
+@Suppress("UnsafeCastFromDynamic")
+internal fun hooks(): Hooks {
+ return js("({})")
+}
+
typealias StringPair = Pair<String, String>
typealias StringBoolPair = Pair<String, Boolean>
diff --git a/src/test/kotlin/test/pl/treksoft/kvision/core/WidgetSpec.kt b/src/test/kotlin/test/pl/treksoft/kvision/core/WidgetSpec.kt
index 183fa9fa..c68d5e7e 100644
--- a/src/test/kotlin/test/pl/treksoft/kvision/core/WidgetSpec.kt
+++ b/src/test/kotlin/test/pl/treksoft/kvision/core/WidgetSpec.kt
@@ -86,4 +86,21 @@ class WidgetSpec : WSpec {
}
}
+ @Test
+ fun getElement() {
+ runW { widget, element ->
+ val e = widget.getElement()
+ assertTrue("Should return correct dom element") { e == element }
+ }
+ }
+
+ @Test
+ fun getElementJQuery() {
+ runW { widget, element ->
+ val j = widget.getElementJQuery()
+ assertTrue("Should return correct jQuery object") { j != null }
+ val e = j?.get()?.get(0)
+ assertTrue("Should return correct dom element from jQuery object") { e == element }
+ }
+ }
} \ No newline at end of file
diff --git a/src/test/kotlin/test/pl/treksoft/kvision/dropdown/DropDownSpec.kt b/src/test/kotlin/test/pl/treksoft/kvision/dropdown/DropDownSpec.kt
index 23caf3a7..ec755fbf 100644
--- a/src/test/kotlin/test/pl/treksoft/kvision/dropdown/DropDownSpec.kt
+++ b/src/test/kotlin/test/pl/treksoft/kvision/dropdown/DropDownSpec.kt
@@ -7,6 +7,7 @@ import test.pl.treksoft.kvision.DomSpec
import kotlin.browser.document
import kotlin.test.Test
import kotlin.test.assertEquals
+import kotlin.test.assertTrue
class DropDownSpec : DomSpec {
@@ -65,4 +66,20 @@ class DropDownSpec : DomSpec {
}
}
+ @Test
+ fun toggle() {
+ run {
+ val root = Root("test")
+ val dd = DropDown("Dropdown", listOf("abc" to "#!/x", "def" to "#!/y"), "flag")
+ root.add(dd)
+ val classes = dd.getElementJQuery()?.attr("class")
+ assertTrue("Dropdown is hidden before toggle") { classes?.contains("open") == false }
+ dd.toggle()
+ val classes2 = dd.getElementJQuery()?.attr("class")
+ assertTrue("Dropdown is visible after toggle") { classes2?.contains("open") == true }
+ dd.toggle()
+ val classes3 = dd.getElementJQuery()?.attr("class")
+ assertTrue("Dropdown is hidden after second toggle") { classes3?.contains("open") == false }
+ }
+ }
} \ No newline at end of file