Bugfixes calendar auto scroll

This commit is contained in:
Lars Westermann 2019-06-14 11:59:19 +02:00
parent 5cf089dd72
commit 73c4190231
Signed by: lars.westermann
GPG key ID: 9D417FA5BB9D5E1D
3 changed files with 126 additions and 39 deletions

View file

@ -3,15 +3,16 @@ package de.kif.frontend.views.calendar
import de.kif.frontend.launch import de.kif.frontend.launch
import de.kif.frontend.repository.RoomRepository import de.kif.frontend.repository.RoomRepository
import de.kif.frontend.repository.ScheduleRepository import de.kif.frontend.repository.ScheduleRepository
import de.westermann.kwebview.View import de.westermann.kwebview.*
import de.westermann.kwebview.createHtmlView import de.westermann.robots.website.toolkit.view.TouchEvent
import de.westermann.kwebview.iterator
import org.w3c.dom.* import org.w3c.dom.*
import org.w3c.dom.events.Event
import org.w3c.dom.events.EventListener import org.w3c.dom.events.EventListener
import org.w3c.dom.events.MouseEvent
import org.w3c.dom.events.WheelEvent
import kotlin.browser.document import kotlin.browser.document
import kotlin.browser.window import kotlin.browser.window
import kotlin.js.Date import kotlin.js.Date
import kotlin.math.abs
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min
@ -80,6 +81,41 @@ class Calendar(calendar: HTMLElement) : View(calendar) {
} }
} }
private fun scroll(horizontal: Double, vertical: Double, event: Event? = null) {
var horizontalScroll = horizontal
var verticalScroll = vertical
if (verticalScroll > 0) {
val x = html.offsetTop - htmlBody.scrollTop
if (x > 0) {
val bodyScroll = min(x, verticalScroll)
verticalScroll -= bodyScroll
htmlBody.scrollBy(ScrollToOptions(0.0, bodyScroll, ScrollBehavior.INSTANT))
} else {
if (calendarTable.scrollTop + calendarTable.clientHeight + 5 >= calendarTable.scrollHeight) {
htmlBody.scrollBy(ScrollToOptions(0.0, verticalScroll, ScrollBehavior.INSTANT))
}
}
} else if (verticalScroll < 0) {
val x = html.offsetTop - htmlBody.scrollTop
if (x < 0) {
val bodyScroll = max(x, verticalScroll)
verticalScroll -= bodyScroll
htmlBody.scrollBy(ScrollToOptions(0.0, bodyScroll, ScrollBehavior.INSTANT))
} else {
if (calendarTable.scrollTop == 0.0) {
htmlBody.scrollBy(ScrollToOptions(0.0, verticalScroll, ScrollBehavior.INSTANT))
}
}
}
scrollHorizontalBy(horizontalScroll, ScrollBehavior.INSTANT)
scrollVerticalBy(verticalScroll, ScrollBehavior.INSTANT)
event?.preventDefault()
event?.stopPropagation()
}
init { init {
scroll += calendarTable scroll += calendarTable
@ -113,52 +149,61 @@ class Calendar(calendar: HTMLElement) : View(calendar) {
} }
} }
onWheel { document.addEventListener("wheel", EventListener {
val event = it as? WheelEvent ?: return@EventListener
autoScroll = false autoScroll = false
val multiplier = when (it.deltaMode) { val multiplier = when (event.deltaMode) {
1 -> 16.0 1 -> 16.0
2 -> window.innerHeight.toDouble() 2 -> window.innerHeight.toDouble()
else -> 1.0 else -> 1.0
} }
var verticalScroll = it.deltaY * multiplier scroll(event.deltaX * multiplier, event.deltaY * multiplier, event)
})
if (verticalScroll > 0) { var mousePoint: Point? = null
val x = html.offsetTop - htmlBody.scrollTop
if (x > 0) {
val bodyScroll = min(x, verticalScroll)
verticalScroll -= bodyScroll
htmlBody.scrollBy(ScrollToOptions(0.0, bodyScroll, ScrollBehavior.INSTANT))
} else {
if (calendarTable.scrollTop + calendarTable.clientHeight + 5 >= calendarTable.scrollHeight) {
htmlBody.scrollBy(ScrollToOptions(0.0, verticalScroll, ScrollBehavior.INSTANT))
}
}
} else if (verticalScroll < 0) {
val x = html.offsetTop - htmlBody.scrollTop
if (x < 0) {
val bodyScroll = max(x, verticalScroll)
verticalScroll -= bodyScroll
htmlBody.scrollBy(ScrollToOptions(0.0, bodyScroll, ScrollBehavior.INSTANT))
} else {
if (calendarTable.scrollTop == 0.0) {
htmlBody.scrollBy(ScrollToOptions(0.0, verticalScroll, ScrollBehavior.INSTANT))
}
}
}
scrollHorizontalBy(it.deltaX * multiplier, ScrollBehavior.INSTANT) document.addEventListener("mousedown", EventListener {
scrollVerticalBy(verticalScroll, ScrollBehavior.INSTANT) val event = it as? MouseEvent ?: return@EventListener
mousePoint = event.toPoint()
it.preventDefault() })
} document.addEventListener("mouseup", EventListener {
mousePoint = null
onMouseDown { })
document.addEventListener("mousemove", EventListener {
val event = it as? MouseEvent ?: return@EventListener
autoScroll = false autoScroll = false
}
html.addEventListener("touchstart", EventListener { val mp = mousePoint ?: return@EventListener
val p = event.toPoint()
scroll(mp.x - p.x, mp.y - p.y, event)
mousePoint = p
})
document.addEventListener("touchstart", EventListener {
val event = it as? TouchEvent ?: return@EventListener
mousePoint = event.toPoint()
})
document.addEventListener("touchend", EventListener {
mousePoint = null
})
document.addEventListener("touchmove", EventListener {
val event = it as? TouchEvent ?: return@EventListener
autoScroll = false
val mp = mousePoint ?: return@EventListener
val p = event.toPoint() ?: return@EventListener
scroll(mp.x - p.x, mp.y - p.y, event)
mousePoint = p
})
document.addEventListener("scroll", EventListener {
autoScroll = false autoScroll = false
}) })

View file

@ -0,0 +1,39 @@
package de.westermann.robots.website.toolkit.view
import org.w3c.dom.events.EventTarget
import org.w3c.dom.events.UIEvent
/**
* @author lars
*/
open external class TouchEvent(type: String) : UIEvent {
open val changedTouches: TouchList
open val targetTouches: TouchList
open val touches: TouchList
open val ctrlKey: Boolean
open val shiftKey: Boolean
open val altKey: Boolean
open val metaKey: Boolean
fun getModifierState(keyArg: String): Boolean
}
open external class TouchList() {
open val length: Int
open fun item(index: Int): Touch?
}
open external class Touch() {
open val identifier: Int
open val target: EventTarget
open val screenX: Int
open val screenY: Int
open val clientX: Int
open val clientY: Int
open val pageX: Int
open val pageY: Int
}
operator fun TouchList.get(index: Int) = item(index)
fun TouchList.all(): List<Touch> = (0..length).map { item(it) }.filterNotNull()
fun TouchList.find(identifier: Int): Touch? = all().find { it.identifier == identifier }

View file

@ -1,6 +1,8 @@
package de.westermann.kwebview package de.westermann.kwebview
import de.westermann.kobserve.event.EventHandler import de.westermann.kobserve.event.EventHandler
import de.westermann.robots.website.toolkit.view.TouchEvent
import de.westermann.robots.website.toolkit.view.get
import org.w3c.dom.* import org.w3c.dom.*
import org.w3c.dom.events.Event import org.w3c.dom.events.Event
import org.w3c.dom.events.EventListener import org.w3c.dom.events.EventListener
@ -72,6 +74,7 @@ inline fun <reified T> EventHandler<T>.bind(element: HTMLElement, event: String)
} }
fun MouseEvent.toPoint(): Point = Point(clientX, clientY) fun MouseEvent.toPoint(): Point = Point(clientX, clientY)
fun TouchEvent.toPoint(): Point? = touches[0]?.let { Point(it.clientX, it.clientY) }
fun DOMRect.toDimension(): Dimension = Dimension(x, y, width, height) fun DOMRect.toDimension(): Dimension = Dimension(x, y, width, height)
fun Number.format(digits: Int): String = this.asDynamic().toFixed(digits) fun Number.format(digits: Int): String = this.asDynamic().toFixed(digits)