]> git.lizzy.rs Git - dragonblocks.git/blob - engine/chat.js
Refactor DOM handling of dragonblocks.Chat
[dragonblocks.git] / engine / chat.js
1 /*
2  * chat.js
3  *
4  * Copyright 2020 Elias Fleckenstein <eliasfleckenstein@web.de>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  * MA 02110-1301, USA.
20  *
21  *
22  */
23
24 dragonblocks.Chat = class
25 {
26         constructor()
27         {
28                 this.input = [""];
29                 this.history = -1;
30                 this.lines = dragonblocks.settings.chat.lines;
31
32                 this.initGraphics();
33                 this.clear();
34
35                 dragonblocks.keyHandler.down("t", _ => {
36                         dragonblocks.chat.open();
37                 });
38
39                 dragonblocks.keyHandler.down("/", event => {
40                         dragonblocks.chat.open();
41                         this.inputDisplay.value = "/";
42                 });
43         }
44
45         initGraphics()
46         {
47                 this.display = document.body.appendChild(document.createElement("div"));
48                 this.display.style.position = "fixed";
49                 this.display.style.top = "0px";
50                 this.display.style.left = "0px";
51                 this.display.style.backgroundColor = "black";
52                 this.display.style.opacity = "0.7";
53                 this.display.style.height = 23 * this.lines + "px";
54                 this.display.style.fontSize = "20px";
55                 this.display.style.color = "white";
56                 this.display.style.width = "100%";
57                 this.display.style.fontFamily = "monospace";
58                 this.display.style.overflowY = "scroll";
59                 this.display.style.scrollbarWidth = "none";
60                 this.display.style.visibility = "hidden";
61
62                 this.inputDisplay = document.body.appendChild(document.createElement("input"));
63                 this.inputDisplay.style.position = "fixed";
64                 this.inputDisplay.style.top = 23 * this.lines + "px";
65                 this.inputDisplay.style.left = "0px";
66                 this.inputDisplay.style.backgroundColor = "black";
67                 this.inputDisplay.style.border = "none";
68                 this.inputDisplay.style.outline = "none";
69                 this.inputDisplay.style.opacity = "0.7";
70                 this.inputDisplay.style.fontSize = "20px";
71                 this.inputDisplay.style.color = "white";
72                 this.inputDisplay.style.height = "23px";
73                 this.inputDisplay.style.width = "100%";
74                 this.inputDisplay.style.caretWidth = "30px";
75                 this.inputDisplay.style.caretHeight = "20px";
76                 this.inputDisplay.style.fontFamily = "monospace";
77                 this.inputDisplay.style.visibility = "hidden";
78
79                 let self = this;
80
81                 this.inputDisplay.addEventListener("keydown", event => {
82                         switch (event.key) {
83                                 case "Enter":
84                                         let message = self.inputDisplay.value;
85                                         event.srcElement.value = "";
86
87                                         if (message == "")
88                                                 return;
89
90                                         self.input[self.input.length - 1] = message;
91                                         self.send(message);
92                                         self.input.push("");
93
94                                         self.history = -1;
95                                         break;
96
97                                 case "Escape":
98                                         self.close();
99                                         break;
100
101                                 case "ArrowUp":
102                                         self.inputDisplay.value = self.historyUp();
103                                         break;
104
105                                 case "ArrowDown":
106                                         self.inputDisplay.value = self.historyDown();
107                                         break;
108                         }
109                 });
110
111                 this.inputDisplay.addEventListener("input", event => {
112                         self.input[self.input.length - 1] = self.inputDisplay;
113                 });
114         }
115
116         open()
117         {
118                 dragonblocks.keyHandler.lockAll();
119
120                 this.display.style.visibility = "visible";
121                 this.inputDisplay.style.visibility = "visible";
122                 this.inputDisplay.focus();
123         }
124
125         close()
126         {
127                 setTimeout(_ => {
128                         dragonblocks.keyHandler.unlockAll();
129                 });
130
131                 this.display.style.visibility = "hidden";
132                 this.inputDisplay.style.visibility = "hidden";
133                 this.inputDisplay.blur();
134         }
135
136         write(text)
137         {
138                 text = text || "";
139
140                 if (text.startsWith("!HTML"))
141                         text = text.replace("!HTML", "");
142                 else
143                         text = dblib.htmlEntities(text);
144
145                 text += "<br>";
146
147                 this.display.innerHTML += text;
148                 this.display.lastChild.scrollIntoView();
149         }
150
151         send(input)
152         {
153                 for (let func of dragonblocks.onChatMessageCallbacks)
154                         if (func(input) == false)
155                                 return false;
156
157                 this.write(input);
158         }
159
160         historyUp()
161         {
162                 this.history--;
163
164                 if (this.input[this.input.length + this.history] == undefined)
165                         this.history++;
166
167                 return this.input[this.input.length + this.history];
168         }
169
170         historyDown()
171         {
172                 this.history++;
173
174                 if (this.input[this.input.length + this.history] == undefined)
175                         this.history--;
176
177                 return this.input[this.input.length + this.history];
178         }
179
180         clear()
181         {
182                 this.display.innerHTML = "<br>".repeat(this.lines);
183         }
184 };
185
186 dragonblocks.chat = new dragonblocks.Chat();
187
188 dragonblocks.chatMessage = msg => {
189         dragonblocks.chat.write(msg);
190 };
191
192 dragonblocks.onChatMessageCallbacks = [];
193
194 dragonblocks.registerOnChatMessage = func => {
195         dragonblocks.onChatMessageCallbacks.push(func);
196 };