aboutsummaryrefslogtreecommitdiff
path: root/kvision-modules/kvision-richtext/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'kvision-modules/kvision-richtext/src/main')
-rw-r--r--kvision-modules/kvision-richtext/src/main/kotlin/pl/treksoft/kvision/KVManagerRichText.kt64
-rw-r--r--kvision-modules/kvision-richtext/src/main/kotlin/pl/treksoft/kvision/form/text/RichText.kt79
-rw-r--r--kvision-modules/kvision-richtext/src/main/kotlin/pl/treksoft/kvision/form/text/RichTextInput.kt133
-rw-r--r--kvision-modules/kvision-richtext/src/main/resources/js/locales/trix/trix.pl.js28
4 files changed, 304 insertions, 0 deletions
diff --git a/kvision-modules/kvision-richtext/src/main/kotlin/pl/treksoft/kvision/KVManagerRichText.kt b/kvision-modules/kvision-richtext/src/main/kotlin/pl/treksoft/kvision/KVManagerRichText.kt
new file mode 100644
index 00000000..1ccd7a85
--- /dev/null
+++ b/kvision-modules/kvision-richtext/src/main/kotlin/pl/treksoft/kvision/KVManagerRichText.kt
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2017-present Robert Jaros
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package pl.treksoft.kvision
+
+import pl.treksoft.kvision.i18n.I18n
+import pl.treksoft.kvision.utils.obj
+import kotlin.browser.window
+
+internal val KVManagerRichTextInit = KVManagerRichText.init()
+
+/**
+ * Internal singleton object which initializes and configures KVision RichText module.
+ */
+@Suppress("EmptyCatchBlock", "TooGenericExceptionCaught")
+internal object KVManagerRichText {
+ fun init() {}
+
+ private val trixCss = try {
+ require("trix/dist/trix.css")
+ } catch (e: Throwable) {
+ }
+ private val trix = try {
+ val trix = require("trix")
+ window.asDynamic().Trix = trix
+ trix.config.languages = obj {}
+ trix.config.languages["en"] = obj {}
+ for (key in js("Object").keys(trix.config.lang)) {
+ trix.config.languages["en"][key] = trix.config.lang[key]
+ }
+ val orig = trix.config.toolbar.getDefaultHTML
+ trix.config.toolbar.getDefaultHTML = {
+ val config = if (trix.config.languages[I18n.language] != undefined) {
+ trix.config.languages[I18n.language]
+ } else {
+ trix.config.languages["en"]
+ }
+ for (key in js("Object").keys(trix.config.lang)) {
+ trix.config.lang[key] = config[key]
+ }
+ orig()
+ }
+ require("./js/locales/trix/trix.pl.js")
+ } catch (e: Throwable) {
+ }
+}
diff --git a/kvision-modules/kvision-richtext/src/main/kotlin/pl/treksoft/kvision/form/text/RichText.kt b/kvision-modules/kvision-richtext/src/main/kotlin/pl/treksoft/kvision/form/text/RichText.kt
new file mode 100644
index 00000000..22126797
--- /dev/null
+++ b/kvision-modules/kvision-richtext/src/main/kotlin/pl/treksoft/kvision/form/text/RichText.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2017-present Robert Jaros
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package pl.treksoft.kvision.form.text
+
+import pl.treksoft.kvision.core.Container
+
+/**
+ * Form field rich text component.
+ *
+ * @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, name: String? = null,
+ label: String? = null, rich: Boolean = false
+) : AbstractText(label, rich) {
+
+ /**
+ * Rich input control height.
+ */
+ var inputHeight
+ get() = input.height
+ set(value) {
+ input.height = value
+ }
+
+ final override val input: RichTextInput = RichTextInput(value).apply {
+ this.id = idc
+ this.name = name
+ }
+
+ init {
+ @Suppress("LeakingThis")
+ input.eventTarget = this
+ this.addInternal(input)
+ this.addInternal(validationInfo)
+ }
+
+ companion object {
+ /**
+ * DSL builder extension function.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+ fun Container.richText(
+ value: String? = null,
+ name: String? = null,
+ label: String? = null,
+ rich: Boolean = false,
+ init: (RichText.() -> Unit)? = null
+ ): RichText {
+ val richText = RichText(value, name, label, rich).apply { init?.invoke(this) }
+ this.add(richText)
+ return richText
+ }
+ }
+}
diff --git a/kvision-modules/kvision-richtext/src/main/kotlin/pl/treksoft/kvision/form/text/RichTextInput.kt b/kvision-modules/kvision-richtext/src/main/kotlin/pl/treksoft/kvision/form/text/RichTextInput.kt
new file mode 100644
index 00000000..961c27cd
--- /dev/null
+++ b/kvision-modules/kvision-richtext/src/main/kotlin/pl/treksoft/kvision/form/text/RichTextInput.kt
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2017-present Robert Jaros
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package pl.treksoft.kvision.form.text
+
+import com.github.snabbdom.VNode
+import pl.treksoft.jquery.jQuery
+import pl.treksoft.kvision.KVManagerRichText
+import pl.treksoft.kvision.core.Container
+import pl.treksoft.kvision.core.StringPair
+import kotlin.browser.document
+
+/**
+ * Basic rich text component.
+ *
+ * @constructor
+ * @param value text input value
+ * @param classes a set of CSS class names
+ */
+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 render("trix-editor")
+ }
+
+ override fun getSnAttrs(): List<StringPair> {
+ val sn = super.getSnAttrs().toMutableList()
+ placeholder?.let {
+ sn.add("placeholder" to translate(it))
+ }
+ name?.let {
+ sn.add("name" to it)
+ }
+ autofocus?.let {
+ if (it) {
+ sn.add("autofocus" to "autofocus")
+ }
+ }
+ if (disabled) {
+ sn.add("disabled" to "disabled")
+ }
+ return sn
+ }
+
+ @Suppress("UnsafeCastFromDynamic", "ComplexMethod")
+ 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")
+ if (trixId != null) {
+ value?.let {
+ if (this.getElement().asDynamic().editor != undefined) {
+ this.getElement().asDynamic().editor.loadHTML(it)
+ }
+ }
+ }
+ })
+ this.getElementJQuery()?.on("trix-file-accept", { e, _ -> e.preventDefault() })
+ }
+
+ override fun afterDestroy() {
+ document.getElementById("trix-input-$trixId")?.let { jQuery(it).remove() }
+ document.getElementById("trix-toolbar-$trixId")?.let { jQuery(it).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
+ if (editor != undefined) {
+ value?.let {
+ editor.loadHTML(it)
+ } ?: editor.loadHTML("")
+ }
+ }
+ }
+
+ override fun changeValue() {
+ // disabled parent class functionality
+ }
+
+ companion object {
+ /**
+ * DSL builder extension function.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+ fun Container.richTextInput(
+ value: String? = null, classes: Set<String> = setOf(), init: (RichTextInput.() -> Unit)? = null
+ ): RichTextInput {
+ val richTextInput = RichTextInput(value, classes).apply { init?.invoke(this) }
+ this.add(richTextInput)
+ return richTextInput
+ }
+ }
+}
diff --git a/kvision-modules/kvision-richtext/src/main/resources/js/locales/trix/trix.pl.js b/kvision-modules/kvision-richtext/src/main/resources/js/locales/trix/trix.pl.js
new file mode 100644
index 00000000..84dbd886
--- /dev/null
+++ b/kvision-modules/kvision-richtext/src/main/resources/js/locales/trix/trix.pl.js
@@ -0,0 +1,28 @@
+(function($){
+ window.Trix.config.languages["pl"] = {
+ GB:"GB",
+ KB:"KB",
+ MB:"MB",
+ PB:"PB",
+ TB:"TB",
+ bold:"Pogrubienie",
+ bullets:"Wypunktowanie",
+ byte:"Bajt",
+ bytes:"Bajty",
+ captionPlaceholder:"Dodaj tytuł…",
+ code:"Kod źródłowy",
+ heading1:"Nagłówek",
+ indent:"Zwiększ poziom",
+ italic:"Pochylenie",
+ link:"Link",
+ numbers:"Numerowanie",
+ outdent:"Zmniejsz poziom",
+ quote:"Cytat",
+ redo:"Ponów",
+ remove:"Usuń",
+ strike:"Przekreślenie",
+ undo:"Cofnij",
+ unlink:"Usuń link",
+ urlPlaceholder:"Wprowadź adres URL…"
+ }
+}(jQuery));