Migrate player client to Alpine.js.
This commit is contained in:
parent
5b13eb5ece
commit
7357528bb5
4 changed files with 122 additions and 14 deletions
45
src/main/kotlin/de/pheerai/buzzer/alpine/attributes.kt
Normal file
45
src/main/kotlin/de/pheerai/buzzer/alpine/attributes.kt
Normal file
|
@ -0,0 +1,45 @@
|
|||
package de.pheerai.buzzer.alpine
|
||||
|
||||
import kotlinx.html.HTMLTag
|
||||
|
||||
fun HTMLTag.xData(data: String) {
|
||||
attributes["x-data"] = data
|
||||
}
|
||||
|
||||
fun HTMLTag.xInit(init: String) {
|
||||
attributes["x-init"] = init
|
||||
}
|
||||
|
||||
fun HTMLTag.xOn(event: String, handler: String, debounce: Boolean = false, debounceMs: Int = 0) {
|
||||
val debounceString = if (debounce && debounceMs > 0) {
|
||||
".debounce.${debounceMs}ms"
|
||||
} else if (debounce) {
|
||||
".debounce"
|
||||
} else {
|
||||
""
|
||||
}
|
||||
attributes["x-on:${event}$debounceString"] = handler
|
||||
}
|
||||
|
||||
fun HTMLTag.xModel(model: String, debounce: Boolean = false, debounceMs: Int = 0) {
|
||||
val debounceString = if (debounce && debounceMs > 0) {
|
||||
".debounce.${debounceMs}ms"
|
||||
} else if (debounce) {
|
||||
".debounce"
|
||||
} else {
|
||||
""
|
||||
}
|
||||
attributes["x-model$debounceString"] = model
|
||||
}
|
||||
|
||||
fun HTMLTag.xShow(data: String) {
|
||||
attributes["x-show"] = data
|
||||
}
|
||||
|
||||
fun HTMLTag.xText(text: String) {
|
||||
attributes["x-text"] = text
|
||||
}
|
||||
|
||||
fun HTMLTag.xBind(type: String, data: String) {
|
||||
attributes["x-bind:$type"] = data
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package de.pheerai.buzzer.clients
|
||||
|
||||
import de.pheerai.buzzer.alpine.*
|
||||
import kotlinx.html.*
|
||||
|
||||
fun HTML.createPlayerDocument() {
|
||||
|
@ -11,23 +12,55 @@ fun HTML.createPlayerDocument() {
|
|||
rel = "stylesheet",
|
||||
type = "text/css"
|
||||
)
|
||||
script { src = "https://code.jquery.com/jquery-3.6.0.min.js" }
|
||||
script { src = "/assets/playerClient.js" }
|
||||
script {
|
||||
src = "https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"
|
||||
defer = true
|
||||
}
|
||||
script {
|
||||
src = "/assets/playerClient.js"
|
||||
}
|
||||
}
|
||||
body {
|
||||
div(classes = "parent") {
|
||||
attributes["foo"] = "bar"
|
||||
xInit("startWebSocket()")
|
||||
xData("{playerName: \"\"}")
|
||||
div(classes = "input") {
|
||||
label { +"Player" }
|
||||
div(classes = "bumper") {}
|
||||
input {
|
||||
xModel("playerName", debounce = true)
|
||||
type = InputType.text
|
||||
id = "username"
|
||||
placeholder = "<name>"
|
||||
}
|
||||
}
|
||||
div(classes = "submit disabled") {
|
||||
xShow("!playerName")
|
||||
+"Enter a name first!"
|
||||
}
|
||||
button(classes = "submit") {
|
||||
onClick = "sendUsername()"
|
||||
+"I know that!"
|
||||
xShow("playerName")
|
||||
xData("{clicked: false}")
|
||||
xOn(
|
||||
"click",
|
||||
"""
|
||||
() => {
|
||||
sendUsername(playerName);
|
||||
clicked = true
|
||||
setTimeout(() => {
|
||||
clicked = false
|
||||
}, 50)
|
||||
}
|
||||
""".trimMargin()
|
||||
)
|
||||
xOn("mousedown", "clicked = true")
|
||||
xOn("touchstart", "clicked = true")
|
||||
xBind("class", "{'active': clicked}")
|
||||
+"I'm "
|
||||
span {
|
||||
xText("playerName")
|
||||
}
|
||||
+" and I know this!"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,8 +52,9 @@ div > .submit {
|
|||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
div > .button:hover {
|
||||
div > button.active {
|
||||
background-color: #5B1D4A;
|
||||
}
|
||||
|
|
|
@ -2,17 +2,46 @@
|
|||
|
||||
let webSocket;
|
||||
|
||||
$.when($.ready).then(function () {
|
||||
function startWebSocket() {
|
||||
let protocolPrefix = (window.location.protocol === 'https:') ? 'wss:' : 'ws:';
|
||||
webSocket = new WebSocket(`${protocolPrefix}//${location.host}/socket/player`);
|
||||
});
|
||||
webSocket.onerror = (ev) => {
|
||||
switch (ev.code) {
|
||||
case 1000:
|
||||
console.log("[WS]: Closed normally")
|
||||
break
|
||||
default:
|
||||
console.log("[WS]: Closed abnormally")
|
||||
reconnectWebSocket();
|
||||
}
|
||||
};
|
||||
webSocket.onclose = (ev) => {
|
||||
switch (ev.code) {
|
||||
case 'ECONNREFUSED':
|
||||
reconnectWebSocket();
|
||||
break
|
||||
default:
|
||||
webSocket.onerror(ev);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function sendUsername() {
|
||||
const username = $('#username').val()
|
||||
if (username !== null && username !== '') {
|
||||
console.log(`Username: ${username}`)
|
||||
webSocket.send(username)
|
||||
function reconnectWebSocket() {
|
||||
setTimeout(() => {
|
||||
console.log("[WS]: Reconnecting...")
|
||||
startWebSocket()
|
||||
}, 2000)
|
||||
}
|
||||
|
||||
function sendUsername(username) {
|
||||
if (
|
||||
username !== undefined
|
||||
&& username !== null
|
||||
&& username !== ''
|
||||
) {
|
||||
console.log(`Username: ${username}`);
|
||||
webSocket.send(username);
|
||||
} else {
|
||||
alert("Please enter a name!")
|
||||
alert("Please enter a name!");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue