diff options
author | Robert Jaros <rjaros@finn.pl> | 2018-03-22 20:23:54 +0100 |
---|---|---|
committer | Robert Jaros <rjaros@finn.pl> | 2018-03-22 20:23:54 +0100 |
commit | 7081cfaed23fe8b34bfdf15918775a846d7649e0 (patch) | |
tree | 15458e3d7fb2cc0ebf32281362ba44f82d27fa0b /src/main/kotlin/pl/treksoft/kvision/dropdown | |
parent | 6ba1eefc59a2940a7258655da4e88b4118e61746 (diff) | |
download | kvision-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')
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 + } + } +} |