diff options
Diffstat (limited to 'kvision-modules/kvision-onsenui/src/main/kotlin/pl/treksoft/kvision/onsenui')
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 } |