aboutsummaryrefslogtreecommitdiff
path: root/kvision-modules/kvision-onsenui/src/main/kotlin/pl
diff options
context:
space:
mode:
authorRobert Jaros <rjaros@finn.pl>2020-06-07 23:17:31 +0200
committerRobert Jaros <rjaros@finn.pl>2020-06-07 23:17:31 +0200
commitc2716ef0aae16553655cab4ea24f685e49e5fee8 (patch)
tree0a3fc4a4603e0cfa1faea3a3ca9d6673b4b9cbb0 /kvision-modules/kvision-onsenui/src/main/kotlin/pl
parent353815977be03d462393c57b829f2264aa9be85d (diff)
downloadkvision-master.tar.gz
kvision-master.tar.bz2
kvision-master.zip
OnsenUI carousel component. Basic tests for OnsenUI module (#126)HEADmaster
Diffstat (limited to 'kvision-modules/kvision-onsenui/src/main/kotlin/pl')
-rw-r--r--kvision-modules/kvision-onsenui/src/main/kotlin/pl/treksoft/kvision/onsenui/carousel/Carousel.kt348
-rw-r--r--kvision-modules/kvision-onsenui/src/main/kotlin/pl/treksoft/kvision/onsenui/carousel/CarouselItem.kt87
-rw-r--r--kvision-modules/kvision-onsenui/src/main/kotlin/pl/treksoft/kvision/onsenui/core/Page.kt4
-rw-r--r--kvision-modules/kvision-onsenui/src/main/kotlin/pl/treksoft/kvision/onsenui/tabbar/Tabbar.kt8
-rw-r--r--kvision-modules/kvision-onsenui/src/main/kotlin/pl/treksoft/kvision/onsenui/toolbar/Toolbar.kt2
5 files changed, 442 insertions, 7 deletions
diff --git a/kvision-modules/kvision-onsenui/src/main/kotlin/pl/treksoft/kvision/onsenui/carousel/Carousel.kt b/kvision-modules/kvision-onsenui/src/main/kotlin/pl/treksoft/kvision/onsenui/carousel/Carousel.kt
new file mode 100644
index 00000000..5998eba5
--- /dev/null
+++ b/kvision-modules/kvision-onsenui/src/main/kotlin/pl/treksoft/kvision/onsenui/carousel/Carousel.kt
@@ -0,0 +1,348 @@
+/*
+ * 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.onsenui.carousel
+
+import com.github.snabbdom.VNode
+import pl.treksoft.kvision.core.Component
+import pl.treksoft.kvision.core.Container
+import pl.treksoft.kvision.core.CssSize
+import pl.treksoft.kvision.core.StringPair
+import pl.treksoft.kvision.panel.SimplePanel
+import pl.treksoft.kvision.utils.asString
+import pl.treksoft.kvision.utils.obj
+import pl.treksoft.kvision.utils.set
+import kotlin.js.Promise
+
+enum class CarouselDirection(internal val type: String) {
+ HORIZONTAL("horizontal"),
+ VERTICAL("vertical")
+}
+
+/**
+ * A carousel component.
+ *
+ * @constructor Creates a carousel component.
+ * @param direction a carousel direction
+ * @param fullscreen whether the carousel should fill the whole screen
+ * @param overscrollable whether the carousel should scroll past first and last items
+ * @param animation determines if the transitions are animated
+ * @param swipeable determines if the carousel can be scrolled by drag or swipe
+ * @param classes a set of CSS class names
+ * @param init an initializer extension function
+ */
+open class Carousel(
+ direction: CarouselDirection? = null,
+ fullscreen: Boolean? = null,
+ overscrollable: Boolean? = null,
+ animation: Boolean? = null,
+ swipeable: Boolean? = null,
+ initialIndex: Int? = null,
+ classes: Set<String> = setOf(),
+ init: (Carousel.() -> Unit)? = null
+) : SimplePanel(classes) {
+
+ /**
+ * A carousel direction.
+ */
+ var direction: CarouselDirection? by refreshOnUpdate(direction)
+
+ /**
+ * Whether the carousel should fill the whole screen.
+ */
+ var fullscreen: Boolean? by refreshOnUpdate(fullscreen)
+
+ /**
+ * Whether the carousel should scroll past first and last items.
+ */
+ var overscrollable: Boolean? by refreshOnUpdate(overscrollable)
+
+ /**
+ * Determines if the transitions are animated.
+ */
+ var animation: Boolean? by refreshOnUpdate(animation)
+
+ /**
+ * Determines if the carousel can be scrolled by drag or swipe.
+ */
+ var swipeable: Boolean? by refreshOnUpdate(swipeable)
+
+ /**
+ * The index of the item to show on start.
+ */
+ var initialIndex: Int? by refreshOnUpdate(initialIndex)
+
+ /**
+ * Whether the selected item will be in the center of the carousel instead of the beginning.
+ */
+ var centered: Boolean? by refreshOnUpdate()
+
+ /**
+ * The item width (only for horizontal direction).
+ */
+ var itemWidth: CssSize? by refreshOnUpdate()
+
+ /**
+ * The item height (only for vertical direction).
+ */
+ var itemHeight: CssSize? by refreshOnUpdate()
+
+ /**
+ * Whether the carousel will be automatically scrolled to the closest item border.
+ */
+ var autoScroll: Boolean? by refreshOnUpdate()
+
+ /**
+ * Specifies how much the user must drag the carousel in order for it to auto scroll to the next item.
+ */
+ var autoScrollRatio: Number? by refreshOnUpdate()
+
+ /**
+ * Whether the carousel is disabled.
+ */
+ var disabled: Boolean? by refreshOnUpdate()
+
+ /**
+ * Whether the carousel will automatically refresh when the number of child nodes change.
+ */
+ var autoRefresh: Boolean? by refreshOnUpdate()
+
+ /**
+ * The swiper inner container.
+ */
+ val swiperPanel = SimplePanel(setOf("ons-swiper-target"))
+
+ init {
+ swiperPanel.parent = this
+ @Suppress("LeakingThis")
+ init?.invoke(this)
+ }
+
+ /**
+ * A dynamic property returning the number of carousel items.
+ */
+ val itemCount: dynamic
+ get() = getElement()?.asDynamic()?.itemCount
+
+ /**
+ * Swipe event listener function.
+ */
+ protected var onSwipeCallback: ((Number) -> Unit)? = null
+
+ override fun render(): VNode {
+ return render("ons-carousel", arrayOf(swiperPanel.renderVNode()))
+ }
+
+ @Suppress("UnsafeCastFromDynamic")
+ override fun afterInsert(node: VNode) {
+ if (onSwipeCallback != null) {
+ getElement()?.asDynamic()?.onSwipe = onSwipeCallback
+ }
+ this.getElementJQuery()?.on("postchange") { e, _ ->
+ this.dispatchEvent("onsPostchange", obj { detail = e })
+ }
+ this.getElementJQuery()?.on("refresh") { e, _ ->
+ this.dispatchEvent("onsRefresh", obj { detail = e })
+ }
+ this.getElementJQuery()?.on("overscroll") { e, _ ->
+ this.dispatchEvent("onsOverscroll", obj { detail = e })
+ }
+ }
+
+ override fun getSnAttrs(): List<StringPair> {
+ val sn = super.getSnAttrs().toMutableList()
+ direction?.let {
+ sn.add("direction" to it.type)
+ }
+ if (fullscreen == true) {
+ sn.add("fullscreen" to "fullscreen")
+ }
+ if (overscrollable == true) {
+ sn.add("overscrollable" to "overscrollable")
+ }
+ if (animation == false) {
+ sn.add("animation" to "none")
+ }
+ if (swipeable == true) {
+ sn.add("swipeable" to "swipeable")
+ }
+ initialIndex?.let {
+ sn.add("initial-index" to it.toString())
+ }
+ if (centered == true) {
+ sn.add("centered" to "centered")
+ }
+ itemWidth?.let {
+ sn.add("item-width" to it.asString())
+ }
+ itemHeight?.let {
+ sn.add("item-height" to it.asString())
+ }
+ if (autoScroll == true) {
+ sn.add("auto-scroll" to "auto-scroll")
+ }
+ autoScrollRatio?.let {
+ sn.add("auto-scroll-ratio" to it.toString())
+ }
+ if (disabled == true) {
+ sn.add("disabled" to "disabled")
+ }
+ if (autoRefresh == true) {
+ sn.add("auto-refresh" to "auto-refresh")
+ }
+ return sn
+ }
+
+ override fun add(child: Component): SimplePanel {
+ swiperPanel.add(child)
+ return this
+ }
+
+ override fun addAll(children: List<Component>): SimplePanel {
+ swiperPanel.addAll(children)
+ return this
+ }
+
+ override fun remove(child: Component): SimplePanel {
+ swiperPanel.remove(child)
+ return this
+ }
+
+ override fun removeAll(): SimplePanel {
+ swiperPanel.removeAll()
+ return this
+ }
+
+ override fun getChildren(): List<Component> {
+ return swiperPanel.getChildren()
+ }
+
+ /**
+ * Shows specified carousel item.
+ * @param index the carousel item index
+ * @param options a parameter object
+ */
+ @Suppress("UnsafeCastFromDynamic")
+ open fun setActiveIndex(index: Int, options: dynamic = undefined): Promise<Unit>? {
+ return getElement()?.asDynamic()?.setActiveIndex(index, options)
+ }
+
+ /**
+ * Gets the active item index.
+ * @return active item index
+ */
+ @Suppress("UnsafeCastFromDynamic")
+ open fun getActiveIndex(): Number {
+ return getElement()?.asDynamic()?.getActiveIndex() ?: -1
+ }
+
+ /**
+ * Shows next carousel item.
+ * @param options a parameter object
+ */
+ @Suppress("UnsafeCastFromDynamic")
+ open fun next(options: dynamic = undefined): Promise<Unit> {
+ return getElement()?.asDynamic()?.next(options)
+ }
+
+ /**
+ * Shows previous carousel item.
+ * @param options a parameter object
+ */
+ @Suppress("UnsafeCastFromDynamic")
+ open fun prev(options: dynamic = undefined): Promise<Unit> {
+ return getElement()?.asDynamic()?.prev(options)
+ }
+
+ /**
+ * Shows first carousel item.
+ * @param options a parameter object
+ */
+ @Suppress("UnsafeCastFromDynamic")
+ open fun first(options: dynamic = undefined): Promise<Unit> {
+ return getElement()?.asDynamic()?.first(options)
+ }
+
+ /**
+ * Shows last carousel item.
+ * @param options a parameter object
+ */
+ @Suppress("UnsafeCastFromDynamic")
+ open fun last(options: dynamic = undefined): Promise<Unit> {
+ return getElement()?.asDynamic()?.last(options)
+ }
+
+ /**
+ * Updates the layout of the carousel.
+ */
+ @Suppress("UnsafeCastFromDynamic")
+ open fun refreshCarousel() {
+ getElement()?.asDynamic()?.refresh()
+ }
+
+ /**
+ * Sets swipe event listener.
+ * @param callback an event listener
+ */
+ open fun onSwipe(callback: (ratio: Number) -> Unit) {
+ onSwipeCallback = callback
+ getElement()?.asDynamic()?.onSwipe = callback
+ }
+
+ /**
+ * Clears swipe event listener.
+ */
+ open fun onSwipeClear() {
+ onSwipeCallback = null
+ getElement()?.asDynamic()?.onSwipe = undefined
+ }
+}
+
+/**
+ * DSL builder extension function.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+fun Container.carousel(
+ direction: CarouselDirection? = null,
+ fullscreen: Boolean? = null,
+ overscrollable: Boolean? = null,
+ animation: Boolean? = null,
+ swipeable: Boolean? = null,
+ initialIndex: Int? = null,
+ classes: Set<String>? = null,
+ className: String? = null,
+ init: (Carousel.() -> Unit)? = null
+): Carousel {
+ val carousel = Carousel(
+ direction,
+ fullscreen,
+ overscrollable,
+ animation,
+ swipeable,
+ initialIndex,
+ classes ?: className.set,
+ init
+ )
+ this.add(carousel)
+ return carousel
+}
diff --git a/kvision-modules/kvision-onsenui/src/main/kotlin/pl/treksoft/kvision/onsenui/carousel/CarouselItem.kt b/kvision-modules/kvision-onsenui/src/main/kotlin/pl/treksoft/kvision/onsenui/carousel/CarouselItem.kt
new file mode 100644
index 00000000..5f1a2803
--- /dev/null
+++ b/kvision-modules/kvision-onsenui/src/main/kotlin/pl/treksoft/kvision/onsenui/carousel/CarouselItem.kt
@@ -0,0 +1,87 @@
+/*
+ * 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.onsenui.carousel
+
+import com.github.snabbdom.VNode
+import org.w3c.dom.events.MouseEvent
+import pl.treksoft.kvision.html.Align
+import pl.treksoft.kvision.html.Div
+import pl.treksoft.kvision.utils.set
+
+/**
+ * A carousel item component.
+ *
+ * @constructor Creates a carousel item component.
+ * @param content the content of the button.
+ * @param rich whether [content] can contain HTML code
+ * @param align text align
+ * @param classes a set of CSS class names
+ * @param init an initializer extension function
+ */
+open class CarouselItem(
+ content: String? = null,
+ rich: Boolean = false,
+ align: Align? = null,
+ classes: Set<String> = setOf(),
+ init: (CarouselItem.() -> Unit)? = null
+) : Div(content, rich, align, classes) {
+
+ init {
+ @Suppress("LeakingThis")
+ init?.invoke(this)
+ }
+
+ override fun render(elementName: String, children: Array<dynamic>): VNode {
+ return super.render("ons-carousel-item", children)
+ }
+
+ /**
+ * A convenient helper for easy setting onClick event handler.
+ */
+ open fun onClick(handler: CarouselItem.(MouseEvent) -> Unit): CarouselItem {
+ this.setEventListener<CarouselItem> {
+ click = { e ->
+ self.handler(e)
+ }
+ }
+ return this
+ }
+}
+
+/**
+ * DSL builder extension function.
+ *
+ * It takes the same parameters as the constructor of the built component.
+ */
+fun Carousel.carouselItem(
+ content: String? = null,
+ rich: Boolean = false,
+ align: Align? = null,
+ classes: Set<String>? = null,
+ className: String? = null,
+ init: (CarouselItem.() -> Unit)? = null
+): CarouselItem {
+ val carouselItem = CarouselItem(content, rich, align, classes ?: className.set, init)
+ this.add(carouselItem)
+ return carouselItem
+}
diff --git a/kvision-modules/kvision-onsenui/src/main/kotlin/pl/treksoft/kvision/onsenui/core/Page.kt b/kvision-modules/kvision-onsenui/src/main/kotlin/pl/treksoft/kvision/onsenui/core/Page.kt
index 72ce513a..3b76ed61 100644
--- a/kvision-modules/kvision-onsenui/src/main/kotlin/pl/treksoft/kvision/onsenui/core/Page.kt
+++ b/kvision-modules/kvision-onsenui/src/main/kotlin/pl/treksoft/kvision/onsenui/core/Page.kt
@@ -51,7 +51,7 @@ open class Page(classes: Set<String> = setOf(), init: (Page.() -> Unit)? = null)
/**
* The page toolbar.
*/
- var toolbar: Toolbar? = null
+ var toolbarPanel: Toolbar? = null
set(value) {
field = value
value?.parent = this
@@ -101,7 +101,7 @@ open class Page(classes: Set<String> = setOf(), init: (Page.() -> Unit)? = null)
}
override fun render(): VNode {
- val toolbarArr = toolbar?.let { arrayOf(it.renderVNode()) } ?: emptyArray()
+ val toolbarArr = toolbarPanel?.let { arrayOf(it.renderVNode()) } ?: emptyArray()
return render(
"ons-page",
toolbarArr + arrayOf(backgroundPanel.renderVNode(), contentPanel.renderVNode(), fixedPanel.renderVNode())
diff --git a/kvision-modules/kvision-onsenui/src/main/kotlin/pl/treksoft/kvision/onsenui/tabbar/Tabbar.kt b/kvision-modules/kvision-onsenui/src/main/kotlin/pl/treksoft/kvision/onsenui/tabbar/Tabbar.kt
index f526676c..a8fd5743 100644
--- a/kvision-modules/kvision-onsenui/src/main/kotlin/pl/treksoft/kvision/onsenui/tabbar/Tabbar.kt
+++ b/kvision-modules/kvision-onsenui/src/main/kotlin/pl/treksoft/kvision/onsenui/tabbar/Tabbar.kt
@@ -52,7 +52,7 @@ enum class TabsPosition(internal val type: String) {
*/
open class Tabbar(
tabPosition: TabsPosition? = null,
- animation: Boolean = true,
+ animation: Boolean? = null,
swipeable: Boolean? = null,
classes: Set<String> = setOf(),
init: (Tabbar.() -> Unit)? = null
@@ -66,7 +66,7 @@ open class Tabbar(
/**
* Determines if the transitions are animated.
*/
- var animation: Boolean by refreshOnUpdate(animation)
+ var animation: Boolean? by refreshOnUpdate(animation)
/**
* Determines if the tab bar can be scrolled by drag or swipe.
@@ -123,7 +123,7 @@ open class Tabbar(
tabPosition?.let {
sn.add("position" to it.type)
}
- if (!animation) {
+ if (animation == false) {
sn.add("animation" to "none")
}
if (swipeable == true) {
@@ -208,7 +208,7 @@ open class Tabbar(
}
/**
- * Get the active tab index.
+ * Gets the active tab index.
* @return active tab index
*/
@Suppress("UnsafeCastFromDynamic")
diff --git a/kvision-modules/kvision-onsenui/src/main/kotlin/pl/treksoft/kvision/onsenui/toolbar/Toolbar.kt b/kvision-modules/kvision-onsenui/src/main/kotlin/pl/treksoft/kvision/onsenui/toolbar/Toolbar.kt
index f52e110d..49231322 100644
--- a/kvision-modules/kvision-onsenui/src/main/kotlin/pl/treksoft/kvision/onsenui/toolbar/Toolbar.kt
+++ b/kvision-modules/kvision-onsenui/src/main/kotlin/pl/treksoft/kvision/onsenui/toolbar/Toolbar.kt
@@ -167,6 +167,6 @@ fun Page.toolbar(
init: (Toolbar.() -> Unit)? = null
): Toolbar {
val toolbar = Toolbar(label, inline, static, classes ?: className.set, init)
- this.toolbar = toolbar
+ this.toolbarPanel = toolbar
return toolbar
}