aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/pl/treksoft/kvision/dropdown
diff options
context:
space:
mode:
authorRobert Jaros <rjaros@finn.pl>2018-03-22 20:23:54 +0100
committerRobert Jaros <rjaros@finn.pl>2018-03-22 20:23:54 +0100
commit7081cfaed23fe8b34bfdf15918775a846d7649e0 (patch)
tree15458e3d7fb2cc0ebf32281362ba44f82d27fa0b /src/main/kotlin/pl/treksoft/kvision/dropdown
parent6ba1eefc59a2940a7258655da4e88b4118e61746 (diff)
downloadkvision-7081cfaed23fe8b34bfdf15918775a846d7649e0.tar.gz
kvision-7081cfaed23fe8b34bfdf15918775a846d7649e0.tar.bz2
kvision-7081cfaed23fe8b34bfdf15918775a846d7649e0.zip
Context menu component based on Bootstrap dropdown.
Diffstat (limited to 'src/main/kotlin/pl/treksoft/kvision/dropdown')
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/dropdown/ContextMenu.kt66
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/dropdown/DropDown.kt20
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/dropdown/Header.kt44
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/dropdown/Separator.kt48
4 files changed, 169 insertions, 9 deletions
diff --git a/src/main/kotlin/pl/treksoft/kvision/dropdown/ContextMenu.kt b/src/main/kotlin/pl/treksoft/kvision/dropdown/ContextMenu.kt
new file mode 100644
index 00000000..ed788ab7
--- /dev/null
+++ b/src/main/kotlin/pl/treksoft/kvision/dropdown/ContextMenu.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018. Robert Jaros
+ */
+package pl.treksoft.kvision.dropdown
+
+import org.w3c.dom.events.MouseEvent
+import pl.treksoft.kvision.core.Display
+import pl.treksoft.kvision.core.Widget
+import pl.treksoft.kvision.html.ListTag
+import pl.treksoft.kvision.html.ListType
+import pl.treksoft.kvision.panel.Root
+import pl.treksoft.kvision.utils.px
+
+/**
+ * Context menu component.
+ *
+ * @constructor
+ * @param classes a set of CSS class names
+ */
+open class ContextMenu(
+ classes: Set<String> = setOf(), init: (ContextMenu.() -> Unit)? = null
+) : ListTag(ListType.UL, classes = classes + "dropdown-menu") {
+
+ init {
+ @Suppress("LeakingThis")
+ hide()
+ @Suppress("LeakingThis")
+ display = Display.BLOCK
+ val root = Root.getLastRoot()
+ if (root != null) {
+ @Suppress("LeakingThis")
+ root.addContextMenu(this)
+ } else {
+ println("At least one Root object is required to create a context menu!")
+ }
+ @Suppress("LeakingThis")
+ init?.invoke(this)
+ }
+
+ /**
+ * Positions and shows a context menu based on a mouse event.
+ * @param mouseEvent mouse event
+ * @return current context menu
+ */
+ open fun positionMenu(mouseEvent: MouseEvent): ContextMenu {
+ this.top = mouseEvent.pageY.toInt().px
+ this.left = mouseEvent.pageX.toInt().px
+ this.show()
+ return this
+ }
+
+ companion object {
+ /**
+ * DSL builder extension function.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+ fun Widget.contextMenu(
+ classes: Set<String> = setOf(), init: (ContextMenu.() -> Unit)? = null
+ ): ContextMenu {
+ val contextMenu = ContextMenu(classes).apply { init?.invoke(this) }
+ this.setContextMenu(contextMenu)
+ return contextMenu
+ }
+ }
+}
diff --git a/src/main/kotlin/pl/treksoft/kvision/dropdown/DropDown.kt b/src/main/kotlin/pl/treksoft/kvision/dropdown/DropDown.kt
index 9a349707..4622ceca 100644
--- a/src/main/kotlin/pl/treksoft/kvision/dropdown/DropDown.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/dropdown/DropDown.kt
@@ -186,15 +186,11 @@ open class DropDown(
elements?.let { elems ->
val c = elems.map {
when (it.second) {
- DD.HEADER.option -> Tag(TAG.LI, it.first, classes = setOf("dropdown-header"))
- DD.SEPARATOR.option -> {
- val tag = Tag(TAG.LI, it.first, classes = setOf("divider"))
- tag.role = "separator"
- tag
- }
+ DD.HEADER.option -> Header(it.first)
+ DD.SEPARATOR.option -> Separator()
DD.DISABLED.option -> {
val tag = Tag(TAG.LI, classes = setOf("disabled"))
- tag.add(Link(it.first, "#"))
+ tag.add(Link(it.first, "javascript:void(0)"))
tag
}
else -> Link(it.first, it.second)
@@ -246,10 +242,11 @@ open class DropDown(
*/
fun Container.dropDown(
text: String, elements: List<StringPair>? = null, icon: String? = null,
- style: ButtonStyle = ButtonStyle.DEFAULT, disabled: Boolean = false, navbar: Boolean = false,
+ style: ButtonStyle = ButtonStyle.DEFAULT, disabled: Boolean = false, forNavbar: Boolean = false,
classes: Set<String> = setOf(), init: (DropDown.() -> Unit)? = null
): DropDown {
- val dropDown = DropDown(text, elements, icon, style, disabled, navbar, classes).apply { init?.invoke(this) }
+ val dropDown =
+ DropDown(text, elements, icon, style, disabled, forNavbar, classes).apply { init?.invoke(this) }
this.add(dropDown)
return dropDown
}
@@ -264,6 +261,11 @@ internal class DropDownButton(
init {
this.id = id
+ setInternalEventListener<DropDownButton> {
+ click = { e ->
+ if (parent?.parent is ContextMenu) e.asDynamic().dropDownCM = true
+ }
+ }
}
override fun render(): VNode {
diff --git a/src/main/kotlin/pl/treksoft/kvision/dropdown/Header.kt b/src/main/kotlin/pl/treksoft/kvision/dropdown/Header.kt
new file mode 100644
index 00000000..e09d0246
--- /dev/null
+++ b/src/main/kotlin/pl/treksoft/kvision/dropdown/Header.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2018. Robert Jaros
+ */
+package pl.treksoft.kvision.dropdown
+
+import pl.treksoft.kvision.html.ListTag
+import pl.treksoft.kvision.html.TAG
+import pl.treksoft.kvision.html.Tag
+
+/**
+ * Menu header component.
+ *
+ * @constructor
+ * @param content header content text
+ * @param classes a set of CSS class names
+ */
+open class Header(content: String? = null, classes: Set<String> = setOf()) :
+ Tag(TAG.LI, content, classes = classes + "dropdown-header") {
+
+
+ companion object {
+ /**
+ * DSL builder extension function.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+ fun ListTag.header(content: String? = null, classes: Set<String> = setOf()): Header {
+ val header = Header(content, classes)
+ this.add(header)
+ return header
+ }
+
+ /**
+ * DSL builder extension function.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+ fun DropDown.header(content: String? = null, classes: Set<String> = setOf()): Header {
+ val header = Header(content, classes)
+ this.add(header)
+ return header
+ }
+ }
+}
diff --git a/src/main/kotlin/pl/treksoft/kvision/dropdown/Separator.kt b/src/main/kotlin/pl/treksoft/kvision/dropdown/Separator.kt
new file mode 100644
index 00000000..e786b47a
--- /dev/null
+++ b/src/main/kotlin/pl/treksoft/kvision/dropdown/Separator.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2018. Robert Jaros
+ */
+package pl.treksoft.kvision.dropdown
+
+import pl.treksoft.kvision.core.StringPair
+import pl.treksoft.kvision.html.ListTag
+import pl.treksoft.kvision.html.TAG
+import pl.treksoft.kvision.html.Tag
+
+/**
+ * Menu separator component.
+ *
+ * @constructor
+ * @param classes a set of CSS class names
+ */
+open class Separator(classes: Set<String> = setOf()) : Tag(TAG.LI, classes = classes + "divider") {
+
+ override fun getSnAttrs(): List<StringPair> {
+ val pr = super.getSnAttrs().toMutableList()
+ pr.add("role" to "separator")
+ return pr
+ }
+
+ companion object {
+ /**
+ * DSL builder extension function.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+ fun ListTag.separator(classes: Set<String> = setOf()): Separator {
+ val separator = Separator(classes)
+ this.add(separator)
+ return separator
+ }
+
+ /**
+ * DSL builder extension function.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+ fun DropDown.separator(classes: Set<String> = setOf()): Separator {
+ val separator = Separator(classes)
+ this.add(separator)
+ return separator
+ }
+ }
+}