aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/pl/treksoft
diff options
context:
space:
mode:
authorRobert Jaros <rjaros@finn.pl>2018-03-26 09:34:38 +0200
committerRobert Jaros <rjaros@finn.pl>2018-03-26 09:41:24 +0200
commit6287ce18301d58792e803bc7daa7068c164e704d (patch)
treecf90971cb887e8f16317f5b795bd5825b3bde29e /src/main/kotlin/pl/treksoft
parent3b1eae9ed8b7e1d57f8f05968820c5eb4bbe8fe2 (diff)
downloadkvision-6287ce18301d58792e803bc7daa7068c164e704d.tar.gz
kvision-6287ce18301d58792e803bc7daa7068c164e704d.tar.bz2
kvision-6287ce18301d58792e803bc7daa7068c164e704d.zip
Plain HTML form attributes (method, action, enctype, target, ...) support.
Form controls refactoring.
Diffstat (limited to 'src/main/kotlin/pl/treksoft')
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/dropdown/DropDown.kt3
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/FormControl.kt35
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/FormPanel.kt90
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/check/CheckBox.kt33
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/check/CheckInput.kt9
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/check/Radio.kt21
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/check/RadioGroup.kt44
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/select/Select.kt30
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/select/SelectInput.kt9
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/spinner/Spinner.kt43
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/spinner/SpinnerInput.kt9
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/text/AbstractText.kt18
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/text/AbstractTextInput.kt9
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/text/Password.kt13
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/text/RichText.kt16
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/text/Text.kt12
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/text/TextArea.kt12
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/time/DateTime.kt30
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/time/DateTimeInput.kt9
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/html/Button.kt28
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/html/Tag.kt3
21 files changed, 289 insertions, 187 deletions
diff --git a/src/main/kotlin/pl/treksoft/kvision/dropdown/DropDown.kt b/src/main/kotlin/pl/treksoft/kvision/dropdown/DropDown.kt
index 0a61a814..70b63c9f 100644
--- a/src/main/kotlin/pl/treksoft/kvision/dropdown/DropDown.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/dropdown/DropDown.kt
@@ -30,6 +30,7 @@ import pl.treksoft.kvision.core.StringBoolPair
import pl.treksoft.kvision.core.StringPair
import pl.treksoft.kvision.html.Button
import pl.treksoft.kvision.html.ButtonStyle
+import pl.treksoft.kvision.html.ButtonType
import pl.treksoft.kvision.html.Link
import pl.treksoft.kvision.html.ListTag
import pl.treksoft.kvision.html.ListType
@@ -257,7 +258,7 @@ internal class DropDownButton(
id: String, text: String, icon: String? = null, style: ButtonStyle = ButtonStyle.DEFAULT,
disabled: Boolean = false, val forNavbar: Boolean = false, classes: Set<String> = setOf()
) :
- Button(text, icon, style, disabled, classes) {
+ Button(text, icon, style, ButtonType.BUTTON, disabled, classes) {
init {
this.id = id
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/FormControl.kt b/src/main/kotlin/pl/treksoft/kvision/form/FormControl.kt
index 41d964fd..091f4162 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/FormControl.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/FormControl.kt
@@ -32,6 +32,21 @@ enum class InputSize(val className: String) {
SMALL("input-sm")
}
+interface FormInput : Component {
+ /**
+ * Determines if the field is disabled.
+ */
+ var disabled: Boolean
+ /**
+ * Input control field size.
+ */
+ var size: InputSize?
+ /**
+ * The name attribute of the generated HTML input element.
+ */
+ var name: String?
+}
+
/**
* Base interface of a form control.
*/
@@ -40,14 +55,30 @@ interface FormControl : Component {
* Determines if the field is disabled.
*/
var disabled: Boolean
+ get() = input.disabled
+ set(value) {
+ input.disabled = value
+ }
/**
- * Input control size.
+ * Input control field size.
*/
var size: InputSize?
+ get() = input.size
+ set(value) {
+ input.size = value
+ }
+ /**
+ * The name attribute of the generated HTML input element.
+ */
+ var name: String?
+ get() = input.name
+ set(value) {
+ input.name = value
+ }
/**
* The actual input component.
*/
- val input: Component
+ val input: FormInput
/**
* Form field label.
*/
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/FormPanel.kt b/src/main/kotlin/pl/treksoft/kvision/form/FormPanel.kt
index 1be29f31..2a274684 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/FormPanel.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/FormPanel.kt
@@ -24,6 +24,7 @@ package pl.treksoft.kvision.form
import com.github.snabbdom.VNode
import pl.treksoft.kvision.core.Container
import pl.treksoft.kvision.core.StringBoolPair
+import pl.treksoft.kvision.core.StringPair
import pl.treksoft.kvision.form.check.CheckBox
import pl.treksoft.kvision.form.check.Radio
import pl.treksoft.kvision.html.TAG
@@ -42,20 +43,80 @@ enum class FormType(internal val formType: String) {
}
/**
+ * Form methods.
+ */
+enum class FormMethod(internal val method: String) {
+ GET("get"),
+ POST("post")
+}
+
+/**
+ * Form encoding types.
+ */
+enum class FormEnctype(internal val enctype: String) {
+ URLENCODED("application/x-www-form-urlencoded"),
+ MULTIPART("multipart/form-data"),
+ PLAIN("text/plain")
+}
+
+/**
+ * Form targets.
+ */
+enum class FormTarget(internal val target: String) {
+ BLANK("_blank"),
+ SELF("_self"),
+ PARENT("_parent"),
+ TOP("_top")
+}
+
+/**
* Bootstrap form component.
*
* @constructor
* @param K model class type
+ * @param method HTTP method
+ * @param action the URL address to send data
+ * @param enctype form encoding type
* @param type form layout
* @param classes set of CSS class names
* @param modelFactory function transforming a Map<String, Any?> to a data model of class K
*/
open class FormPanel<K>(
+ method: FormMethod? = null, action: String? = null, enctype: FormEnctype? = null,
private val type: FormType? = null, classes: Set<String> = setOf(),
modelFactory: (Map<String, Any?>) -> K
) : SimplePanel(classes) {
/**
+ * HTTP method.
+ */
+ var method by refreshOnUpdate(method)
+ /**
+ * The URL address to send data.
+ */
+ var action by refreshOnUpdate(action)
+ /**
+ * The form encoding type.
+ */
+ var enctype by refreshOnUpdate(enctype)
+ /**
+ * The form name.
+ */
+ var name: String? by refreshOnUpdate()
+ /**
+ * The form target.
+ */
+ var target: FormTarget? by refreshOnUpdate()
+ /**
+ * Determines if the form is not validated.
+ */
+ var novalidate: Boolean? by refreshOnUpdate()
+ /**
+ * Determines if the form should have autocomplete.
+ */
+ var autocomplete: Boolean? by refreshOnUpdate()
+
+ /**
* Function returning validation message.
*/
var validatorMessage
@@ -111,6 +172,32 @@ open class FormPanel<K>(
return cl
}
+ override fun getSnAttrs(): List<StringPair> {
+ val sn = super.getSnAttrs().toMutableList()
+ method?.let {
+ sn.add("method" to it.method)
+ }
+ action?.let {
+ sn.add("action" to it)
+ }
+ enctype?.let {
+ sn.add("enctype" to it.enctype)
+ }
+ name?.let {
+ sn.add("name" to it)
+ }
+ target?.let {
+ sn.add("target" to it.target)
+ }
+ if (autocomplete == false) {
+ sn.add("autocomplete" to "off")
+ }
+ if (novalidate == true) {
+ sn.add("novalidate" to "novalidate")
+ }
+ return sn
+ }
+
protected fun <C : FormControl> addInternal(
key: KProperty1<K, *>, control: C, required: Boolean = false,
validatorMessage: ((C) -> String?)? = null,
@@ -284,10 +371,11 @@ open class FormPanel<K>(
* It takes the same parameters as the constructor of the built component.
*/
fun <K> Container.formPanel(
+ method: FormMethod? = null, action: String? = null, enctype: FormEnctype? = null,
type: FormType? = null, classes: Set<String> = setOf(),
modelFactory: (Map<String, Any?>) -> K
): FormPanel<K> {
- val panel = FormPanel(type, classes, modelFactory)
+ val panel = FormPanel(method, action, enctype, type, classes, modelFactory)
this.add(panel)
return panel
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/check/CheckBox.kt b/src/main/kotlin/pl/treksoft/kvision/form/check/CheckBox.kt
index 58033d3a..3afca46e 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/check/CheckBox.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/check/CheckBox.kt
@@ -48,11 +48,12 @@ enum class CheckBoxStyle(internal val className: String) {
*
* @constructor
* @param value selection state
+ * @param name the name of the input element
* @param label label text bound to the input element
* @param rich determines if [label] can contain HTML code
*/
open class CheckBox(
- value: Boolean = false, label: String? = null,
+ value: Boolean = false, name: String? = null, label: String? = null,
rich: Boolean = false
) : SimplePanel(setOf("checkbox")), BoolFormControl {
@@ -76,19 +77,6 @@ open class CheckBox(
input.startValue = value
}
/**
- * The name attribute of the generated HTML input element.
- */
- var name
- get() = input.name
- set(value) {
- input.name = value
- }
- override var disabled
- get() = input.disabled
- set(value) {
- input.disabled = value
- }
- /**
* The label text bound to the input element.
*/
var label
@@ -116,20 +104,15 @@ open class CheckBox(
* Determines if the checkbox is rendered inline.
*/
var inline by refreshOnUpdate(false)
- /**
- * The size of the input.
- */
- override var size
- get() = input.size
- set(value) {
- input.size = value
- }
private val idc = "kv_form_checkbox_$counter"
final override val input: CheckInput = CheckInput(
CheckInputType.CHECKBOX, value,
setOf("styled")
- ).apply { id = idc }
+ ).apply {
+ this.id = idc
+ this.name = name
+ }
final override val flabel: FieldLabel = FieldLabel(idc, label, rich, classes = setOf())
final override val validationInfo: HelpBlock = HelpBlock().apply { visible = false }
@@ -204,10 +187,10 @@ open class CheckBox(
* It takes the same parameters as the constructor of the built component.
*/
fun Container.checkBox(
- value: Boolean = false, label: String? = null,
+ value: Boolean = false, name: String? = null, label: String? = null,
rich: Boolean = false, init: (CheckBox.() -> Unit)? = null
): CheckBox {
- val checkBox = CheckBox(value, label, rich).apply { init?.invoke(this) }
+ val checkBox = CheckBox(value, name, label, rich).apply { init?.invoke(this) }
this.add(checkBox)
return checkBox
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/check/CheckInput.kt b/src/main/kotlin/pl/treksoft/kvision/form/check/CheckInput.kt
index 0ed85e44..f79c1b48 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/check/CheckInput.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/check/CheckInput.kt
@@ -27,6 +27,7 @@ import pl.treksoft.kvision.core.Container
import pl.treksoft.kvision.core.StringBoolPair
import pl.treksoft.kvision.core.StringPair
import pl.treksoft.kvision.core.Widget
+import pl.treksoft.kvision.form.FormInput
import pl.treksoft.kvision.form.InputSize
/**
@@ -48,7 +49,7 @@ enum class CheckInputType(internal val type: String) {
open class CheckInput(
type: CheckInputType = CheckInputType.CHECKBOX, value: Boolean = false,
classes: Set<String> = setOf()
-) : Widget(classes) {
+) : Widget(classes), FormInput {
init {
this.setInternalEventListener<CheckInput> {
@@ -81,11 +82,11 @@ open class CheckInput(
/**
* The name attribute of the generated HTML input element.
*/
- var name: String? by refreshOnUpdate()
+ override var name: String? by refreshOnUpdate()
/**
* Determines if the field is disabled.
*/
- var disabled by refreshOnUpdate(false)
+ override var disabled by refreshOnUpdate(false)
/**
* The additional String value used for the radio button group.
*/
@@ -93,7 +94,7 @@ open class CheckInput(
/**
* The size of the input.
*/
- var size: InputSize? by refreshOnUpdate()
+ override var size: InputSize? by refreshOnUpdate()
override fun render(): VNode {
return render("input")
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/check/Radio.kt b/src/main/kotlin/pl/treksoft/kvision/form/check/Radio.kt
index 6e26fa5b..181d9665 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/check/Radio.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/check/Radio.kt
@@ -86,19 +86,6 @@ open class Radio(
input.extraValue = value
}
/**
- * The name attribute of the generated HTML input element.
- */
- var name
- get() = input.name
- set(value) {
- input.name = value
- }
- override var disabled
- get() = input.disabled
- set(value) {
- input.disabled = value
- }
- /**
* The label text bound to the input element.
*/
var label
@@ -126,14 +113,6 @@ open class Radio(
* Determines if the radio button is rendered inline.
*/
var inline by refreshOnUpdate(false)
- /**
- * The size of the input.
- */
- override var size
- get() = input.size
- set(value) {
- input.size = value
- }
private val idc = "kv_form_radio_$counter"
final override val input: CheckInput = CheckInput(CheckInputType.RADIO, value).apply {
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/check/RadioGroup.kt b/src/main/kotlin/pl/treksoft/kvision/form/check/RadioGroup.kt
index 84e3d89f..8900437b 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/check/RadioGroup.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/check/RadioGroup.kt
@@ -24,7 +24,6 @@ package pl.treksoft.kvision.form.check
import pl.treksoft.kvision.core.Container
import pl.treksoft.kvision.core.StringBoolPair
import pl.treksoft.kvision.core.StringPair
-import pl.treksoft.kvision.core.Widget
import pl.treksoft.kvision.form.FieldLabel
import pl.treksoft.kvision.form.HelpBlock
import pl.treksoft.kvision.form.InputSize
@@ -41,12 +40,13 @@ import pl.treksoft.kvision.panel.SimplePanel
* @constructor
* @param options an optional list of options (label to value pairs) for the group
* @param value selected option
+ * @param name the name attribute of the generated HTML input element
* @param inline determines if the options are rendered inline
* @param label label text of the options group
* @param rich determines if [label] can contain HTML code
*/
open class RadioGroup(
- options: List<StringPair>? = null, value: String? = null, inline: Boolean = false,
+ options: List<StringPair>? = null, value: String? = null, name: String? = null, inline: Boolean = false,
label: String? = null,
rich: Boolean = false
) : SimplePanel(setOf("form-group")), StringFormControl {
@@ -87,16 +87,26 @@ open class RadioGroup(
set(value) {
flabel.rich = value
}
- override var size: InputSize? = null
+ override var name
+ get() = getNameFromChildren()
+ set(value) {
+ setNameToChildren(value)
+ }
+ override var size
+ get() = getSizeFromChildren()
+ set(value) {
+ setSizeToChildren(value)
+ }
private val idc = "kv_form_radiogroup_" + Select.counter
- final override val input = Widget()
+ final override val input = CheckInput()
final override val flabel: FieldLabel = FieldLabel(idc, label, rich)
final override val validationInfo: HelpBlock = HelpBlock().apply { visible = false }
init {
setChildrenFromOptions()
setValueToChildren(value)
+ setNameToChildren(name)
counter++
}
@@ -129,16 +139,34 @@ open class RadioGroup(
getChildren().filterIsInstance<Radio>().forEach { it.disabled = disabled }
}
+ private fun getNameFromChildren(): String? {
+ return getChildren().filterIsInstance<Radio>().firstOrNull()?.name ?: this.idc
+ }
+
+ private fun setNameToChildren(name: String?) {
+ val tname = name ?: this.idc
+ getChildren().filterIsInstance<Radio>().forEach { it.name = tname }
+ }
+
+ private fun getSizeFromChildren(): InputSize? {
+ return getChildren().filterIsInstance<Radio>().firstOrNull()?.size
+ }
+
+ private fun setSizeToChildren(size: InputSize?) {
+ getChildren().filterIsInstance<Radio>().forEach { it.size = size }
+ }
+
private fun setChildrenFromOptions() {
+ val currentName = this.name
super.removeAll()
this.addInternal(flabel)
options?.let {
- val tidc = this.idc
+ val tname = currentName ?: this.idc
val tinline = this.inline
val c = it.map {
Radio(false, extraValue = it.first, label = it.second).apply {
inline = tinline
- name = tidc
+ name = tname
eventTarget = this@RadioGroup
setEventListener<Radio> {
change = {
@@ -169,10 +197,10 @@ open class RadioGroup(
* It takes the same parameters as the constructor of the built component.
*/
fun Container.radioGroup(
- options: List<StringPair>? = null, value: String? = null, inline: Boolean = false,
+ options: List<StringPair>? = null, value: String? = null, name: String? = null, inline: Boolean = false,
label: String? = null, rich: Boolean = false, init: (RadioGroup.() -> Unit)? = null
): RadioGroup {
- val radioGroup = RadioGroup(options, value, inline, label, rich).apply { init?.invoke(this) }
+ val radioGroup = RadioGroup(options, value, name, inline, label, rich).apply { init?.invoke(this) }
this.add(radioGroup)
return radioGroup
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/select/Select.kt b/src/main/kotlin/pl/treksoft/kvision/form/select/Select.kt
index 0c9cdb2e..f19081e1 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/select/Select.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/select/Select.kt
@@ -41,6 +41,7 @@ import pl.treksoft.kvision.utils.SnOn
* @constructor
* @param options an optional list of options (label to value pairs) for the select control
* @param value selected value
+ * @param name the name attribute of the generated HTML input element
* @param multiple allows multiple value selection (multiple values are comma delimited)
* @param ajaxOptions additional options for remote (AJAX) data source
* @param label label text bound to the input element
@@ -48,7 +49,7 @@ import pl.treksoft.kvision.utils.SnOn
*/
@Suppress("TooManyFunctions")
open class Select(
- options: List<StringPair>? = null, value: String? = null,
+ options: List<StringPair>? = null, value: String? = null, name: String? = null,
multiple: Boolean = false, ajaxOptions: AjaxOptions? = null, label: String? = null,
rich: Boolean = false
) : SimplePanel(setOf("form-group")), StringFormControl {
@@ -70,14 +71,6 @@ open class Select(
input.value = value
}
/**
- * The name attribute of the generated HTML select element.
- */
- var name
- get() = input.name
- set(value) {
- input.name = value
- }
- /**
* Determines if multiple value selection is allowed.
*/
var multiple
@@ -149,11 +142,6 @@ open class Select(
set(value) {
input.emptyOption = value
}
- override var disabled
- get() = input.disabled
- set(value) {
- input.disabled = value
- }
/**
* Determines if the select is automatically focused.
*/
@@ -178,17 +166,15 @@ open class Select(
set(value) {
flabel.rich = value
}
- override var size
- get() = input.size
- set(value) {
- input.size = value
- }
private val idc = "kv_form_select_$counter"
final override val input: SelectInput = SelectInput(
options, value, multiple, ajaxOptions,
setOf("form-control")
- ).apply { id = idc }
+ ).apply {
+ this.id = idc
+ this.name = name
+ }
final override val flabel: FieldLabel = FieldLabel(idc, label, rich)
final override val validationInfo: HelpBlock = HelpBlock().apply { visible = false }
@@ -287,11 +273,11 @@ open class Select(
* It takes the same parameters as the constructor of the built component.
*/
fun Container.select(
- options: List<StringPair>? = null, value: String? = null,
+ options: List<StringPair>? = null, value: String? = null, name: String? = null,
multiple: Boolean = false, ajaxOptions: AjaxOptions? = null, label: String? = null,
rich: Boolean = false, init: (Select.() -> Unit)? = null
): Select {
- val select = Select(options, value, multiple, ajaxOptions, label, rich).apply { init?.invoke(this) }
+ val select = Select(options, value, name, multiple, ajaxOptions, label, rich).apply { init?.invoke(this) }
this.add(select)
return select
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/select/SelectInput.kt b/src/main/kotlin/pl/treksoft/kvision/form/select/SelectInput.kt
index 87580139..97f3989c 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/select/SelectInput.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/select/SelectInput.kt
@@ -28,6 +28,7 @@ import pl.treksoft.kvision.core.Container
import pl.treksoft.kvision.core.CssSize
import pl.treksoft.kvision.core.StringBoolPair
import pl.treksoft.kvision.core.StringPair
+import pl.treksoft.kvision.form.FormInput
import pl.treksoft.kvision.form.InputSize
import pl.treksoft.kvision.html.ButtonStyle
import pl.treksoft.kvision.panel.SimplePanel
@@ -60,7 +61,7 @@ open class SelectInput(
options: List<StringPair>? = null, value: String? = null,
multiple: Boolean = false, ajaxOptions: AjaxOptions? = null,
classes: Set<String> = setOf()
-) : SimplePanel(classes) {
+) : SimplePanel(classes), FormInput {
/**
* A list of options (label to value pairs) for the select control.
@@ -73,7 +74,7 @@ open class SelectInput(
/**
* The name attribute of the generated HTML select element.
*/
- var name: String? by refreshOnUpdate()
+ override var name: String? by refreshOnUpdate()
/**
* Determines if multiple value selection is allowed.
*/
@@ -118,7 +119,7 @@ open class SelectInput(
/**
* Determines if the field is disabled.
*/
- var disabled by refreshOnUpdate(false)
+ override var disabled by refreshOnUpdate(false)
/**
* Determines if the select is automatically focused.
*/
@@ -126,7 +127,7 @@ open class SelectInput(
/**
* The size of the input.
*/
- var size: InputSize? by refreshOnUpdate()
+ override var size: InputSize? by refreshOnUpdate()
init {
setChildrenFromOptions()
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/spinner/Spinner.kt b/src/main/kotlin/pl/treksoft/kvision/form/spinner/Spinner.kt
index 9d72f36b..4fa68e47 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/spinner/Spinner.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/spinner/Spinner.kt
@@ -35,6 +35,7 @@ import pl.treksoft.kvision.utils.SnOn
*
* @constructor
* @param value spinner value
+ * @param name the name attribute of the generated HTML input element
* @param min minimal value (default 0)
* @param max maximal value (default 100)
* @param step step value (default 1)
@@ -45,7 +46,7 @@ import pl.treksoft.kvision.utils.SnOn
* @param rich determines if [label] can contain HTML code
*/
open class Spinner(
- value: Number? = null, min: Int = 0, max: Int = DEFAULT_MAX, step: Double = DEFAULT_STEP,
+ value: Number? = null, name: String? = null, min: Int = 0, max: Int = DEFAULT_MAX, step: Double = DEFAULT_STEP,
decimals: Int = 0, buttonsType: ButtonsType = ButtonsType.VERTICAL,
forceType: ForceType = ForceType.NONE, label: String? = null,
rich: Boolean = false
@@ -127,19 +128,6 @@ open class Spinner(
input.placeholder = value
}
/**
- * The name attribute of the generated HTML input element.
- */
- var name
- get() = input.name
- set(value) {
- input.name = value
- }
- override var disabled
- get() = input.disabled
- set(value) {
- input.disabled = value
- }
- /**
* Determines if the spinner is automatically focused.
*/
var autofocus
@@ -171,15 +159,13 @@ open class Spinner(
set(value) {
flabel.rich = value
}
- override var size
- get() = input.size
- set(value) {
- input.size = value
- }
protected val idc = "kv_form_spinner_$counter"
final override val input: SpinnerInput = SpinnerInput(value, min, max, step, decimals, buttonsType, forceType)
- .apply { id = idc }
+ .apply {
+ this.id = idc
+ this.name = name
+ }
final override val flabel: FieldLabel = FieldLabel(idc, label, rich)
final override val validationInfo: HelpBlock = HelpBlock().apply { visible = false }
@@ -253,12 +239,19 @@ open class Spinner(
* It takes the same parameters as the constructor of the built component.
*/
fun Container.spinner(
- value: Number? = null, min: Int = 0, max: Int = DEFAULT_MAX, step: Double = DEFAULT_STEP,
- decimals: Int = 0, buttonsType: ButtonsType = ButtonsType.VERTICAL,
- forceType: ForceType = ForceType.NONE, label: String? = null,
- rich: Boolean = false, init: (Spinner.() -> Unit)? = null
+ value: Number? = null,
+ name: String? = null,
+ min: Int = 0,
+ max: Int = DEFAULT_MAX,
+ step: Double = DEFAULT_STEP,
+ decimals: Int = 0,
+ buttonsType: ButtonsType = ButtonsType.VERTICAL,
+ forceType: ForceType = ForceType.NONE,
+ label: String? = null,
+ rich: Boolean = false,
+ init: (Spinner.() -> Unit)? = null
): Spinner {
- val spinner = Spinner(value, min, max, step, decimals, buttonsType, forceType, label, rich).apply {
+ val spinner = Spinner(value, name, min, max, step, decimals, buttonsType, forceType, label, rich).apply {
init?.invoke(
this
)
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/spinner/SpinnerInput.kt b/src/main/kotlin/pl/treksoft/kvision/form/spinner/SpinnerInput.kt
index b9903ff8..e318db35 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/spinner/SpinnerInput.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/spinner/SpinnerInput.kt
@@ -27,6 +27,7 @@ import pl.treksoft.kvision.core.Container
import pl.treksoft.kvision.core.StringBoolPair
import pl.treksoft.kvision.core.StringPair
import pl.treksoft.kvision.core.Widget
+import pl.treksoft.kvision.form.FormInput
import pl.treksoft.kvision.form.InputSize
import pl.treksoft.kvision.utils.obj
@@ -71,7 +72,7 @@ open class SpinnerInput(
decimals: Int = 0, buttonsType: ButtonsType = ButtonsType.VERTICAL,
forceType: ForceType = ForceType.NONE,
classes: Set<String> = setOf()
-) : Widget(classes + "form-control") {
+) : Widget(classes + "form-control"), FormInput {
init {
this.addSurroundingCssClass("input-group")
@@ -136,11 +137,11 @@ open class SpinnerInput(
/**
* The name attribute of the generated HTML input element.
*/
- var name: String? by refreshOnUpdate()
+ override var name: String? by refreshOnUpdate()
/**
* Determines if the field is disabled.
*/
- var disabled by refreshOnUpdate(false)
+ override var disabled by refreshOnUpdate(false)
/**
* Determines if the spinner is automatically focused.
*/
@@ -152,7 +153,7 @@ open class SpinnerInput(
/**
* The size of the input.
*/
- var size: InputSize? by refreshOnUpdate()
+ override var size: InputSize? by refreshOnUpdate()
private var siblings: JQuery? = null
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/text/AbstractText.kt b/src/main/kotlin/pl/treksoft/kvision/form/text/AbstractText.kt
index 3c62d4a8..7c23615a 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/text/AbstractText.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/text/AbstractText.kt
@@ -67,14 +67,6 @@ abstract class AbstractText(label: String? = null, rich: Boolean = false) :
input.placeholder = value
}
/**
- * The name attribute of the generated HTML input element.
- */
- var name
- get() = input.name
- set(value) {
- input.name = value
- }
- /**
* Maximal length of the text input value.
*/
var maxlength
@@ -82,11 +74,6 @@ abstract class AbstractText(label: String? = null, rich: Boolean = false) :
set(value) {
input.maxlength = value
}
- override var disabled
- get() = input.disabled
- set(value) {
- input.disabled = value
- }
/**
* Determines if the text input is automatically focused.
*/
@@ -119,11 +106,6 @@ abstract class AbstractText(label: String? = null, rich: Boolean = false) :
set(value) {
flabel.rich = value
}
- override var size
- get() = input.size
- set(value) {
- input.size = value
- }
/**
* @suppress
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/text/AbstractTextInput.kt b/src/main/kotlin/pl/treksoft/kvision/form/text/AbstractTextInput.kt
index 5f4a243d..52cc7792 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/text/AbstractTextInput.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/text/AbstractTextInput.kt
@@ -25,6 +25,7 @@ import com.github.snabbdom.VNode
import pl.treksoft.kvision.core.StringBoolPair
import pl.treksoft.kvision.core.StringPair
import pl.treksoft.kvision.core.Widget
+import pl.treksoft.kvision.form.FormInput
import pl.treksoft.kvision.form.InputSize
/**
@@ -37,7 +38,7 @@ import pl.treksoft.kvision.form.InputSize
abstract class AbstractTextInput(
value: String? = null,
classes: Set<String> = setOf()
-) : Widget(classes) {
+) : Widget(classes), FormInput {
init {
this.setInternalEventListener<AbstractTextInput> {
@@ -65,7 +66,7 @@ abstract class AbstractTextInput(
/**
* The name attribute of the generated HTML input element.
*/
- var name: String? by refreshOnUpdate()
+ override var name: String? by refreshOnUpdate()
/**
* Maximal length of the text input value.
*/
@@ -73,7 +74,7 @@ abstract class AbstractTextInput(
/**
* Determines if the field is disabled.
*/
- var disabled by refreshOnUpdate(false)
+ override var disabled by refreshOnUpdate(false)
/**
* Determines if the text input is automatically focused.
*/
@@ -85,7 +86,7 @@ abstract class AbstractTextInput(
/**
* The size of the input.
*/
- var size: InputSize? by refreshOnUpdate()
+ override var size: InputSize? by refreshOnUpdate()
override fun getSnClass(): List<StringBoolPair> {
val cl = super.getSnClass().toMutableList()
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/text/Password.kt b/src/main/kotlin/pl/treksoft/kvision/form/text/Password.kt
index 995243c9..1d36516e 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/text/Password.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/text/Password.kt
@@ -28,12 +28,13 @@ import pl.treksoft.kvision.core.Container
*
* @constructor
* @param value text input value
+ * @param name the name attribute of the generated HTML input element
* @param label label text bound to the input element
* @param rich determines if [label] can contain HTML code
*/
-open class Password(value: String? = null, label: String? = null, rich: Boolean = false) : Text(
+open class Password(value: String? = null, name: String? = null, label: String? = null, rich: Boolean = false) : Text(
TextInputType.PASSWORD,
- value, label, rich
+ value, name, label, rich
) {
companion object {
/**
@@ -42,9 +43,13 @@ open class Password(value: String? = null, label: String? = null, rich: Boolean
* It takes the same parameters as the constructor of the built component.
*/
fun Container.password(
- value: String? = null, label: String? = null, rich: Boolean = false, init: (Password.() -> Unit)? = null
+ value: String? = null,
+ name: String? = null,
+ label: String? = null,
+ rich: Boolean = false,
+ init: (Password.() -> Unit)? = null
): Password {
- val password = Password(value, label, rich).apply { init?.invoke(this) }
+ val password = Password(value, name, label, rich).apply { init?.invoke(this) }
this.add(password)
return password
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/text/RichText.kt b/src/main/kotlin/pl/treksoft/kvision/form/text/RichText.kt
index 953fec90..22126797 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/text/RichText.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/text/RichText.kt
@@ -28,11 +28,12 @@ import pl.treksoft.kvision.core.Container
*
* @constructor
* @param value text input value
+ * @param name the name attribute of the generated HTML input element
* @param label label text bound to the input element
* @param rich determines if [label] can contain HTML code
*/
open class RichText(
- value: String? = null,
+ value: String? = null, name: String? = null,
label: String? = null, rich: Boolean = false
) : AbstractText(label, rich) {
@@ -45,7 +46,10 @@ open class RichText(
input.height = value
}
- final override val input: RichTextInput = RichTextInput(value).apply { id = idc }
+ final override val input: RichTextInput = RichTextInput(value).apply {
+ this.id = idc
+ this.name = name
+ }
init {
@Suppress("LeakingThis")
@@ -61,9 +65,13 @@ open class RichText(
* It takes the same parameters as the constructor of the built component.
*/
fun Container.richText(
- value: String? = null, label: String? = null, rich: Boolean = false, init: (RichText.() -> Unit)? = null
+ value: String? = null,
+ name: String? = null,
+ label: String? = null,
+ rich: Boolean = false,
+ init: (RichText.() -> Unit)? = null
): RichText {
- val richText = RichText(value, label, rich).apply { init?.invoke(this) }
+ val richText = RichText(value, name, label, rich).apply { init?.invoke(this) }
this.add(richText)
return richText
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/text/Text.kt b/src/main/kotlin/pl/treksoft/kvision/form/text/Text.kt
index fd53adff..7e4127f5 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/text/Text.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/text/Text.kt
@@ -29,11 +29,12 @@ import pl.treksoft.kvision.core.Container
* @constructor
* @param type text input type (default "text")
* @param value text input value
+ * @param name the name attribute of the generated HTML input element
* @param label label text bound to the input element
* @param rich determines if [label] can contain HTML code
*/
open class Text(
- type: TextInputType = TextInputType.TEXT, value: String? = null,
+ type: TextInputType = TextInputType.TEXT, value: String? = null, name: String? = null,
label: String? = null, rich: Boolean = false
) : AbstractText(label, rich) {
@@ -54,7 +55,10 @@ open class Text(
input.autocomplete = value
}
- final override val input: TextInput = TextInput(type, value).apply { id = idc }
+ final override val input: TextInput = TextInput(type, value).apply {
+ this.id = idc
+ this.name = name
+ }
init {
@Suppress("LeakingThis")
@@ -70,10 +74,10 @@ open class Text(
* It takes the same parameters as the constructor of the built component.
*/
fun Container.text(
- type: TextInputType = TextInputType.TEXT, value: String? = null,
+ type: TextInputType = TextInputType.TEXT, value: String? = null, name: String? = null,
label: String? = null, rich: Boolean = false, init: (Text.() -> Unit)? = null
): Text {
- val text = Text(type, value, label, rich).apply { init?.invoke(this) }
+ val text = Text(type, value, name, label, rich).apply { init?.invoke(this) }
this.add(text)
return text
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/text/TextArea.kt b/src/main/kotlin/pl/treksoft/kvision/form/text/TextArea.kt
index 58f63028..d5058583 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/text/TextArea.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/text/TextArea.kt
@@ -30,11 +30,12 @@ import pl.treksoft.kvision.core.Container
* @param cols number of columns
* @param rows number of rows
* @param value text input value
+ * @param name the name attribute of the generated HTML input element
* @param label label text bound to the input element
* @param rich determines if [label] can contain HTML code
*/
open class TextArea(
- cols: Int? = null, rows: Int? = null, value: String? = null,
+ cols: Int? = null, rows: Int? = null, value: String? = null, name: String? = null,
label: String? = null, rich: Boolean = false
) : AbstractText(label, rich) {
@@ -63,7 +64,10 @@ open class TextArea(
input.wrapHard = value
}
- final override val input: TextAreaInput = TextAreaInput(cols, rows, value).apply { id = idc }
+ final override val input: TextAreaInput = TextAreaInput(cols, rows, value).apply {
+ this.id = idc
+ this.name = name
+ }
init {
@Suppress("LeakingThis")
@@ -79,10 +83,10 @@ open class TextArea(
* It takes the same parameters as the constructor of the built component.
*/
fun Container.textArea(
- cols: Int? = null, rows: Int? = null, value: String? = null,
+ cols: Int? = null, rows: Int? = null, value: String? = null, name: String? = null,
label: String? = null, rich: Boolean = false, init: (TextArea.() -> Unit)? = null
): TextArea {
- val textArea = TextArea(cols, rows, value, label, rich).apply { init?.invoke(this) }
+ val textArea = TextArea(cols, rows, value, name, label, rich).apply { init?.invoke(this) }
this.add(textArea)
return textArea
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/time/DateTime.kt b/src/main/kotlin/pl/treksoft/kvision/form/time/DateTime.kt
index ecf930e2..3d32fd8c 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/time/DateTime.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/time/DateTime.kt
@@ -36,12 +36,13 @@ import kotlin.js.Date
*
* @constructor
* @param value date/time input value
+ * @param name the name attribute of the generated HTML input element
* @param format date/time format (default YYYY-MM-DD HH:mm)
* @param label label text bound to the input element
* @param rich determines if [label] can contain HTML code
*/
open class DateTime(
- value: Date? = null, format: String = "YYYY-MM-DD HH:mm", label: String? = null,
+ value: Date? = null, name: String? = null, format: String = "YYYY-MM-DD HH:mm", label: String? = null,
rich: Boolean = false
) : SimplePanel(setOf("form-group")), DateFormControl {
@@ -70,19 +71,6 @@ open class DateTime(
input.placeholder = value
}
/**
- * The name attribute of the generated HTML input element.
- */
- var name
- get() = input.name
- set(value) {
- input.name = value
- }
- override var disabled
- get() = input.disabled
- set(value) {
- input.disabled = value
- }
- /**
* Determines if the date/time input is automatically focused.
*/
var autofocus
@@ -170,14 +158,12 @@ open class DateTime(
set(value) {
flabel.rich = value
}
- override var size
- get() = input.size
- set(value) {
- input.size = value
- }
private val idc = "kv_form_time_$counter"
- final override val input: DateTimeInput = DateTimeInput(value, format).apply { id = idc }
+ final override val input: DateTimeInput = DateTimeInput(value, format).apply {
+ this.id = idc
+ this.name = name
+ }
final override val flabel: FieldLabel = FieldLabel(idc, label, rich)
final override val validationInfo: HelpBlock = HelpBlock().apply { visible = false }
@@ -249,10 +235,10 @@ open class DateTime(
* It takes the same parameters as the constructor of the built component.
*/
fun Container.dateTime(
- value: Date? = null, format: String = "YYYY-MM-DD HH:mm", label: String? = null,
+ value: Date? = null, name: String? = null, format: String = "YYYY-MM-DD HH:mm", label: String? = null,
rich: Boolean = false, init: (DateTime.() -> Unit)? = null
): DateTime {
- val dateTime = DateTime(value, format, label, rich).apply { init?.invoke(this) }
+ val dateTime = DateTime(value, name, format, label, rich).apply { init?.invoke(this) }
this.add(dateTime)
return dateTime
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/time/DateTimeInput.kt b/src/main/kotlin/pl/treksoft/kvision/form/time/DateTimeInput.kt
index d935487b..86e9c7ba 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/time/DateTimeInput.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/time/DateTimeInput.kt
@@ -26,6 +26,7 @@ import pl.treksoft.kvision.core.Container
import pl.treksoft.kvision.core.StringBoolPair
import pl.treksoft.kvision.core.StringPair
import pl.treksoft.kvision.core.Widget
+import pl.treksoft.kvision.form.FormInput
import pl.treksoft.kvision.form.InputSize
import pl.treksoft.kvision.utils.obj
import pl.treksoft.kvision.utils.toDateF
@@ -47,7 +48,7 @@ internal const val MAX_VIEW = 4
open class DateTimeInput(
value: Date? = null, format: String = "YYYY-MM-DD HH:mm",
classes: Set<String> = setOf()
-) : Widget(classes + "form-control") {
+) : Widget(classes + "form-control"), FormInput {
init {
this.setInternalEventListener<DateTimeInput> {
@@ -72,11 +73,11 @@ open class DateTimeInput(
/**
* The name attribute of the generated HTML input element.
*/
- var name: String? by refreshOnUpdate()
+ override var name: String? by refreshOnUpdate()
/**
* Determines if the field is disabled.
*/
- var disabled by refreshOnUpdate(false)
+ override var disabled by refreshOnUpdate(false)
/**
* Determines if the text input is automatically focused.
*/
@@ -88,7 +89,7 @@ open class DateTimeInput(
/**
* The size of the input.
*/
- var size: InputSize? by refreshOnUpdate()
+ override var size: InputSize? by refreshOnUpdate()
/**
* Day of the week start. 0 (Sunday) to 6 (Saturday).
*/
diff --git a/src/main/kotlin/pl/treksoft/kvision/html/Button.kt b/src/main/kotlin/pl/treksoft/kvision/html/Button.kt
index 84f7c309..99f4ca13 100644
--- a/src/main/kotlin/pl/treksoft/kvision/html/Button.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/html/Button.kt
@@ -52,6 +52,15 @@ enum class ButtonSize(internal val className: String) {
}
/**
+ * Button types.
+ */
+enum class ButtonType(internal val buttonType: String) {
+ BUTTON("button"),
+ SUBMIT("submit"),
+ RESET("reset")
+}
+
+/**
* Button component.
*
* @constructor
@@ -62,7 +71,7 @@ enum class ButtonSize(internal val className: String) {
* @param classes a set of CSS class names
*/
open class Button(
- text: String, icon: String? = null, style: ButtonStyle = ButtonStyle.DEFAULT,
+ text: String, icon: String? = null, style: ButtonStyle = ButtonStyle.DEFAULT, type: ButtonType = ButtonType.BUTTON,
disabled: Boolean = false, classes: Set<String> = setOf()
) : Widget(classes) {
@@ -79,6 +88,10 @@ open class Button(
*/
var style by refreshOnUpdate(style)
/**
+ * Button types.
+ */
+ var type by refreshOnUpdate(type)
+ /**
* Determines if button is disabled.
*/
var disabled by refreshOnUpdate(disabled)
@@ -117,7 +130,7 @@ open class Button(
}
override fun getSnAttrs(): List<StringPair> {
- return super.getSnAttrs() + ("type" to "button")
+ return super.getSnAttrs() + ("type" to type.buttonType)
}
/**
@@ -139,10 +152,15 @@ open class Button(
* It takes the same parameters as the constructor of the built component.
*/
fun Container.button(
- text: String, icon: String? = null, style: ButtonStyle = ButtonStyle.DEFAULT,
- disabled: Boolean = false, classes: Set<String> = setOf(), init: (Button.() -> Unit)? = null
+ text: String,
+ icon: String? = null,
+ style: ButtonStyle = ButtonStyle.DEFAULT,
+ type: ButtonType = ButtonType.BUTTON,
+ disabled: Boolean = false,
+ classes: Set<String> = setOf(),
+ init: (Button.() -> Unit)? = null
): Button {
- val button = Button(text, icon, style, disabled, classes).apply { init?.invoke(this) }
+ val button = Button(text, icon, style, type, disabled, classes).apply { init?.invoke(this) }
this.add(button)
return button
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/html/Tag.kt b/src/main/kotlin/pl/treksoft/kvision/html/Tag.kt
index 936d7b89..75536b88 100644
--- a/src/main/kotlin/pl/treksoft/kvision/html/Tag.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/html/Tag.kt
@@ -76,7 +76,8 @@ enum class TAG(internal val tagName: String) {
TR("tr"),
TD("td"),
- FORM("form")
+ FORM("form"),
+ INPUT("input")
}
/**