diff options
author | Robert Jaros <rjaros@finn.pl> | 2017-11-03 15:16:42 +0100 |
---|---|---|
committer | Robert Jaros <rjaros@finn.pl> | 2017-11-03 15:16:42 +0100 |
commit | b9a849b4ebf397b04b4b3c405de325b740b958aa (patch) | |
tree | 0be1b01f68064e0f62f295573acaf3579b3d7d82 /src/main | |
parent | d4d9ea0afaf76778f3bb588e501749867053ca5f (diff) | |
download | kvision-b9a849b4ebf397b04b4b3c405de325b740b958aa.tar.gz kvision-b9a849b4ebf397b04b4b3c405de325b740b958aa.tar.bz2 kvision-b9a849b4ebf397b04b4b3c405de325b740b958aa.zip |
Select input components
Diffstat (limited to 'src/main')
5 files changed, 402 insertions, 23 deletions
diff --git a/src/main/assets/js/bootstrap-select-i18n.min.js b/src/main/assets/js/bootstrap-select-i18n.min.js new file mode 100644 index 00000000..4428d3c0 --- /dev/null +++ b/src/main/assets/js/bootstrap-select-i18n.min.js @@ -0,0 +1 @@ +!function(a,b){"function"==typeof define&&define.amd?define(["jquery"],function(a){return b(a)}):"object"==typeof module&&module.exports?module.exports=b(require("jquery")):b(a.jQuery)}(this,function(a){!function(a){a.fn.selectpicker.defaults={noneSelectedText:"",noneResultsText:"",countSelectedText:function(a,b){return 1==a?"... ({n})":"... ({n})"},maxOptionsText:function(a,b){return[1==a?"🛇":"🛇",1==b?"🛇":"🛇"]},selectAllText:"++",deselectAllText:"--",multipleSeparator:", "}}(a)});
\ No newline at end of file diff --git a/src/main/kotlin/pl/treksoft/kvision/Showcase.kt b/src/main/kotlin/pl/treksoft/kvision/Showcase.kt index 282ea510..8821e94b 100644 --- a/src/main/kotlin/pl/treksoft/kvision/Showcase.kt +++ b/src/main/kotlin/pl/treksoft/kvision/Showcase.kt @@ -2,26 +2,12 @@ package pl.treksoft.kvision import com.lightningkite.kotlin.observable.list.observableListOf import pl.treksoft.kvision.basic.Label -import pl.treksoft.kvision.core.BGATTACH -import pl.treksoft.kvision.core.BGREPEAT -import pl.treksoft.kvision.core.BGSIZE -import pl.treksoft.kvision.core.BORDERSTYLE -import pl.treksoft.kvision.core.Background -import pl.treksoft.kvision.core.Border -import pl.treksoft.kvision.core.COLOR -import pl.treksoft.kvision.core.Img -import pl.treksoft.kvision.core.Root +import pl.treksoft.kvision.core.* import pl.treksoft.kvision.data.DataComponent import pl.treksoft.kvision.data.DataContainer import pl.treksoft.kvision.dropdown.DD.* import pl.treksoft.kvision.dropdown.DropDown -import pl.treksoft.kvision.form.CheckBox -import pl.treksoft.kvision.form.INPUTSIZE -import pl.treksoft.kvision.form.TEXTINPUTTYPE -import pl.treksoft.kvision.form.Text -import pl.treksoft.kvision.form.TextArea -import pl.treksoft.kvision.form.TextAreaInput -import pl.treksoft.kvision.form.TextInput +import pl.treksoft.kvision.form.* import pl.treksoft.kvision.html.* import pl.treksoft.kvision.html.TAG.DIV import pl.treksoft.kvision.html.TAG.H1 @@ -73,7 +59,7 @@ class Showcase : ApplicationBase() { } } root.add(mbutton2) - val textField = TextInput(placeholder = "Wprowadź hasło ...", value = "abc") + val textField = TextInput(value = "abc").apply { placeholder = "Wprowadź hasło ..." } val mbutton3 = Button("Ukryj/Pokaż").setEventListener<Button> { click = { if (datac.visible) datac.hide() else datac.show() @@ -82,6 +68,45 @@ class Showcase : ApplicationBase() { } root.add(mbutton3) + val select = SelectInput(listOf("klucz1" to "Klucz 1", "klucz2" to "Klucz 2"), "klucz2,klucz1", multiple = true) + root.add(select) + + val mbuttons = Button("Select").setEventListener<Button> { + click = { + println(select.value) + } + } + root.add(mbuttons) + + val select2 = SelectInput(value = "klucz1") + select2.add(SelectOption("klucz0", "Klucz 0", "Subtext 0", "flag")) + select2.add(SelectOption(divider = true)) + select2.add(SelectOption("klucz1", "Klucz 1", "Subtext 1", "fa-flag")) + select2.add(SelectOption("klucz2", "Klucz 2", disabled = true)) + root.add(select2) + + val select3 = SelectInput().apply { + placeholder = "Wybierz opcje" + emptyOption = true + liveSearch = true + style = BUTTONSTYLE.WARNING + selectWidthType = SELECTWIDTHTYPE.FIT + } + select3.add(SelectOptGroup("Opcje pierwsze", listOf("k" to "Opcja pierwsza 1", "m" to "Opcja pierwsza 2"))) + val sopt = SelectOptGroup("Opcje drugie", maxOptions = 2) + sopt.add(SelectOption("a", "Opcja druga 1", "Subtext 1")) + sopt.add(SelectOption("b", "Opcja druga 2")) + sopt.add(SelectOption("c", "Opcja druga 3").apply { color = Color(COLOR.RED) }) + select3.add(sopt) + root.add(select3) + + val mbuttons3 = Button("Select").setEventListener<Button> { + click = { + println(select3.value) + } + } + root.add(mbuttons3) + val container = SimplePanel(setOf("abc", "def")) val h1 = Tag(H1, "To jest <i>test pisania</i> tekstu", false, null, classes = setOf("test", "test2")) container.add(h1) @@ -109,7 +134,7 @@ class Showcase : ApplicationBase() { val passwordField = TextInput(TEXTINPUTTYPE.PASSWORD) root.add(passwordField) - val textField2 = TextInput(placeholder = "Disabled") + val textField2 = TextInput().apply { placeholder = "Disabled" } textField2.disabled = true textField2.size = INPUTSIZE.LARGE root.add(textField2) @@ -140,13 +165,20 @@ class Showcase : ApplicationBase() { change = { e -> println("rchange" + self.value) } }*/ - val text = Text(placeholder = "Pole formularza", maxlength = 5, label = "To jest pole") + val text = Text(label = "To jest pole").apply { + placeholder = "Pole formularza" + maxlength = 5 + } root.add(text) - val textareainput = TextAreaInput(cols = 5, rows = 2, placeholder = "...", value = "To jest tekst\nTo jest <b>te</b></textarea>kst2") + val textareainput = TextAreaInput(cols = 5, rows = 2, value = "To jest tekst\nTo jest <b>te</b></textarea>kst2").apply { + placeholder = "..." + } root.add(textareainput) - val textarea = TextArea(cols = 5, rows = 2, placeholder = "...", value = "To jest tekst\nTo jest <b>te</b></textarea>kst2", label = "Pole długie") + val textarea = TextArea(cols = 5, rows = 2, value = "To jest tekst\nTo jest <b>te</b></textarea>kst2", label = "Pole długie").apply { + placeholder = "..." + } root.add(textarea) textarea.setEventListener<TextArea> { input = { e -> @@ -171,13 +203,21 @@ class Showcase : ApplicationBase() { val dd2 = DropDown("Dropdown2", listOf("abc" to "#!/abc", "def" to "#!/def", "xyz" to DISABLED.type, "Header" to HEADER.type, "Separtatorek" to SEPARATOR.type - ), "flag", dropup = true) + ), "flag").apply { dropup = true } root.add(dd2) dd2.setEventListener<DropDown> { hideBsDropdown = { e -> println("hide" + e.detail) } hiddenBsDropdown = { e -> println("hidden" + e.detail) } } + val ddbutton = Button("Toggle").setEventListener<Button> { + click = { + console.log("x") + dd2.toggle() + } + } + root.add(ddbutton) + val dd3 = DropDown("Dropdown3", icon = "file") dd3.add(Tag(TAG.H4, "ABC")) dd3.add(Button("To jest button")) @@ -362,7 +402,7 @@ class Showcase : ApplicationBase() { } } root.add(button2) - val button3 = Button("To jest przycisk IMG", image = Img("kotlin.png")) + val button3 = Button("To jest przycisk IMG").apply { image = Img("kotlin.png") } button3.setEventListener { click = { e -> Confirm.show("Pytanie", "Czy na pewno chcesz kliknąć przycisk?", noCallback = { println("no") }) { diff --git a/src/main/kotlin/pl/treksoft/kvision/form/SelectInput.kt b/src/main/kotlin/pl/treksoft/kvision/form/SelectInput.kt new file mode 100644 index 00000000..61c0240c --- /dev/null +++ b/src/main/kotlin/pl/treksoft/kvision/form/SelectInput.kt @@ -0,0 +1,203 @@ +package pl.treksoft.kvision.form + +import com.github.snabbdom.VNode +import pl.treksoft.kvision.core.CssSize +import pl.treksoft.kvision.html.BUTTONSTYLE +import pl.treksoft.kvision.panel.SimplePanel +import pl.treksoft.kvision.snabbdom.StringBoolPair +import pl.treksoft.kvision.snabbdom.StringPair + +private val _aKVNULL = "#kvnull" + +enum class SELECTWIDTHTYPE(val value: String) { + AUTO("auto"), + FIT("fit") +} + +class SelectInput(options: List<StringPair>? = null, override var value: String? = null, + multiple: Boolean = false, classes: Set<String> = setOf()) : SimplePanel(classes), StringFormField { + + private var options = options + set(value) { + field = value + setChildrenFromOptions() + } + + @Suppress("LeakingThis") + var startValue: String? = value + set(value) { + field = value + this.value = value + refresh() + } + var name: String? = null + set(value) { + field = value + refresh() + } + var multiple: Boolean = multiple + set(value) { + field = value + refresh() + } + var maxOptions: Int? = null + set(value) { + field = value + refresh() + } + var liveSearch: Boolean = false + set(value) { + field = value + refresh() + } + var placeholder: String? = null + set(value) { + field = value + refresh() + } + var style: BUTTONSTYLE? = null + set(value) { + field = value + refresh() + } + var selectWidth: CssSize? = null + set(value) { + field = value + refresh() + } + var selectWidthType: SELECTWIDTHTYPE? = null + set(value) { + field = value + refresh() + } + var emptyOption: Boolean = false + set(value) { + field = value + setChildrenFromOptions() + } + override var disabled: Boolean = false + set(value) { + field = value + refresh() + } + var autofocus: Boolean? = null + set(value) { + field = value + refresh() + } + override var size: INPUTSIZE? = null + set(value) { + field = value + refresh() + } + + init { + setChildrenFromOptions() + this.setInternalEventListener<SelectInput> { + change = { + val v = getElementJQuery()?.`val`() + self.value = v?.let { + if (self.multiple) { + @Suppress("UNCHECKED_CAST") + val arr = it as? Array<String> + if (arr != null && arr.isNotEmpty()) { + arr.joinToString() + } else { + null + } + } else { + val vs = it as String + if (_aKVNULL == vs) { + null + } else { + vs + } + } + } + } + } + } + + override fun render(): VNode { + return kvh("select", childrenVNodes()) + } + + private fun setChildrenFromOptions() { + this.removeAll() + if (emptyOption) { + this.add(SelectOption(_aKVNULL, "")) + } + options?.let { + val c = it.map { + SelectOption(it.first, it.second) + } + this.addAll(c) + } + } + + override fun getSnClass(): List<StringBoolPair> { + val cl = super.getSnClass().toMutableList() + cl.add("selectpicker" to true) + size?.let { + cl.add(it.className to true) + } + return cl + } + + override fun getSnAttrs(): List<StringPair> { + val sn = super.getSnAttrs().toMutableList() + name?.let { + sn.add("name" to it) + } + if (multiple) { + sn.add("multiple" to "true") + } + maxOptions?.let { + sn.add("data-max-options" to "" + it) + } + if (liveSearch) { + sn.add("data-live-search" to "true") + } + placeholder?.let { + sn.add("title" to it) + } + autofocus?.let { + if (it) { + sn.add("autofocus" to "autofocus") + } + } + if (disabled) { + sn.add("disabled" to "true") + } + val btnStyle = style?.className ?: "btn-default" + when (size) { + INPUTSIZE.LARGE -> { + sn.add("data-style" to "$btnStyle btn-lg") + } + INPUTSIZE.SMALL -> { + sn.add("data-style" to "$btnStyle btn-sm") + } + else -> { + sn.add("data-style" to btnStyle) + } + } + selectWidthType?.let { + sn.add("data-width" to it.value) + } ?: selectWidth?.let { + sn.add("data-width" to it.first.toString() + it.second.unit) + } + return sn + } + + @Suppress("UnsafeCastFromDynamic") + override fun afterInsert(node: VNode) { + getElementJQueryD()?.selectpicker("render") + value?.let { + if (multiple) { + getElementJQueryD()?.selectpicker("val", it.split(",").toTypedArray()) + } else { + getElementJQueryD()?.selectpicker("val", it) + } + } + } +} diff --git a/src/main/kotlin/pl/treksoft/kvision/form/SelectOptGroup.kt b/src/main/kotlin/pl/treksoft/kvision/form/SelectOptGroup.kt new file mode 100644 index 00000000..22483777 --- /dev/null +++ b/src/main/kotlin/pl/treksoft/kvision/form/SelectOptGroup.kt @@ -0,0 +1,60 @@ +package pl.treksoft.kvision.form + +import com.github.snabbdom.VNode +import pl.treksoft.kvision.panel.SimplePanel +import pl.treksoft.kvision.snabbdom.StringPair + +class SelectOptGroup(label: String, options: List<StringPair>? = null, maxOptions: Int? = null, + disabled: Boolean = false, classes: Set<String> = setOf()) : SimplePanel(classes) { + + var label: String = label + set(value) { + field = value + refresh() + } + private var options = options + set(value) { + field = value + setChildrenFromOptions() + } + var maxOptions: Int? = maxOptions + set(value) { + field = value + refresh() + } + var disabled: Boolean = disabled + set(value) { + field = value + refresh() + } + + init { + setChildrenFromOptions() + } + + override fun render(): VNode { + return kvh("optgroup", childrenVNodes()) + } + + private fun setChildrenFromOptions() { + this.removeAll() + options?.let { + val c = it.map { + SelectOption(it.first, it.second) + } + this.addAll(c) + } + } + + override fun getSnAttrs(): List<StringPair> { + val sn = super.getSnAttrs().toMutableList() + sn.add("label" to label) + maxOptions?.let { + sn.add("data-max-options" to "" + it) + } + if (disabled) { + sn.add("disabled" to "true") + } + return sn + } +}
\ No newline at end of file diff --git a/src/main/kotlin/pl/treksoft/kvision/form/SelectOption.kt b/src/main/kotlin/pl/treksoft/kvision/form/SelectOption.kt new file mode 100644 index 00000000..48412e17 --- /dev/null +++ b/src/main/kotlin/pl/treksoft/kvision/form/SelectOption.kt @@ -0,0 +1,75 @@ +package pl.treksoft.kvision.form + +import com.github.snabbdom.VNode +import pl.treksoft.kvision.core.Widget +import pl.treksoft.kvision.snabbdom.StringPair + +open class SelectOption(value: String? = null, label: String? = null, subtext: String? = null, icon: String? = null, + divider: Boolean = false, disabled: Boolean = false, + classes: Set<String> = setOf()) : Widget(classes) { + + var value: String? = value + set(value) { + field = value + refresh() + } + + var label: String? = label + set(value) { + field = value + refresh() + } + + var subtext: String? = subtext + set(value) { + field = value + refresh() + } + + var icon: String? = icon + set(value) { + field = value + refresh() + } + + var divider: Boolean = divider + set(value) { + field = value + refresh() + } + + var disabled: Boolean = disabled + set(value) { + field = value + refresh() + } + + override fun render(): VNode { + return kvh("option", arrayOf(label ?: value)) + } + + override fun getSnAttrs(): List<StringPair> { + val sn = super.getSnAttrs().toMutableList() + value?.let { + sn.add("value" to it) + } + if (!divider) { + subtext?.let { + sn.add("data-subtext" to it) + } + icon?.let { + if (it.startsWith("fa-")) { + sn.add("data-icon" to "fa $it") + } else { + sn.add("data-icon" to "glyphicon-$it") + } + } + if (disabled) { + sn.add("disabled" to "true") + } + } else { + sn.add("data-divider" to "true") + } + return sn + } +} |