summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.gradle1
-rw-r--r--src/main/assets/css/style.css8
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/Showcase.kt37
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/core/KVManager.kt2
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/text/AbstractTextInput.kt20
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/text/RichText.kt19
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/text/RichTextInput.kt83
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/text/TextAreaInput.kt2
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/text/TextInput.kt2
-rw-r--r--src/test/kotlin/test/pl/treksoft/kvision/form/text/RichTextInputSpec.kt28
-rw-r--r--src/test/kotlin/test/pl/treksoft/kvision/form/text/RichTextSpec.kt31
11 files changed, 217 insertions, 16 deletions
diff --git a/build.gradle b/build.gradle
index 8e43c79b..aeab07b8 100644
--- a/build.gradle
+++ b/build.gradle
@@ -54,6 +54,7 @@ kotlinFrontend {
dependency("awesome-bootstrap-checkbox", "0.3.7")
dependency "bootstrap-select"
dependency "ajax-bootstrap-select"
+ dependency "trix"
dependency("snabbdom", "0.6.9")
dependency "snabbdom-virtualize"
dependency "navigo"
diff --git a/src/main/assets/css/style.css b/src/main/assets/css/style.css
index 61696cb2..fbb29c37 100644
--- a/src/main/assets/css/style.css
+++ b/src/main/assets/css/style.css
@@ -52,3 +52,11 @@
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAICAQAAADdTl4aAAAAIElEQVQoz2MwrTD9TxFsZ7jPcV+IIsjFQAUw6hFqegQA+xzRHT2p7pEAAAAASUVORK5CYII=') center center no-repeat #cecece;
cursor: row-resize;
}
+
+.trix-control {
+ overflow-y: auto;
+}
+
+trix-toolbar .trix-button-group {
+ margin-bottom: 3px;
+}
diff --git a/src/main/kotlin/pl/treksoft/kvision/Showcase.kt b/src/main/kotlin/pl/treksoft/kvision/Showcase.kt
index b6444720..084b60d6 100644
--- a/src/main/kotlin/pl/treksoft/kvision/Showcase.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/Showcase.kt
@@ -7,19 +7,20 @@ 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.check.CheckBox
import pl.treksoft.kvision.form.INPUTSIZE
-import pl.treksoft.kvision.form.text.TEXTINPUTTYPE
-import pl.treksoft.kvision.form.text.Text
-import pl.treksoft.kvision.form.text.TextArea
-import pl.treksoft.kvision.form.text.TextAreaInput
-import pl.treksoft.kvision.form.text.TextInput
+import pl.treksoft.kvision.form.check.CheckBox
import pl.treksoft.kvision.form.select.AjaxOptions
import pl.treksoft.kvision.form.select.SELECTWIDTHTYPE
import pl.treksoft.kvision.form.select.Select
import pl.treksoft.kvision.form.select.SelectInput
import pl.treksoft.kvision.form.select.SelectOptGroup
import pl.treksoft.kvision.form.select.SelectOption
+import pl.treksoft.kvision.form.text.RichText
+import pl.treksoft.kvision.form.text.TEXTINPUTTYPE
+import pl.treksoft.kvision.form.text.Text
+import pl.treksoft.kvision.form.text.TextArea
+import pl.treksoft.kvision.form.text.TextAreaInput
+import pl.treksoft.kvision.form.text.TextInput
import pl.treksoft.kvision.html.*
import pl.treksoft.kvision.html.TAG.DIV
import pl.treksoft.kvision.html.TAG.H1
@@ -217,6 +218,25 @@ class Showcase : ApplicationBase() {
}
root.add(mbuttons8)
+ val htmlArea = RichText("test<b>Boldzik</b>", "Pole html").apply {
+ size = INPUTSIZE.SMALL
+ placeholder = "Wprowadź rich text"
+ width = 50.perc()
+ inputHeight = 200.px()
+ }
+ root.add(htmlArea)
+ htmlArea.setEventListener<RichText> {
+ change = {
+ console.log(self.value)
+ }
+ }
+ val mbuttons9 = Button("Sprawdz html").setEventListener<Button> {
+ click = {
+ println(htmlArea.value)
+ }
+ }
+ root.add(mbuttons9)
+
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)
@@ -482,6 +502,11 @@ class Showcase : ApplicationBase() {
} else {
split.show()
}
+ if (htmlArea.visible) {
+ htmlArea.hide()
+ } else {
+ htmlArea.show()
+ }
}
}
root.add(button)
diff --git a/src/main/kotlin/pl/treksoft/kvision/core/KVManager.kt b/src/main/kotlin/pl/treksoft/kvision/core/KVManager.kt
index 541733b3..e3c34190 100644
--- a/src/main/kotlin/pl/treksoft/kvision/core/KVManager.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/core/KVManager.kt
@@ -27,6 +27,8 @@ object KVManager {
private val bootstrapSelectAjaxCss = require("ajax-bootstrap-select/dist/css/ajax-bootstrap-select.min.css")
private val bootstrapSelectAjax = require("ajax-bootstrap-select/dist/js/ajax-bootstrap-select.min.js")
private val bootstrapSelectAjaxI18n = require("./js/ajax-bootstrap-select.pl-PL.js")
+ private val trixCss = require("trix/dist/trix.css")
+ private val trix = require("trix")
private val sdPatch = Snabbdom.init(arrayOf(classModule, attributesModule, propsModule, styleModule,
eventListenersModule, datasetModule))
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 09d9ec50..a71a84a5 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/text/AbstractTextInput.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/text/AbstractTextInput.kt
@@ -7,17 +7,12 @@ import pl.treksoft.kvision.snabbdom.StringBoolPair
import pl.treksoft.kvision.snabbdom.StringPair
abstract class AbstractTextInput(value: String? = null,
- classes: Set<String> = setOf()) : Widget(classes + "form-control"), StringFormField {
+ classes: Set<String> = setOf()) : Widget(classes), StringFormField {
init {
this.setInternalEventListener<AbstractTextInput> {
input = {
- val v = getElementJQuery()?.`val`() as String?
- if (v != null && v.isNotEmpty()) {
- self.value = v
- } else {
- self.value = null
- }
+ self.changeValue()
}
}
}
@@ -105,9 +100,18 @@ abstract class AbstractTextInput(value: String? = null,
return sn
}
- private fun refreshState() {
+ protected open fun refreshState() {
value?.let {
getElementJQuery()?.`val`(it)
} ?: getElementJQueryD()?.`val`(null)
}
+
+ protected open fun changeValue() {
+ val v = getElementJQuery()?.`val`() as String?
+ if (v != null && v.isNotEmpty()) {
+ this.value = v
+ } else {
+ this.value = null
+ }
+ }
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/text/RichText.kt b/src/main/kotlin/pl/treksoft/kvision/form/text/RichText.kt
new file mode 100644
index 00000000..b963b4ea
--- /dev/null
+++ b/src/main/kotlin/pl/treksoft/kvision/form/text/RichText.kt
@@ -0,0 +1,19 @@
+package pl.treksoft.kvision.form.text
+
+open class RichText(value: String? = null,
+ label: String? = null, rich: Boolean = false) : AbstractText(label, rich) {
+
+ var inputHeight
+ get() = input.height
+ set(value) {
+ input.height = value
+ }
+
+ final override val input: RichTextInput = RichTextInput(value).apply { id = idc }
+
+ init {
+ @Suppress("LeakingThis")
+ input.eventTarget = this
+ this.addInternal(input)
+ }
+}
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/text/RichTextInput.kt b/src/main/kotlin/pl/treksoft/kvision/form/text/RichTextInput.kt
new file mode 100644
index 00000000..5f791c94
--- /dev/null
+++ b/src/main/kotlin/pl/treksoft/kvision/form/text/RichTextInput.kt
@@ -0,0 +1,83 @@
+package pl.treksoft.kvision.form.text
+
+import com.github.snabbdom.VNode
+import pl.treksoft.jquery.jQuery
+import pl.treksoft.kvision.snabbdom.StringPair
+import kotlin.browser.document
+
+open class RichTextInput(value: String? = null, classes: Set<String> = setOf()) :
+ AbstractTextInput(value, classes + "form-control" + "trix-control") {
+
+ private var trixId: String? = null
+
+ override fun render(): VNode {
+ return kvh("trix-editor")
+ }
+
+ override fun getSnAttrs(): List<StringPair> {
+ val sn = super.getSnAttrs().toMutableList()
+ placeholder?.let {
+ sn.add("placeholder" to it)
+ }
+ name?.let {
+ sn.add("name" to it)
+ }
+ autofocus?.let {
+ if (it) {
+ sn.add("autofocus" to "autofocus")
+ }
+ }
+ if (disabled) {
+ sn.add("disabled" to "true")
+ }
+ return sn
+ }
+
+ @Suppress("UnsafeCastFromDynamic")
+ override fun afterInsert(node: VNode) {
+ if (this.disabled || this.readonly == true) {
+ this.getElementJQuery()?.removeAttr("contenteditable")
+ } else {
+ this.getElementJQuery()?.on("trix-change", { _, _ ->
+ if (trixId != null) {
+ val v = document.getElementById("trix-input-" + trixId)?.let { jQuery(it).`val`() as String? }
+ value = if (v != null && v.isNotEmpty()) {
+ v
+ } else {
+ null
+ }
+ val event = org.w3c.dom.events.Event("change")
+ this.getElement()?.dispatchEvent(event)
+ }
+ })
+ }
+ this.getElementJQuery()?.on("trix-initialize", { _, _ ->
+ trixId = this.getElementJQuery()?.attr("trix-id")
+ value?.let {
+ this.getElement().asDynamic().editor.loadHTML(it)
+ }
+ })
+ this.getElementJQuery()?.on("trix-file-accept", { e, _ -> e.preventDefault() })
+ }
+
+ override fun afterDestroy() {
+ document.getElementById("trix-input-" + trixId)?.remove()
+ document.getElementById("trix-toolbar-" + trixId)?.remove()
+ trixId = null
+ }
+
+ @Suppress("UnsafeCastFromDynamic")
+ override fun refreshState() {
+ val v = document.getElementById("trix-input-" + trixId)?.let { jQuery(it).`val`() as String? }
+ if (value != v) {
+ val editor = this.getElement().asDynamic().editor
+ value?.let {
+ editor.loadHTML(it)
+ } ?: editor.loadHTML("")
+ }
+ }
+
+ override fun changeValue() {
+ // disabled parent class functionality
+ }
+}
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/text/TextAreaInput.kt b/src/main/kotlin/pl/treksoft/kvision/form/text/TextAreaInput.kt
index e8fd9a43..2b5ff31d 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/text/TextAreaInput.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/text/TextAreaInput.kt
@@ -4,7 +4,7 @@ import com.github.snabbdom.VNode
import pl.treksoft.kvision.snabbdom.StringPair
open class TextAreaInput(cols: Int? = null, rows: Int? = null, value: String? = null, classes: Set<String> = setOf()) :
- AbstractTextInput(value, classes) {
+ AbstractTextInput(value, classes + "form-control") {
var cols: Int? = cols
set(value) {
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/text/TextInput.kt b/src/main/kotlin/pl/treksoft/kvision/form/text/TextInput.kt
index 436c0fec..3cd86e04 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/text/TextInput.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/text/TextInput.kt
@@ -9,7 +9,7 @@ enum class TEXTINPUTTYPE(val type: String) {
}
open class TextInput(type: TEXTINPUTTYPE = TEXTINPUTTYPE.TEXT, value: String? = null, classes: Set<String> = setOf()) :
- AbstractTextInput(value, classes) {
+ AbstractTextInput(value, classes + "form-control") {
var type: TEXTINPUTTYPE = type
set(value) {
diff --git a/src/test/kotlin/test/pl/treksoft/kvision/form/text/RichTextInputSpec.kt b/src/test/kotlin/test/pl/treksoft/kvision/form/text/RichTextInputSpec.kt
new file mode 100644
index 00000000..c2a3a6ee
--- /dev/null
+++ b/src/test/kotlin/test/pl/treksoft/kvision/form/text/RichTextInputSpec.kt
@@ -0,0 +1,28 @@
+package test.pl.treksoft.kvision.form.text
+
+import pl.treksoft.jquery.jQuery
+import pl.treksoft.kvision.core.Root
+import pl.treksoft.kvision.form.text.RichTextInput
+import test.pl.treksoft.kvision.DomSpec
+import kotlin.browser.document
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+class RichTextInputSpec : DomSpec {
+
+ @Test
+ fun render() {
+ run {
+ val root = Root("test")
+ val hai = RichTextInput(value = "abc").apply {
+ placeholder = "place"
+ id = "idti"
+ }
+ root.add(hai)
+ val id = document.getElementById("test")?.let { jQuery(it).find("trix-editor").attr("trix-id") } ?: "0"
+ val content = document.getElementById("test")?.let { jQuery(it).find("trix-editor")[0]?.outerHTML }
+ assertEquals("<trix-editor contenteditable=\"\" class=\"form-control trix-control\" id=\"idti\" placeholder=\"place\" trix-id=\"$id\" input=\"trix-input-$id\" toolbar=\"trix-toolbar-$id\"></trix-editor>", content, "Should render correct html area field")
+ }
+ }
+
+} \ No newline at end of file
diff --git a/src/test/kotlin/test/pl/treksoft/kvision/form/text/RichTextSpec.kt b/src/test/kotlin/test/pl/treksoft/kvision/form/text/RichTextSpec.kt
new file mode 100644
index 00000000..24851007
--- /dev/null
+++ b/src/test/kotlin/test/pl/treksoft/kvision/form/text/RichTextSpec.kt
@@ -0,0 +1,31 @@
+package test.pl.treksoft.kvision.form.text
+
+import pl.treksoft.jquery.jQuery
+import pl.treksoft.kvision.core.Root
+import pl.treksoft.kvision.form.text.RichText
+import test.pl.treksoft.kvision.DomSpec
+import kotlin.browser.document
+import kotlin.test.Test
+import kotlin.test.assertEquals
+
+class RichTextSpec : DomSpec {
+
+ @Test
+ fun render() {
+ run {
+ val root = Root("test")
+ val hai = RichText(value = "abc", label = "Field").apply {
+ placeholder = "place"
+ id = "idti"
+ }
+ root.add(hai)
+ val id = document.getElementById("test")?.let { jQuery(it).find("trix-editor").attr("trix-id") } ?: "0"
+ val iid = hai.input.id
+ val content = document.getElementById("test")?.let { jQuery(it).find("trix-editor")[0]?.outerHTML }
+ assertEquals("<trix-editor contenteditable=\"\" class=\"form-control trix-control\" id=\"$iid\" placeholder=\"place\" trix-id=\"$id\" input=\"trix-input-$id\" toolbar=\"trix-toolbar-$id\"></trix-editor>", content, "Should render correct html area form field")
+ val label = document.getElementById("test")?.let { jQuery(it).find("label")[0]?.outerHTML }
+ assertEquals("<label for=\"$iid\">Field</label>", label, "Should render correct label for html area form field")
+ }
+ }
+
+} \ No newline at end of file