many small client improvements
This commit is contained in:
parent
0122ca2e4f
commit
40fc917164
15
js_client/app.js
Normal file
15
js_client/app.js
Normal file
@ -0,0 +1,15 @@
|
||||
window.addEventListener('load', e => {
|
||||
registerSW();
|
||||
});
|
||||
|
||||
async function registerSW() {
|
||||
if ('serviceWorker' in navigator) {
|
||||
try {
|
||||
await navigator.serviceWorker.register('./sw.js');
|
||||
} catch (e) {
|
||||
alert('ServiceWorker registration failed. Sorry about that.');
|
||||
}
|
||||
} else {
|
||||
document.querySelector('.alert').removeAttribute('hidden');
|
||||
}
|
||||
}
|
BIN
js_client/big_icon.png
Normal file
BIN
js_client/big_icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.5 KiB |
@ -2,7 +2,7 @@ export function setCookie(cname, cvalue, exdays) {
|
||||
var d = new Date();
|
||||
d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
|
||||
var expires = "expires=" + d.toUTCString();
|
||||
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
|
||||
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/; SameSite=Strict";
|
||||
}
|
||||
|
||||
export function getCookie(cname) {
|
||||
|
@ -2,39 +2,46 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<!-- Polyfills only needed for Firefox and Edge. -->
|
||||
<script src="https://unpkg.com/@webcomponents/webcomponentsjs@latest/webcomponents-loader.js"></script>
|
||||
<!-- Works only on browsers that support Javascript modules like
|
||||
<link rel="icon" type="image/png" href="./favicon.png" />
|
||||
<link rel="manifest" href="./manifest.json">
|
||||
<script type="module" src="./app.js"></script>
|
||||
<script type="module" src="./sw.js"></script>
|
||||
|
||||
<!-- Polyfills only needed for Firefox and Edge. -->
|
||||
<script src="https://unpkg.com/@webcomponents/webcomponentsjs@latest/webcomponents-loader.js"></script>
|
||||
<!-- Works only on browsers that support Javascript modules like
|
||||
Chrome, Safari, Firefox 60, Edge 17 -->
|
||||
|
||||
<style>
|
||||
body {
|
||||
background-color: black;
|
||||
font-size: 1.5vh;
|
||||
}
|
||||
<style>
|
||||
body {
|
||||
background-color: black;
|
||||
|
||||
font-size: 1.5vh;
|
||||
}
|
||||
|
||||
@media (max-aspect-ratio: 3/2) {
|
||||
body {
|
||||
font-size: 1.5vh;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
// Original viewport definition, note the "id" that I use to modify the viewport later on:
|
||||
<meta name="viewport" id="viewport" content="width=device-width, height=device-height, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>
|
||||
|
||||
<script>
|
||||
@media (max-aspect-ratio: 3/2) {
|
||||
body {
|
||||
font-size: 1.5vh;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
// Original viewport definition, note the "id" that I use to modify the viewport later on:
|
||||
<meta name="viewport" id="viewport"
|
||||
content="width=device-width, height=device-height, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
|
||||
|
||||
<script>
|
||||
// Global boolean variable that holds the current orientation
|
||||
var pageInPortraintMode;
|
||||
|
||||
|
||||
// Listen for window resizes to detect orientation changes
|
||||
window.addEventListener("resize", windowSizeChanged);
|
||||
|
||||
|
||||
// Set the global orientation variable as soon as the page loads
|
||||
addEventListener("load", function() {
|
||||
addEventListener("load", function () {
|
||||
pageInPortraintMode = window.innerHeight > window.innerWidth;
|
||||
document.getElementById("viewport").setAttribute("content", "width=" + window.innerWidth + ", height=" + window.innerHeight + ", initial-scale=1.0, maximum-scale=1.0, user-scalable=0");
|
||||
})
|
||||
|
||||
|
||||
// Adjust viewport values only if orientation has changed (not on every window resize)
|
||||
function windowSizeChanged() {
|
||||
if (((pageInPortraintMode === true) && (window.innerHeight < window.innerWidth)) || ((pageInPortraintMode === false) && (window.innerHeight > window.innerWidth))) {
|
||||
@ -42,15 +49,16 @@
|
||||
document.getElementById("viewport").setAttribute("content", "width=" + window.innerWidth + ", height=" + window.innerHeight + ", initial-scale=1.0, maximum-scale=1.0, user-scalable=0");
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<info-box id="infobox"></info-box>
|
||||
<server-connection id="server-connection" lang="en" grid_id="grid" url="wss://the-cake-is-a-lie.net:8765"></server-connection>
|
||||
<crossword-grid id="grid" infobox_id="infobox" width="10" height="10"></crossword-grid>
|
||||
<script type="module" src="./main.js"></script>
|
||||
<info-box id="infobox"></info-box>
|
||||
<server-connection id="server-connection" lang="en" grid_id="grid" url="wss://the-cake-is-a-lie.net:8765">
|
||||
</server-connection>
|
||||
<crossword-grid id="grid" infobox_id="infobox" width="10" height="10"></crossword-grid>
|
||||
<script type="module" src="./main.js"></script>
|
||||
|
||||
</body>
|
||||
|
||||
|
BIN
js_client/favicon.png
Normal file
BIN
js_client/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.3 KiB |
@ -2,39 +2,44 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<!-- Polyfills only needed for Firefox and Edge. -->
|
||||
<script src="https://unpkg.com/@webcomponents/webcomponentsjs@latest/webcomponents-loader.js"></script>
|
||||
<!-- Works only on browsers that support Javascript modules like
|
||||
<link rel="icon" type="image/png" href="./favicon.png" />
|
||||
<link rel="manifest" href="./manifest.json">
|
||||
<script type="module" src="./app.js"></script>
|
||||
<script type="module" src="./sw.js"></script>
|
||||
<!-- Polyfills only needed for Firefox and Edge. -->
|
||||
<script src="https://unpkg.com/@webcomponents/webcomponentsjs@latest/webcomponents-loader.js"></script>
|
||||
<!-- Works only on browsers that support Javascript modules like
|
||||
Chrome, Safari, Firefox 60, Edge 17 -->
|
||||
|
||||
<style>
|
||||
body {
|
||||
background-color: black;
|
||||
font-size: 1.5vh;
|
||||
}
|
||||
<style>
|
||||
body {
|
||||
background-color: black;
|
||||
font-size: 1.5vh;
|
||||
}
|
||||
|
||||
@media (max-aspect-ratio: 3/2) {
|
||||
body {
|
||||
font-size: 1.5vh;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
// Original viewport definition, note the "id" that I use to modify the viewport later on:
|
||||
<meta name="viewport" id="viewport" content="width=device-width, height=device-height, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>
|
||||
|
||||
<script>
|
||||
@media (max-aspect-ratio: 3/2) {
|
||||
body {
|
||||
font-size: 1.5vh;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
// Original viewport definition, note the "id" that I use to modify the viewport later on:
|
||||
<meta name="viewport" id="viewport"
|
||||
content="width=device-width, height=device-height, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
|
||||
|
||||
<script>
|
||||
// Global boolean variable that holds the current orientation
|
||||
var pageInPortraintMode;
|
||||
|
||||
|
||||
// Listen for window resizes to detect orientation changes
|
||||
window.addEventListener("resize", windowSizeChanged);
|
||||
|
||||
|
||||
// Set the global orientation variable as soon as the page loads
|
||||
addEventListener("load", function() {
|
||||
addEventListener("load", function () {
|
||||
pageInPortraintMode = window.innerHeight > window.innerWidth;
|
||||
document.getElementById("viewport").setAttribute("content", "width=" + window.innerWidth + ", height=" + window.innerHeight + ", initial-scale=1.0, maximum-scale=1.0, user-scalable=0");
|
||||
})
|
||||
|
||||
|
||||
// Adjust viewport values only if orientation has changed (not on every window resize)
|
||||
function windowSizeChanged() {
|
||||
if (((pageInPortraintMode === true) && (window.innerHeight < window.innerWidth)) || ((pageInPortraintMode === false) && (window.innerHeight > window.innerWidth))) {
|
||||
@ -42,15 +47,15 @@
|
||||
document.getElementById("viewport").setAttribute("content", "width=" + window.innerWidth + ", height=" + window.innerHeight + ", initial-scale=1.0, maximum-scale=1.0, user-scalable=0");
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<info-box id="infobox"></info-box>
|
||||
<server-connection id="server-connection" lang="de" grid_id="grid" url="ws://localhost:8765"></server-connection>
|
||||
<crossword-grid id="grid" infobox_id="infobox" width="10" height="10"></crossword-grid>
|
||||
<script type="module" src="./main.js"></script>
|
||||
<info-box id="infobox"></info-box>
|
||||
<server-connection id="server-connection" lang="de" grid_id="grid" url="ws://localhost:8765"></server-connection>
|
||||
<crossword-grid id="grid" infobox_id="infobox" width="10" height="10"></crossword-grid>
|
||||
<script type="module" src="./main.js"></script>
|
||||
|
||||
</body>
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { html, css, LitElement, unsafeCSS } from 'https://unpkg.com/lit-element/lit-element.js?module';
|
||||
import './infoBox.js'
|
||||
import {GridElement, GridLetter, GridBox, gridType} from './gridBoxes.js'
|
||||
import { GridElement, GridLetter, GridBox, gridType } from './gridBoxes.js'
|
||||
import './solutionBox.js'
|
||||
|
||||
export class CrosswordGrid extends LitElement {
|
||||
@ -88,10 +88,11 @@ export class CrosswordGrid extends LitElement {
|
||||
|
||||
this.solution_locations = json_grid.solution
|
||||
|
||||
if (this.solutionBox)
|
||||
if (this.solutionBox) {
|
||||
this.solutionBox.length = this.solution_locations.length;
|
||||
this.solutionBox.requestUpdate();
|
||||
console.log("update box");
|
||||
}
|
||||
|
||||
var y;
|
||||
var x;
|
||||
@ -126,14 +127,19 @@ export class CrosswordGrid extends LitElement {
|
||||
|
||||
this.requestUpdate();
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
focusNextCellHorizontal(x, y) {
|
||||
focusNextCellHorizontal(x, y, skip_revealed = false) {
|
||||
if (x + 1 < this.width && this.grid[y][x + 1].getGridType() === gridType.LETTER) {
|
||||
if (this.grid[y][x].getGridType() === gridType.LETTER) {
|
||||
this.grid[y][x].getGridLetter().blur();
|
||||
//this.grid[y][x].getGridLetter().blur();
|
||||
}
|
||||
|
||||
if (skip_revealed && this.grid[y][x + 1].getGridLetter().revealed) {
|
||||
return this.focusNextCellHorizontal(x + 1, y, true);
|
||||
}
|
||||
|
||||
this.grid[y][x + 1].getGridLetter().focus(x, y);
|
||||
|
||||
|
||||
@ -143,11 +149,16 @@ export class CrosswordGrid extends LitElement {
|
||||
return false;
|
||||
}
|
||||
|
||||
focusPrevCellHorizontal(x, y) {
|
||||
focusPrevCellHorizontal(x, y, skip_revealed = false) {
|
||||
if (x - 1 >= 0 && this.grid[y][x - 1].getGridType() === gridType.LETTER) {
|
||||
if (this.grid[y][x].getGridType() === gridType.LETTER) {
|
||||
this.grid[y][x].getGridLetter().blur();
|
||||
//this.grid[y][x].getGridLetter().blur();
|
||||
}
|
||||
|
||||
if (skip_revealed && this.grid[y][x - 1].getGridLetter().revealed) {
|
||||
return this.focusPrevCellHorizontal(x - 1, y, true);
|
||||
}
|
||||
|
||||
this.grid[y][x - 1].getGridLetter().focus();
|
||||
|
||||
|
||||
@ -157,10 +168,13 @@ export class CrosswordGrid extends LitElement {
|
||||
return false;
|
||||
}
|
||||
|
||||
focusNextCellVertical(x, y) {
|
||||
focusNextCellVertical(x, y, skip_revealed = false) {
|
||||
if (y + 1 < this.height && this.grid[y + 1][x].getGridType() === gridType.LETTER) {
|
||||
if (this.grid[y][x].getGridType() === gridType.LETTER) {
|
||||
this.grid[y][x].getGridLetter().blur();
|
||||
//this.grid[y][x].getGridLetter().blur();
|
||||
}
|
||||
if (skip_revealed && this.grid[y + 1][x].getGridLetter().revealed) {
|
||||
return this.focusNextCellVertical(x, y + 1, true);
|
||||
}
|
||||
this.grid[y + 1][x].getGridLetter().focus(x, y);
|
||||
|
||||
@ -170,10 +184,13 @@ export class CrosswordGrid extends LitElement {
|
||||
return false;
|
||||
}
|
||||
|
||||
focusPrevCellVertical(x, y) {
|
||||
focusPrevCellVertical(x, y, skip_revealed = false) {
|
||||
if (y - 1 >= 0 && this.grid[y - 1][x].getGridType() === gridType.LETTER) {
|
||||
if (this.grid[y][x].getGridType() === gridType.LETTER) {
|
||||
this.grid[y][x].getGridLetter().blur();
|
||||
//this.grid[y][x].getGridLetter().blur();
|
||||
}
|
||||
if (skip_revealed && this.grid[y - 1][x].getGridLetter().revealed) {
|
||||
return this.focusPrevCellVertical(x, y - 1, true);
|
||||
}
|
||||
this.grid[y - 1][x].getGridLetter().focus();
|
||||
|
||||
@ -186,18 +203,18 @@ export class CrosswordGrid extends LitElement {
|
||||
|
||||
focusNextCell(x, y) {
|
||||
if (this.lastMoveVertical) {
|
||||
if (this.focusNextCellVertical(x, y)) {
|
||||
if (this.focusNextCellVertical(x, y, true)) {
|
||||
return;
|
||||
}
|
||||
if (this.focusNextCellHorizontal(x, y)) {
|
||||
if (this.focusNextCellHorizontal(x, y, true)) {
|
||||
this.lastMoveVertical = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (this.focusNextCellHorizontal(x, y)) {
|
||||
if (this.focusNextCellHorizontal(x, y, true)) {
|
||||
return;
|
||||
}
|
||||
if (this.focusNextCellVertical(x, y)) {
|
||||
if (this.focusNextCellVertical(x, y, true)) {
|
||||
this.lastMoveVertical = true;
|
||||
}
|
||||
}
|
||||
@ -209,18 +226,18 @@ export class CrosswordGrid extends LitElement {
|
||||
return;
|
||||
}
|
||||
if (this.lastMoveVertical) {
|
||||
if (this.focusPrevCellVertical(x, y)) {
|
||||
if (this.focusPrevCellVertical(x, y, true)) {
|
||||
return;
|
||||
}
|
||||
if (this.focusPrevCellHorizontal(x, y)) {
|
||||
if (this.focusPrevCellHorizontal(x, y, true)) {
|
||||
this.lastMoveVertical = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (this.focusPrevCellHorizontal(x, y)) {
|
||||
if (this.focusPrevCellHorizontal(x, y, true)) {
|
||||
return;
|
||||
}
|
||||
if (this.focusPrevCellVertical(x, y)) {
|
||||
if (this.focusPrevCellVertical(x, y, true)) {
|
||||
this.lastMoveVertical = true;
|
||||
}
|
||||
}
|
||||
@ -335,23 +352,33 @@ export class CrosswordGrid extends LitElement {
|
||||
this.serverConnection.sendMessage(msg)
|
||||
}
|
||||
|
||||
setSolutionLetter(solutionNumber, letter, revealed = false){
|
||||
setSolutionLetter(solutionNumber, letter, revealed = false) {
|
||||
this.solutionBox.setLetter(solutionNumber, letter, revealed);
|
||||
const x = this.solution_locations[solutionNumber][1];
|
||||
const y = this.solution_locations[solutionNumber][0];
|
||||
console.log("update solution letter");
|
||||
var old_val = this.grid[y][x].getGridLetter().value;
|
||||
this.grid[y][x].getGridLetter().value = letter;
|
||||
|
||||
if (old_val != letter && !revealed) {
|
||||
this.sendMessage({
|
||||
'type': 'update',
|
||||
'x': x,
|
||||
'y': y,
|
||||
'letter': letter
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
render() {
|
||||
this.num_hints = 0;
|
||||
console.log("refreshing grid");
|
||||
|
||||
var solution_length = 0;
|
||||
if (this.solution_locations){
|
||||
if (this.solution_locations) {
|
||||
solution_length = this.solution_locations.length;
|
||||
}
|
||||
|
||||
|
@ -397,6 +397,8 @@ export class GridLetter extends GridBox {
|
||||
|
||||
updateLetter(letter, revealed) {
|
||||
this.value = letter;
|
||||
var element = this.shadowRoot.getElementById(`${this.x}-${this.y}`);
|
||||
element.value = letter;
|
||||
if (revealed) {
|
||||
console.log("rec")
|
||||
this.shadowRoot.getElementById(`${this.x}-${this.y}`).readOnly = true;
|
||||
|
@ -2,6 +2,11 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<link rel="icon" type="image/png" href="./favicon.png" />
|
||||
<link rel="manifest" href="./manifest.json">
|
||||
<script type="module" src="./app.js"></script>
|
||||
<script type="module" src="./sw.js"></script>
|
||||
|
||||
<!-- Polyfills only needed for Firefox and Edge. -->
|
||||
<script src="https://unpkg.com/@webcomponents/webcomponentsjs@latest/webcomponents-loader.js"></script>
|
||||
<!-- Works only on browsers that support Javascript modules like
|
||||
@ -72,8 +77,12 @@
|
||||
|
||||
<div class="centerbox">
|
||||
<h3>Select the language:</h3>
|
||||
<a href="./german.html"> <div class="box"> German </div> </a>
|
||||
<a href="./english.html"> <div class="box"> English </div> </a>
|
||||
<a href="./german.html">
|
||||
<div class="box"> German </div>
|
||||
</a>
|
||||
<a href="./english.html">
|
||||
<div class="box"> English </div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
16
js_client/manifest.json
Normal file
16
js_client/manifest.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "Crosswords",
|
||||
"short_name": "crosswords",
|
||||
"start_url": "./",
|
||||
"display": "standalone",
|
||||
"background_color": "#000000",
|
||||
"description": "Simple Collaborative Crossword",
|
||||
"theme_color": "#000000",
|
||||
"icons": [
|
||||
{
|
||||
"src": "./big_icon.png",
|
||||
"sizes": "256x256",
|
||||
"type": "image/png"
|
||||
}
|
||||
]
|
||||
}
|
@ -73,7 +73,7 @@ export class ServerConnection extends WebsocketConnection {
|
||||
console.log("stored session", sessionId, "as cookie")
|
||||
setCookie("session", sessionId, 2);
|
||||
const urlparams = new URLSearchParams(window.location.search);
|
||||
if (urlparams.has('session') && this.sessionId === urlparams.get('session')){
|
||||
if (urlparams.has('session') && this.sessionId === urlparams.get('session')) {
|
||||
return;
|
||||
}
|
||||
urlparams.set('session', sessionId);
|
||||
|
51
js_client/sw.js
Normal file
51
js_client/sw.js
Normal file
@ -0,0 +1,51 @@
|
||||
const cacheName = 'pwa-conf-v4';
|
||||
const staticAssets = [
|
||||
'./app.js ',
|
||||
'./big_icon.png',
|
||||
'./english.html',
|
||||
'./german.html',
|
||||
'./grid.js',
|
||||
'./infoBox.js',
|
||||
'./manifest.json',
|
||||
'./serverConnection.js',
|
||||
'./cookie.js',
|
||||
'./favicon.png',
|
||||
'./gridBoxes.js',
|
||||
'./index.html',
|
||||
'./main.js',
|
||||
'./solutionBox.js',
|
||||
'./websocket.js'
|
||||
];
|
||||
|
||||
|
||||
self.addEventListener('install', async event => {
|
||||
const cache = await caches.open(cacheName);
|
||||
|
||||
|
||||
await cache.addAll(staticAssets);
|
||||
|
||||
|
||||
});
|
||||
|
||||
self.addEventListener('fetch', event => {
|
||||
const req = event.request;
|
||||
event.respondWith(networkFirst(req));
|
||||
});
|
||||
|
||||
async function cacheFirst(req) {
|
||||
const cache = await caches.open(cacheName);
|
||||
|
||||
|
||||
const cachedResponse = await cache.match(req);
|
||||
|
||||
|
||||
return cachedResponse || fetch(req);
|
||||
|
||||
|
||||
}
|
||||
|
||||
async function networkFirst(req) {
|
||||
return fetch(req).catch(function() {
|
||||
return caches.match(req);
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue
Block a user