first version
This commit is contained in:
		
							
								
								
									
										94
									
								
								js_client/assets/hint_both.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								js_client/assets/hint_both.svg
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,94 @@ | ||||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||
| <svg | ||||
|    xmlns:dc="http://purl.org/dc/elements/1.1/" | ||||
|    xmlns:cc="http://creativecommons.org/ns#" | ||||
|    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | ||||
|    xmlns:svg="http://www.w3.org/2000/svg" | ||||
|    xmlns="http://www.w3.org/2000/svg" | ||||
|    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||
|    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||
|    width="100" | ||||
|    height="100" | ||||
|    viewBox="0 0 26.458333 26.458334" | ||||
|    version="1.1" | ||||
|    id="svg8" | ||||
|    inkscape:version="1.0.2 (e86c870879, 2021-01-15)" | ||||
|    sodipodi:docname="hint_both.svg"> | ||||
|   <defs | ||||
|      id="defs2" /> | ||||
|   <sodipodi:namedview | ||||
|      id="base" | ||||
|      pagecolor="#ffffff" | ||||
|      bordercolor="#666666" | ||||
|      borderopacity="1.0" | ||||
|      inkscape:pageopacity="0.0" | ||||
|      inkscape:pageshadow="2" | ||||
|      inkscape:zoom="4.3481303" | ||||
|      inkscape:cx="49.605183" | ||||
|      inkscape:cy="79.488474" | ||||
|      inkscape:document-units="mm" | ||||
|      inkscape:current-layer="layer1" | ||||
|      inkscape:document-rotation="0" | ||||
|      showgrid="true" | ||||
|      units="px" | ||||
|      inkscape:window-width="1920" | ||||
|      inkscape:window-height="950" | ||||
|      inkscape:window-x="0" | ||||
|      inkscape:window-y="27" | ||||
|      inkscape:window-maximized="1"> | ||||
|     <inkscape:grid | ||||
|        type="xygrid" | ||||
|        id="grid10" | ||||
|        spacingy="0.52916667" | ||||
|        spacingx="0.52916667" /> | ||||
|   </sodipodi:namedview> | ||||
|   <metadata | ||||
|      id="metadata5"> | ||||
|     <rdf:RDF> | ||||
|       <cc:Work | ||||
|          rdf:about=""> | ||||
|         <dc:format>image/svg+xml</dc:format> | ||||
|         <dc:type | ||||
|            rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | ||||
|         <dc:title></dc:title> | ||||
|       </cc:Work> | ||||
|     </rdf:RDF> | ||||
|   </metadata> | ||||
|   <g | ||||
|      inkscape:label="Ebene 1" | ||||
|      inkscape:groupmode="layer" | ||||
|      id="layer1"> | ||||
|     <path | ||||
|        sodipodi:type="star" | ||||
|        style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.529167;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers" | ||||
|        id="path861" | ||||
|        sodipodi:sides="3" | ||||
|        sodipodi:cx="13.229166" | ||||
|        sodipodi:cy="23.8125" | ||||
|        sodipodi:r1="2.6458333" | ||||
|        sodipodi:r2="1.3229167" | ||||
|        sodipodi:arg1="1.5707963" | ||||
|        sodipodi:arg2="2.6179939" | ||||
|        inkscape:flatsided="true" | ||||
|        inkscape:rounded="0" | ||||
|        inkscape:randomized="0" | ||||
|        d="m 13.229166,26.458333 -2.291359,-3.96875 4.582718,0 z" | ||||
|        inkscape:transform-center-y="0.66145805" /> | ||||
|     <path | ||||
|        sodipodi:type="star" | ||||
|        style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.529167;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers" | ||||
|        id="path863" | ||||
|        sodipodi:sides="3" | ||||
|        sodipodi:cx="23.8125" | ||||
|        sodipodi:cy="13.229166" | ||||
|        sodipodi:r1="2.6458333" | ||||
|        sodipodi:r2="1.3229167" | ||||
|        sodipodi:arg1="0" | ||||
|        sodipodi:arg2="1.0471976" | ||||
|        inkscape:flatsided="true" | ||||
|        inkscape:rounded="0" | ||||
|        inkscape:randomized="0" | ||||
|        d="m 26.458333,13.229166 -3.96875,2.291359 v -4.582718 z" | ||||
|        inkscape:transform-center-x="-0.66145805" /> | ||||
|   </g> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 3.0 KiB | 
							
								
								
									
										78
									
								
								js_client/assets/hint_horizontal.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								js_client/assets/hint_horizontal.svg
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,78 @@ | ||||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||
| <svg | ||||
|    xmlns:dc="http://purl.org/dc/elements/1.1/" | ||||
|    xmlns:cc="http://creativecommons.org/ns#" | ||||
|    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | ||||
|    xmlns:svg="http://www.w3.org/2000/svg" | ||||
|    xmlns="http://www.w3.org/2000/svg" | ||||
|    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||
|    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||
|    width="100" | ||||
|    height="100" | ||||
|    viewBox="0 0 26.458333 26.458334" | ||||
|    version="1.1" | ||||
|    id="svg8" | ||||
|    sodipodi:docname="hint_horizontal.svg" | ||||
|    inkscape:version="1.0.2 (e86c870879, 2021-01-15)"> | ||||
|   <defs | ||||
|      id="defs2" /> | ||||
|   <sodipodi:namedview | ||||
|      id="base" | ||||
|      pagecolor="#ffffff" | ||||
|      bordercolor="#666666" | ||||
|      borderopacity="1.0" | ||||
|      inkscape:pageopacity="0.0" | ||||
|      inkscape:pageshadow="2" | ||||
|      inkscape:zoom="4.3481303" | ||||
|      inkscape:cx="49.605183" | ||||
|      inkscape:cy="74.492628" | ||||
|      inkscape:document-units="mm" | ||||
|      inkscape:current-layer="layer1" | ||||
|      inkscape:document-rotation="0" | ||||
|      showgrid="true" | ||||
|      units="px" | ||||
|      inkscape:window-width="1920" | ||||
|      inkscape:window-height="950" | ||||
|      inkscape:window-x="0" | ||||
|      inkscape:window-y="27" | ||||
|      inkscape:window-maximized="1"> | ||||
|     <inkscape:grid | ||||
|        type="xygrid" | ||||
|        id="grid10" | ||||
|        spacingy="0.52916667" | ||||
|        spacingx="0.52916667" /> | ||||
|   </sodipodi:namedview> | ||||
|   <metadata | ||||
|      id="metadata5"> | ||||
|     <rdf:RDF> | ||||
|       <cc:Work | ||||
|          rdf:about=""> | ||||
|         <dc:format>image/svg+xml</dc:format> | ||||
|         <dc:type | ||||
|            rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | ||||
|         <dc:title></dc:title> | ||||
|       </cc:Work> | ||||
|     </rdf:RDF> | ||||
|   </metadata> | ||||
|   <g | ||||
|      inkscape:label="Ebene 1" | ||||
|      inkscape:groupmode="layer" | ||||
|      id="layer1"> | ||||
|     <path | ||||
|        sodipodi:type="star" | ||||
|        style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.529167;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers" | ||||
|        id="path863" | ||||
|        sodipodi:sides="3" | ||||
|        sodipodi:cx="23.8125" | ||||
|        sodipodi:cy="13.229166" | ||||
|        sodipodi:r1="2.6458333" | ||||
|        sodipodi:r2="1.3229167" | ||||
|        sodipodi:arg1="0" | ||||
|        sodipodi:arg2="1.0471976" | ||||
|        inkscape:flatsided="true" | ||||
|        inkscape:rounded="0" | ||||
|        inkscape:randomized="0" | ||||
|        d="m 26.458333,13.229166 -3.96875,2.291359 v -4.582718 z" | ||||
|        inkscape:transform-center-x="-0.66145805" /> | ||||
|   </g> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 2.4 KiB | 
							
								
								
									
										34
									
								
								js_client/assets/hint_vertical.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								js_client/assets/hint_vertical.svg
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | ||||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||
| <svg | ||||
|    xmlns:dc="http://purl.org/dc/elements/1.1/" | ||||
|    xmlns:cc="http://creativecommons.org/ns#" | ||||
|    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | ||||
|    xmlns:svg="http://www.w3.org/2000/svg" | ||||
|    xmlns="http://www.w3.org/2000/svg" | ||||
|    width="100" | ||||
|    height="100" | ||||
|    viewBox="0 0 26.458333 26.458334" | ||||
|    version="1.1" | ||||
|    id="svg8"> | ||||
|   <defs | ||||
|      id="defs2" /> | ||||
|   <metadata | ||||
|      id="metadata5"> | ||||
|     <rdf:RDF> | ||||
|       <cc:Work | ||||
|          rdf:about=""> | ||||
|         <dc:format>image/svg+xml</dc:format> | ||||
|         <dc:type | ||||
|            rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | ||||
|         <dc:title></dc:title> | ||||
|       </cc:Work> | ||||
|     </rdf:RDF> | ||||
|   </metadata> | ||||
|   <g | ||||
|      id="layer1"> | ||||
|     <path | ||||
|        style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.529167;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers" | ||||
|        id="path861" | ||||
|        d="m 13.229166,26.458333 -2.291359,-3.96875 4.582718,0 z" /> | ||||
|   </g> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 1.0 KiB | 
							
								
								
									
										23
									
								
								js_client/cookie.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								js_client/cookie.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | ||||
| 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=/"; | ||||
| } | ||||
|  | ||||
| export function getCookie(cname) { | ||||
|     var name = cname + "="; | ||||
|     var decodedCookie = decodeURIComponent(document.cookie); | ||||
|     var ca = decodedCookie.split(';'); | ||||
|     for (var i = 0; i < ca.length; i++) { | ||||
|         var c = ca[i]; | ||||
|         while (c.charAt(0) == ' ') { | ||||
|             c = c.substring(1); | ||||
|         } | ||||
|         if (c.indexOf(name) == 0) { | ||||
|             return c.substring(name.length, c.length); | ||||
|         } | ||||
|     } | ||||
|     return ""; | ||||
| } | ||||
|  | ||||
							
								
								
									
										772
									
								
								js_client/grid.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										772
									
								
								js_client/grid.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,772 @@ | ||||
| import { html, css, LitElement, unsafeCSS } from 'https://unpkg.com/lit-element/lit-element.js?module'; | ||||
| import './infoBox.js' | ||||
|  | ||||
| const gridType = { | ||||
|     EMPTY: 0, | ||||
|     HINT: 1, | ||||
|     LETTER: 2 | ||||
| }; | ||||
|  | ||||
| export class GridElement { | ||||
|     constructor(x, y, grid, type) { | ||||
|         this.x = x; | ||||
|         this.y = y; | ||||
|         this.type = type | ||||
|         this.grid = grid; | ||||
|  | ||||
|  | ||||
|         this.gridLetter = null; | ||||
|         this.hintBox = null; | ||||
|         this.emptyBox = null; | ||||
|     } | ||||
|  | ||||
|     setGridLetter(gridLetter) { | ||||
|         this.gridLetter = gridLetter; | ||||
|     } | ||||
|  | ||||
|     getGridLetter() { | ||||
|         return this.gridLetter; | ||||
|     } | ||||
|  | ||||
|     setHintBox(hintBox) { | ||||
|         this.hintBox = hintBox; | ||||
|     } | ||||
|  | ||||
|     getHintBox() { | ||||
|         return this.hintBox; | ||||
|     } | ||||
|  | ||||
|     setEmptyBox(emptyBox) { | ||||
|         this.emptyBox = emptyBox; | ||||
|     } | ||||
|  | ||||
|     getEmptyBox() { | ||||
|         return this.emptyBox; | ||||
|     } | ||||
|  | ||||
|     getGridType() { | ||||
|         return this.type; | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| export class GridBox extends LitElement { | ||||
|     static get styles() { | ||||
|         return css` | ||||
|             input[type='text'] { | ||||
|                 width: 1.5em; | ||||
|                 height: 1.5em; | ||||
|                 text-align: center; | ||||
|                 border-style: solid; | ||||
|                 border-color: black; | ||||
|                 border-width: 0.2 em; | ||||
|                 background-color: black; | ||||
|                 outline: none; | ||||
|                 color: transparent; | ||||
|                 text-shadow: 0 0 1 black; | ||||
|                 font-size: 2em; | ||||
|                 user-select: none; | ||||
|                 text-transform: uppercase; | ||||
|             } | ||||
|         `; | ||||
|     } | ||||
|  | ||||
|     static get properties() { | ||||
|         return { | ||||
|             x: { type: Number }, | ||||
|             y: { type: Number }, | ||||
|             grid_id: { type: String } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     constructor() { | ||||
|         super(); | ||||
|         this.x = 0; | ||||
|         this.y = 0; | ||||
|         this.gridElement = null; | ||||
|         this.grid_id = null; | ||||
|         this.crosswordGrid = null; | ||||
|         this.isRevealed = false; | ||||
|     } | ||||
|  | ||||
|     update(props) { | ||||
|         super.update(); | ||||
|         if (props.has("grid_id")) { | ||||
|             this.updateGridElement(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     updateGridElement() { | ||||
|         if (this.grid_id != null) { | ||||
|  | ||||
|             this.crosswordGrid = document.getElementById(this.grid_id); | ||||
|             this.gridElement = this.crosswordGrid.getGridElement(this.x, this.y); | ||||
|             this.gridElement.setEmptyBox(this); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     render() { | ||||
|         return html`<input type="text" id="${this.x}-${this.y}" maxlength="1" value="" disabled></input>`; | ||||
|     } | ||||
| } | ||||
|  | ||||
| customElements.define('grid-box', GridBox); | ||||
|  | ||||
|  | ||||
| export class GridLetter extends GridBox { | ||||
|     static get styles() { | ||||
|         return css` | ||||
|             input[type='text'] { | ||||
|                 width: 1.5em; | ||||
|                 height: 1.5em; | ||||
|                 text-align: center; | ||||
|                 border-style: solid; | ||||
|                 border-width: 0.2 em; | ||||
|                 border-color: black; | ||||
|                 outline: none; | ||||
|                 color: black; | ||||
|                 font-size: 2em; | ||||
|                 user-select: none; | ||||
|                 text-transform: capitalize; | ||||
|             } | ||||
|  | ||||
|             input[type='text']:focus { | ||||
|                 background-color: LightYellow; | ||||
|                 border-color: Yellow; | ||||
|  | ||||
|             } | ||||
|  | ||||
|             input[type='text']:read-only { | ||||
|                 background-color: LightGreen; | ||||
|             } | ||||
|  | ||||
|             input[type='text']:selection { | ||||
|                 background: transparent; | ||||
|             } | ||||
|         `; | ||||
|     } | ||||
|  | ||||
|     static get properties() { | ||||
|         return { | ||||
|             letter: { type: String }, | ||||
|             x: { type: Number }, | ||||
|             y: { type: Number }, | ||||
|             grid_id: { type: String } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     constructor() { | ||||
|         super(); | ||||
|         this._value = ''; | ||||
|         this.is_focused = false; | ||||
|         this.key_delay = false; | ||||
|         this.updateGridElement(); | ||||
|     } | ||||
|  | ||||
|  | ||||
|  | ||||
|     set value(value) { | ||||
|         const oldValue = this.value; | ||||
|         console.log("update value to: " + value); | ||||
|  | ||||
|         this._value = value; | ||||
|         this.requestUpdate('value', oldValue); | ||||
|     } | ||||
|  | ||||
|     get value() { | ||||
|         return this._value; | ||||
|     } | ||||
|  | ||||
|     onInput(e) { | ||||
|  | ||||
|         if (!this.is_focused) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         //if (this.key_delay){ | ||||
|         //    var el = this.shadowRoot.getElementById(`${this.x}-${this.y}`); | ||||
|         //    el.value = this.value; | ||||
|         //    el.select(); | ||||
|         //    e.handled = true; | ||||
|         //    return; | ||||
|         //} | ||||
|  | ||||
|         var oldVal = this.value; | ||||
|         this.value = e.target.value | ||||
|  | ||||
|         if (this.revealed) { | ||||
|             this.value = oldVal; | ||||
|             return | ||||
|         } | ||||
|  | ||||
|         if (this.value.length > 1) { | ||||
|             this.value = str.slice(0); | ||||
|             e.target.value = this.value | ||||
|             e.handled = true; | ||||
|         } | ||||
|  | ||||
|         if (!e.handled && this.value === " ") { | ||||
|             this.value = ""; | ||||
|             e.target.value = ""; | ||||
|             e.handled = true; | ||||
|         } | ||||
|  | ||||
|         if (!e.handled && this.value.length === 0) { | ||||
|             this.crosswordGrid.focusPrevCell(this.x, this.y); | ||||
|             e.handled = true; | ||||
|         } | ||||
|         else if (!e.handled && this.value.length === 1) { | ||||
|             this.crosswordGrid.focusNextCell(this.x, this.y); | ||||
|             e.handled = true; | ||||
|         } | ||||
|         else { | ||||
|             this.focus(); | ||||
|         } | ||||
|  | ||||
|         if (oldVal != this.value) { | ||||
|             this.crosswordGrid.sendMessage({ | ||||
|                 'type': 'update', | ||||
|                 'x': this.x, | ||||
|                 'y': this.y, | ||||
|                 'letter': this.value | ||||
|             }) | ||||
|         } | ||||
|  | ||||
|         if (!e.handled){ | ||||
|  | ||||
|             e.target.select(); | ||||
|  | ||||
|             e.handled = true; | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     onKeydown(e) { | ||||
|  | ||||
|         if (!this.is_focused) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         this.key_delay = false; | ||||
|  | ||||
|         var key = e.key; | ||||
|  | ||||
|         console.log(key); | ||||
|  | ||||
|  | ||||
|         if (this.value.length == 0) { | ||||
|             if (key === 'Backspace' || key === 'Delete') { | ||||
|                 this.crosswordGrid.focusPrevCell(this.x, this.y); | ||||
|                 e.handled = true; | ||||
|                 return | ||||
|  | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // check arrow keys | ||||
|         if (key === "ArrowLeft") { | ||||
|             // left | ||||
|             this.crosswordGrid.focusPrevCellHorizontal(this.x, this.y); | ||||
|             e.handled = true; | ||||
|             return; | ||||
|         } | ||||
|         else if (key === "ArrowUp") { | ||||
|             // up | ||||
|             this.crosswordGrid.focusPrevCellVertical(this.x, this.y); | ||||
|             e.handled = true; | ||||
|             return; | ||||
|  | ||||
|         } | ||||
|         else if (key === "ArrowRight") { | ||||
|             //right | ||||
|             this.crosswordGrid.focusNextCellHorizontal(this.x, this.y); | ||||
|             e.handled = true; | ||||
|             return; | ||||
|         } | ||||
|         else if (key === "ArrowDown") { | ||||
|             //down | ||||
|             this.crosswordGrid.focusNextCellVertical(this.x, this.y); | ||||
|             e.handled = true; | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|  | ||||
|  | ||||
|         e.target.select(); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     onFocus(e) { | ||||
|         e.target.select(); | ||||
|         this.is_focused = true; | ||||
|         this.key_delay = true; | ||||
|  | ||||
|         this.crosswordGrid.updateHints(this.x, this.y); | ||||
|     } | ||||
|  | ||||
|     focus() { | ||||
|         var element = this.shadowRoot.getElementById(`${this.x}-${this.y}`); | ||||
|         element.focus(); | ||||
|     } | ||||
|  | ||||
|     blur() { | ||||
|         var element = this.shadowRoot.getElementById(`${this.x}-${this.y}`); | ||||
|         element.blur(); | ||||
|         this.is_focused = false; | ||||
|     } | ||||
|  | ||||
|     updateGridElement() { | ||||
|         super.updateGridElement() | ||||
|  | ||||
|         if (this.grid_id != null) { | ||||
|  | ||||
|             this.gridElement.setGridLetter(this); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     updateLetter(letter, revealed) { | ||||
|         this.value = letter; | ||||
|         if (revealed) | ||||
|         { | ||||
|             console.log("rec") | ||||
|             this.shadowRoot.getElementById(`${this.x}-${this.y}`).readOnly = true; | ||||
|             this.blur(); | ||||
|             this.revealed = true; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     render() { | ||||
|         this.updateGridElement(); | ||||
|         return html`<input type="text" id="${this.x}-${this.y}" value="${this.value}" @input=${this.onInput} @focus=${this.onFocus} @keydown=${this.onKeydown} autocomplete="off"></input>`; | ||||
|     } | ||||
| } | ||||
|  | ||||
| customElements.define('grid-letter', GridLetter); | ||||
|  | ||||
|  | ||||
|  | ||||
| export class HintBox extends GridBox { | ||||
|  | ||||
|     static get styles() { | ||||
|  | ||||
|         return css` | ||||
|  | ||||
|             .hint { | ||||
|                 display: grid; | ||||
|             } | ||||
|              | ||||
|  | ||||
|             .triangle-down { | ||||
|                 position: relative; | ||||
|                 top: 3em; | ||||
|                 left: 1em; | ||||
|                 z-index: 10; | ||||
|                 grid-column: 1; | ||||
|                 grid-row: 1; | ||||
|                 width: 0; | ||||
|                 height: 0; | ||||
|                 border-left: 0.75em solid transparent; | ||||
|                 border-right: 0.75em solid transparent; | ||||
|                 border-top: 1.3em solid #555; | ||||
|                  | ||||
|             } | ||||
|  | ||||
|             .triangle-right { | ||||
|                 position: relative; | ||||
|                 top: 1em; | ||||
|                 left: 3em; | ||||
|                 z-index: 10; | ||||
|                 grid-column: 1; | ||||
|                 grid-row: 1; | ||||
|                 width: 0; | ||||
|                 height: 0; | ||||
|                 border-top: 0.75em solid transparent; | ||||
|                 border-bottom: 0.75em solid transparent; | ||||
|                 border-left: 1.3em solid #555; | ||||
|                  | ||||
|             } | ||||
|  | ||||
|             input[type='text']{ | ||||
|                 grid-column: 1; | ||||
|                 grid-row: 1; | ||||
|                 width: 1.5em; | ||||
|                 height: 1.5em; | ||||
|                 text-align: center; | ||||
|                 border-style: solid; | ||||
|                 border-color: black; | ||||
|                 border-width: 0.2 em; | ||||
|                 background-color: #555; | ||||
|                 outline: none; | ||||
|                 color: white; | ||||
|                 text-shadow: 0 0 1 black; | ||||
|                 font-size: 2em; | ||||
|                 user-select: none; | ||||
|                 text-transform: uppercase; | ||||
|             } | ||||
|         `; | ||||
|     } | ||||
|  | ||||
|     static get properties() { | ||||
|         return { | ||||
|             x: { type: Number }, | ||||
|             y: { type: Number }, | ||||
|             grid_id: { type: String }, | ||||
|             horizontal_hint: { type: String }, | ||||
|             vertical_hint: { type: String }, | ||||
|             hint_id: { type: String } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     constructor() { | ||||
|         super(); | ||||
|         this.vertical_hint = ""; | ||||
|         this.horizontal_hint = ""; | ||||
|         this.hint_id = 0; | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
|  | ||||
|     getVerticalHint() { | ||||
|         return this.vertical_hint; | ||||
|     } | ||||
|  | ||||
|     getHorizontalHint() { | ||||
|         return this.horizontal_hint; | ||||
|     } | ||||
|  | ||||
|     hasVerticalHint() { | ||||
|         return this.vertical_hint.length > 0; | ||||
|     } | ||||
|  | ||||
|     hasHorizontalHint() { | ||||
|         return this.horizontal_hint.length > 0; | ||||
|     } | ||||
|  | ||||
|     updateGridElement() { | ||||
|         super.updateGridElement() | ||||
|  | ||||
|         if (this.grid_id != null) { | ||||
|  | ||||
|             this.gridElement.setHintBox(this); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     render() { | ||||
|  | ||||
|         this.updateGridElement(); | ||||
|  | ||||
|         var verticalArrow = html``; | ||||
|         var horizontalArrow = html``; | ||||
|  | ||||
|         if (this.hasVerticalHint()) { | ||||
|             verticalArrow = html`<div class="triangle-down"></div>`; | ||||
|         } | ||||
|  | ||||
|         if (this.hasHorizontalHint()) { | ||||
|             horizontalArrow = html`<div class="triangle-right"></div>`; | ||||
|         } | ||||
|  | ||||
|         return html` | ||||
|         <div class="hint"> | ||||
|             <input type="text" id="${this.x}-${this.y}" value="${this.hint_id}" disabled></input> | ||||
|             ${verticalArrow} | ||||
|             ${horizontalArrow} | ||||
|         </div> | ||||
|         `; | ||||
|     } | ||||
| } | ||||
|  | ||||
| customElements.define('hint-box', HintBox); | ||||
|  | ||||
| export class CrosswordGrid extends LitElement { | ||||
|     static get styles() { | ||||
|         return css` | ||||
|             body { | ||||
|                 background-color: black; | ||||
|             } | ||||
|  | ||||
|             table { | ||||
|                 position: relative; | ||||
|                 top: 5em; | ||||
|                 border-spacing: 0px; | ||||
|                 border-style: solid; | ||||
|                 border-color: black; | ||||
|                 border-width: 1em; | ||||
|             } | ||||
|  | ||||
|             td { | ||||
|                 padding: 0px; | ||||
|             } | ||||
|         `; | ||||
|     } | ||||
|  | ||||
|     static get properties() { | ||||
|         return { | ||||
|             id: { type: String }, | ||||
|             width: { type: Number }, | ||||
|             height: { type: Number }, | ||||
|             infobox_id: {type: String} | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     constructor() { | ||||
|         super(); | ||||
|         this.width = 10; | ||||
|         this.height = 10; | ||||
|         this.grid = []; | ||||
|  | ||||
|         this.json_grid = null; | ||||
|  | ||||
|         this.num_hints = 0; | ||||
|  | ||||
|         this.lastMoveVertical = false; | ||||
|  | ||||
|         this.infobox = null; | ||||
|  | ||||
|         this.serverConnection = null; | ||||
|     } | ||||
|  | ||||
|     createGridByJson(json_grid) { | ||||
|         this.num_hints = 0; | ||||
|         this.json_grid = json_grid; | ||||
|         this.grid = []; | ||||
|         const width = json_grid.w; | ||||
|         const height = json_grid.h; | ||||
|  | ||||
|         var y; | ||||
|         var x; | ||||
|  | ||||
|         for (y = 0; y < height; y++) { | ||||
|             var row = []; | ||||
|             for (x = 0; x < width; x++) { | ||||
|                 const json_cell = json_grid.grid[y][x]; | ||||
|                 const cell_type = json_cell.cell_type; | ||||
|  | ||||
|                 switch (cell_type) { | ||||
|                     case "empty": { | ||||
|                         row.push(new GridElement(x, y, this, gridType.EMPTY)); | ||||
|                         break; | ||||
|                     } | ||||
|                     case "hint": { | ||||
|                         row.push(new GridElement(x, y, this, gridType.HINT)); | ||||
|                         break; | ||||
|                     } | ||||
|                     case "letter": { | ||||
|                         row.push(new GridElement(x, y, this, gridType.LETTER)); | ||||
|                         break; | ||||
|                     } | ||||
|  | ||||
|                 }; | ||||
|             } | ||||
|             this.grid.push(row); | ||||
|         } | ||||
|  | ||||
|         this.width = width; | ||||
|         this.height = height; | ||||
|     } | ||||
|  | ||||
|     focusNextCellHorizontal(x, y) { | ||||
|         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 + 1].getGridLetter().focus(); | ||||
|  | ||||
|  | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     focusPrevCellHorizontal(x, y) { | ||||
|         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 - 1].getGridLetter().focus(); | ||||
|  | ||||
|  | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     focusNextCellVertical(x, y) { | ||||
|         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 + 1][x].getGridLetter().focus(); | ||||
|  | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     focusPrevCellVertical(x, y) { | ||||
|         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 - 1][x].getGridLetter().focus(); | ||||
|  | ||||
|  | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     focusNextCell(x, y) { | ||||
|         if (this.lastMoveVertical) { | ||||
|             if (this.focusNextCellVertical(x, y)) { | ||||
|                 return; | ||||
|             } | ||||
|             if (this.focusNextCellHorizontal(x, y)) { | ||||
|                 this.lastMoveVertical = false; | ||||
|             } | ||||
|         } | ||||
|         else { | ||||
|             if (this.focusNextCellHorizontal(x, y)) { | ||||
|                 return; | ||||
|             } | ||||
|             if (this.focusNextCellVertical(x, y)) { | ||||
|                 this.lastMoveVertical = true; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     focusPrevCell(x, y) { | ||||
|         if (this.lastMoveVertical) { | ||||
|             if (this.focusPrevCellVertical(x, y)) { | ||||
|                 return; | ||||
|             } | ||||
|             if (this.focusPrevCellHorizontal(x, y)) { | ||||
|                 this.lastMoveVertical = false; | ||||
|             } | ||||
|         } | ||||
|         else { | ||||
|             if (this.focusPrevCellHorizontal(x, y)) { | ||||
|                 return; | ||||
|             } | ||||
|             if (this.focusPrevCellVertical(x, y)) { | ||||
|                 this.lastMoveVertical = true; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     getGridElement(x, y) { | ||||
|         return this.grid[y][x]; | ||||
|     } | ||||
|  | ||||
|     update(props) { | ||||
|         if (props.has("width") || props.has("height")) { | ||||
|             // | ||||
|         } | ||||
|         if (props.has("infobox_id")) { | ||||
|             this.infobox = document.getElementById(this.infobox_id); | ||||
|         } | ||||
|         super.update() | ||||
|     } | ||||
|  | ||||
|     updateHints(x,y) { | ||||
|         var cell = this.grid[y][x]; | ||||
|         if (cell.getGridType() != gridType.LETTER){ | ||||
|             console.error("cannot get hints for non letter cell"); | ||||
|         } | ||||
|  | ||||
|         //get horizontal hint: | ||||
|         var upper_end = cell; | ||||
|         while (upper_end.getGridType() === gridType.LETTER) { | ||||
|             upper_end = this.grid[upper_end.y - 1][x] | ||||
|         } | ||||
|  | ||||
|         var left_end = cell; | ||||
|         while (left_end.getGridType() === gridType.LETTER) { | ||||
|             left_end = this.grid[y][left_end.x - 1] | ||||
|         } | ||||
|  | ||||
|         var hHint = ""; | ||||
|         var vHint = ""; | ||||
|  | ||||
|         if (left_end.getGridType() === gridType.HINT) { | ||||
|             var box = left_end.getHintBox(); | ||||
|             hHint = `${box.hint_id}: ${box.horizontal_hint}`; | ||||
|         } | ||||
|  | ||||
|         if (upper_end.getGridType() === gridType.HINT) { | ||||
|             var box = upper_end.getHintBox() | ||||
|             vHint = `${box.hint_id}: ${box.vertical_hint}`; | ||||
|         } | ||||
|  | ||||
|         this.infobox.horizontal_hint = hHint; | ||||
|         this.infobox.vertical_hint = vHint; | ||||
|     } | ||||
|  | ||||
|     renderCell(el) { | ||||
|         switch (el.type) { | ||||
|             case gridType.LETTER: { | ||||
|                 return html`<grid-letter grid_id='${this.id}' x='${el.x}' y='${el.y}' ></grid-letter>`; | ||||
|  | ||||
|             } | ||||
|             case gridType.EMPTY: { | ||||
|                 return html`<grid-box grid_id='${this.id}' x='${el.x}' y='${el.y}' ></grid-box>`; | ||||
|  | ||||
|             } | ||||
|             case gridType.HINT: { | ||||
|                 var vertical_hint = this.json_grid.grid[el.y][el.x].vertical_hint; | ||||
|                 var horizontal_hint = this.json_grid.grid[el.y][el.x].horizontal_hint; | ||||
|  | ||||
|                 if (!vertical_hint){ | ||||
|                     vertical_hint = ""; | ||||
|                 } | ||||
|                 if (!horizontal_hint){ | ||||
|                     horizontal_hint = ""; | ||||
|                 } | ||||
|  | ||||
|                 this.num_hints += 1; | ||||
|  | ||||
|                 return html` | ||||
|                     <hint-box grid_id='${this.id}' x='${el.x}' y='${el.y}' horizontal_hint='${horizontal_hint}' vertical_hint='${vertical_hint}' hint_id=${this.num_hints}></hint-box> | ||||
|                 `; | ||||
|  | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     updateLetter(x,y,letter,revealed) { | ||||
|         var cell = this.grid[y][x]; | ||||
|         if (cell.getGridType() != gridType.LETTER){ | ||||
|             console.error("received bad message"); | ||||
|         } | ||||
|         cell.getGridLetter().updateLetter(letter, revealed) | ||||
|     } | ||||
|  | ||||
|     registerServerConnection(connection){ | ||||
|         this.serverConnection = connection | ||||
|     } | ||||
|  | ||||
|     sendMessage(msg){ | ||||
|         if (!this.serverConnection) { | ||||
|             console.error("no server connection registered") | ||||
|         } | ||||
|         this.serverConnection.sendMessage(msg) | ||||
|     } | ||||
|  | ||||
|     render() { | ||||
|         this.num_hints = 0; | ||||
|         console.log("refreshing grid"); | ||||
|         return html` | ||||
|             <table> | ||||
|                 ${this.grid.map((row) => html`<tr>${row.map((el) => html`<td>${this.renderCell(el)}</td>`)}</tr>`)} | ||||
|             </table> | ||||
|         `; | ||||
|     } | ||||
| } | ||||
|  | ||||
| customElements.define('crossword-grid', CrosswordGrid); | ||||
							
								
								
									
										20
									
								
								js_client/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								js_client/index.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | ||||
| <!doctype html> | ||||
| <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 | ||||
|        Chrome, Safari, Firefox 60, Edge 17 --> | ||||
|  | ||||
| </head> | ||||
|  | ||||
| <body style="background-color: black;"> | ||||
|     <info-box id="infobox"></info-box> | ||||
|     <server-connection id="server-connection" 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> | ||||
|  | ||||
| </html> | ||||
							
								
								
									
										55
									
								
								js_client/infoBox.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								js_client/infoBox.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,55 @@ | ||||
| import { html, css, LitElement, unsafeCSS } from 'https://unpkg.com/lit-element/lit-element.js?module'; | ||||
|  | ||||
| export class InfoBox extends LitElement { | ||||
|     static get styles() { | ||||
|         return css` | ||||
|             .hinttext { | ||||
|                 color: white; | ||||
|                 margin-left: 1em; | ||||
|                 margin-top: 0.8em; | ||||
|                  | ||||
|  | ||||
|             } | ||||
|  | ||||
|             .infobox { | ||||
|                 z-index: 20; | ||||
|                 position: fixed; | ||||
|                 top: 0em; | ||||
|                 left: 0em; | ||||
|                 right: 0em; | ||||
|                 height: 6em; | ||||
|  | ||||
|                 border-style: solid; | ||||
|                 border-color: white; | ||||
|                 border-width: 0.2 em; | ||||
|                 background-color: #333; | ||||
|                 color: white; | ||||
|             } | ||||
|         `; | ||||
|     } | ||||
|  | ||||
|     static get properties() { | ||||
|         return { | ||||
|             horizontal_hint: { type: String }, | ||||
|             vertical_hint: { type: String } | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     constructor() { | ||||
|         super(); | ||||
|         this.vertical_hint = ""; | ||||
|         this.horizontal_hint = ""; | ||||
|     } | ||||
|  | ||||
|     render() { | ||||
|         return html` | ||||
|             <div class="infobox"> | ||||
|                 <div class="hinttext">▶ ${this.horizontal_hint}</div> | ||||
|                 <div class="hinttext">▼ ${this.vertical_hint}</div> | ||||
|             </div> | ||||
|         `; | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| customElements.define('info-box', InfoBox); | ||||
							
								
								
									
										3
									
								
								js_client/main.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								js_client/main.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| import '/grid.js' | ||||
| import '/serverConnection.js' | ||||
|  | ||||
							
								
								
									
										12
									
								
								js_client/serve.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								js_client/serve.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| #!/usr/bin/env python3 | ||||
| from http.server import HTTPServer, SimpleHTTPRequestHandler, test | ||||
| import sys | ||||
|  | ||||
| class CORSRequestHandler (SimpleHTTPRequestHandler): | ||||
|     def end_headers (self): | ||||
|         self.send_header('Access-Control-Allow-Origin', '*') | ||||
|         SimpleHTTPRequestHandler.end_headers(self) | ||||
|  | ||||
| if __name__ == '__main__': | ||||
|     test(CORSRequestHandler, HTTPServer, port=int(sys.argv[1]) if len(sys.argv) > 1 else 8000) | ||||
|  | ||||
							
								
								
									
										141
									
								
								js_client/serverConnection.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								js_client/serverConnection.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,141 @@ | ||||
| import { html, css, LitElement } from 'https://unpkg.com/lit-element/lit-element.js?module'; | ||||
| import { WebsocketConnection } from '/websocket.js'; | ||||
| import { getCookie, setCookie } from '/cookie.js'; | ||||
|  | ||||
| export class ServerConnection extends WebsocketConnection { | ||||
|     static get styles() { | ||||
|         return css``; | ||||
|     } | ||||
|  | ||||
|     static get properties() { | ||||
|         return { | ||||
|             url: { type: String }, | ||||
|             grid_id: { type: String } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     constructor() { | ||||
|         super(); | ||||
|         this.sessionId = null; | ||||
|         this.isRegistered = false; | ||||
|         this.crossword_grid = null; | ||||
|     } | ||||
|  | ||||
|     update(props) { | ||||
|         if (props.has("grid_id")) { | ||||
|             this.crossword_grid = document.getElementById(this.grid_id); | ||||
|             this.crossword_grid.registerServerConnection(this); | ||||
|         } | ||||
|         super.update(props) | ||||
|     } | ||||
|  | ||||
|     updateLocalSessionId() { | ||||
|         // look whether the session id is given in url params | ||||
|         // or stored as cookie | ||||
|         const queryString = window.location.search; | ||||
|         const params = new URLSearchParams(queryString); | ||||
|         if (params.has('session')) { | ||||
|             this.sessionId = params.get('session'); | ||||
|             return; | ||||
|         } | ||||
|         const cookie_session = getCookie('session'); | ||||
|         if (cookie_session != "") { | ||||
|             this.sessionId = cookie_session; | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     register() { | ||||
|         this.updateLocalSessionId(); | ||||
|         console.log("register", this.sessionId); | ||||
|         this.sendMessage({ | ||||
|             'type': 'register', | ||||
|             'sessionId': this.sessionId | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     onopen(event) { | ||||
|         super.onopen(event); | ||||
|         console.log("overloaded", this); | ||||
|         this.register(); | ||||
|     } | ||||
|  | ||||
|     handleRegistration(sessionId) { | ||||
|         if (!sessionId) { | ||||
|             console.warn("got undefined session id"); | ||||
|             return; | ||||
|         } | ||||
|         this.sessionId = sessionId; | ||||
|         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')){ | ||||
|             return; | ||||
|         } | ||||
|         urlparams.set('session', sessionId); | ||||
|         var newurl = window.location.protocol + "//" + window.location.host + window.location.pathname + '?session=' + sessionId; | ||||
|         window.history.pushState({ path: newurl }, '', newurl); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     handleCrossword(crossword) { | ||||
|         this.crossword_grid.createGridByJson(crossword); | ||||
|     } | ||||
|  | ||||
|     handleUpdate(updates) { | ||||
|         var i = 0; | ||||
|         for (i = 0; i < updates.length; i++) { | ||||
|             const item = updates[i]; | ||||
|  | ||||
|             const x = item['x']; | ||||
|             const y = item['y']; | ||||
|  | ||||
|             if (item.hasOwnProperty("user_input")) { | ||||
|                 const letter = item['user_input']; | ||||
|                 this.crossword_grid.updateLetter(x, y, letter, false); | ||||
|             } | ||||
|             if (item.hasOwnProperty("revealed")) { | ||||
|                 console.log("update"); | ||||
|                 const letter = item['revealed']; | ||||
|                 this.crossword_grid.updateLetter(x, y, letter, true); | ||||
|             } | ||||
|  | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     onmessage(event) { | ||||
|         super.onmessage(event) | ||||
|         try { | ||||
|             const msg = JSON.parse(event.data); | ||||
|             if (!msg.type) { | ||||
|                 throw "missing type" | ||||
|             } | ||||
|             switch (msg.type) { | ||||
|                 case 'register': { | ||||
|                     this.handleRegistration(msg.sessionId); | ||||
|                     break; | ||||
|                 } | ||||
|                 case 'crossword': { | ||||
|                     this.handleCrossword(msg.crossword); | ||||
|                     break; | ||||
|                 } | ||||
|                 case 'update': { | ||||
|                     this.handleUpdate(msg.updates); | ||||
|                     break | ||||
|                 } | ||||
|  | ||||
|             } | ||||
|  | ||||
|         } | ||||
|         catch (err) { | ||||
|             console.error("could not parse servermessage", err); | ||||
|             return | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
|  | ||||
| customElements.define('server-connection', ServerConnection); | ||||
							
								
								
									
										88
									
								
								js_client/websocket.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								js_client/websocket.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,88 @@ | ||||
| import { html, css, LitElement } from 'https://unpkg.com/lit-element/lit-element.js?module'; | ||||
|  | ||||
| export class WebsocketConnection extends LitElement { | ||||
|     static get styles() { | ||||
|         return css``; | ||||
|     } | ||||
|  | ||||
|     static get properties() { | ||||
|         return { | ||||
|             url: { type: String } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     constructor() { | ||||
|         super(); | ||||
|  | ||||
|         this.url = ''; | ||||
|         this.socket = null; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     onopen(event){ | ||||
|         console.log("websocket connected"); | ||||
|     } | ||||
|  | ||||
|     onclose(event){ | ||||
|         console.log("websocket closed"); | ||||
|     } | ||||
|  | ||||
|     onerror(event){ | ||||
|         console.log("websocket error, closing..."); | ||||
|         if (this.socket && this.socket.readyState === WebSocket.OPEN) { | ||||
|             this.socket.close(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     onmessage(event){ | ||||
|         console.log("received message:", event.data); | ||||
|     } | ||||
|  | ||||
|     isSocketConnected(){ | ||||
|         if (! this.socket){ | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         if (this.socket.readyState === WebSocket.OPEN) { | ||||
|             return true; | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     sendMessage(msg){ | ||||
|          | ||||
|         if (this.isSocketConnected()) { | ||||
|             var string_msg = JSON.stringify(msg); | ||||
|             this.socket.send(string_msg); | ||||
|         } | ||||
|         else { | ||||
|             console.error("cannot send message, websocket disconnected"); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     connect() { | ||||
|         console.log(`connect to ${this.url}...`); | ||||
|         this.socket = new WebSocket(this.url); | ||||
|         this.socket.onopen = (event) => this.onopen(event); | ||||
|         this.socket.onclose = (event) => this.onclose(event); | ||||
|         this.socket.onerror = (event) => this.onerror(event); | ||||
|         this.socket.onmessage = (event) => this.onmessage(event); | ||||
|     } | ||||
|  | ||||
|     update(props) { | ||||
|         if (props.has("url")){ | ||||
|             this.connect(); | ||||
|         } | ||||
|         super.update(props); | ||||
|     } | ||||
|  | ||||
|  | ||||
|  | ||||
|     render() { | ||||
|         // do nothing | ||||
|         return html``; | ||||
|     } | ||||
| } | ||||
|  | ||||
| customElements.define('websocket-connection', WebsocketConnection); | ||||
		Reference in New Issue
	
	Block a user