Vitalii Polishchuk 3 anni fa
parent
commit
3f5388655b
3 ha cambiato i file con 230 aggiunte e 0 eliminazioni
  1. 99 0
      js/13-js-chat/css/main.css
  2. 36 0
      js/13-js-chat/index.html
  3. 95 0
      js/13-js-chat/js/main.js

+ 99 - 0
js/13-js-chat/css/main.css

@@ -0,0 +1,99 @@
+.chat {
+    display: flex;
+    flex-direction: column-reverse;
+}
+
+#chatInterface {
+    display: flex;
+    align-items: center;
+    margin: 20px;
+    font-size: 16px;
+    font-family: "Roboto", sans-serif;
+}
+
+#chatWindow {
+    display: flex;
+    flex-direction: column;
+    width: 60vw;
+    height: 80vh;
+    background-color: rgb(235, 233, 233);
+    border: 1px solid #99a3ba;
+    margin-bottom: 15px;
+    overflow-y: scroll;
+    overflow-x: hidden;
+}
+
+#chatWindow div {
+    display: flex;
+    flex-direction: column;
+    border: 1px solid rgb(185, 185, 185);
+    max-width: fit-content;
+    padding: 10px;
+    margin: 10px;
+    border-radius: 15px 15px 15px 0px;
+    background-color: #fff;
+}
+
+#chatWindow div span:first-child {
+    font-weight: bold;
+}
+
+#chatWindow div span:last-child {
+    margin-top: 10px;
+    font-size: 12px;
+}
+
+.nickname,
+.message {
+    position: relative;
+}
+
+label {
+    position: absolute;
+    top: 12%;
+    left: 5%;
+    color: rgba(8, 8, 8, 0.4);
+    transition: all 0.5s ease-in-out;
+}
+
+input:focus ~ label,
+input:valid ~ label {
+    top: -40%;
+    font-size: 12px;
+}
+
+input {
+    padding: 5px 15px;
+    margin-right: 10px;
+}
+
+input[type="text"] {
+    border: 2px solid #99a3ba;
+    border-radius: 8px;
+    outline: none;
+}
+
+input[type="text"]:focus {
+    box-shadow: 0 0 3px 1px rgb(163, 186, 199);
+}
+
+#btn {
+    width: 70px;
+    height: 30px;
+    font-weight: bold;
+    color: #fff;
+    border: none;
+    border-radius: 8px;
+    background-color: #99a3ba;
+    transition: 0.3s ease-in-out;
+}
+
+#btn:hover {
+    background-color: #798cb6;
+    transform: scale(1.05);
+}
+
+#btn:active {
+    background-color: #607cb8;
+    transform: scale(0.95);
+}

+ 36 - 0
js/13-js-chat/index.html

@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+    <meta charset="UTF-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>CHAT</title>
+    <link rel="stylesheet" href="css/main.css">
+    <link rel="preconnect" href="https://fonts.googleapis.com">
+    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+    <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;500&display=swap" rel="stylesheet">
+</head>
+
+<body>
+
+    <div class="chat">
+        <div id="chatInterface">
+            <div class="nickname">
+                <input id="nick" type="text" required>
+                <label for="nick">Nickname</label>
+            </div>
+            <div class="message">
+                <input id="msg" type="text" required>
+                <label for="msg">Message</label>
+            </div>
+            <input id="btn" type="button" value="SEND">
+        </div>
+
+        <div id="chatWindow"></div>
+    </div>
+
+    <script src="js/main.js"></script>
+</body>
+
+</html>

+ 95 - 0
js/13-js-chat/js/main.js

@@ -0,0 +1,95 @@
+//stage 0 - 4
+function jsonPost(url, data) {
+    return new Promise((resolve, reject) => {
+        var x = new XMLHttpRequest();
+        x.onerror = () => reject(new Error('jsonPost failed'))
+        //         //x.setRequestHeader('Content-Type', 'application/json');
+        x.open("POST", url, true);
+        x.send(JSON.stringify(data))
+
+        x.onreadystatechange = () => {
+            if (x.readyState == XMLHttpRequest.DONE && x.status == 200) {
+                resolve(JSON.parse(x.responseText))
+            }
+            else if (x.status != 200) {
+                reject(new Error('status is not 200'))
+            }
+        }
+    })
+}
+
+let timeConverter = timestamp => {
+    let date = new Date(timestamp);
+    let optionsDate = { year: "numeric", month: 'long', day: 'numeric' }
+    let optionsTime = { hour: '2-digit', minute: '2-digit' }
+    let convertedDate = date.toLocaleDateString("ua-UA", optionsDate) + "  " + date.toLocaleTimeString("ua-UA", optionsTime)
+
+    return convertedDate;
+}
+
+let updateScroll = () => {
+    setTimeout(() => chatWindow.scrollTop = chatWindow.scrollHeight, 350)
+}
+
+btn.onclick = e => {
+    if (nick.value !== "" && msg.value !== "") {
+        jsonPost("http://students.a-level.com.ua:10012", { func: 'addMessage', nick: nick.value, message: msg.value })
+
+        msg.value = ""
+    }
+}
+
+let msgId = 0;
+
+let chatWindowShower = () => {
+    jsonPost("http://students.a-level.com.ua:10012", { func: "getMessages", messageId: msgId })
+        .then(json => {
+
+            if (json.nextMessageId !== msgId) {
+                updateScroll()
+                msgId = json.nextMessageId;
+            }
+
+            for (let key of json.data) {
+                let div = document.createElement("div");
+                let spanNick = document.createElement("span");
+                let spanMsg = document.createElement("span");
+                let spanDate = document.createElement("span");
+                spanNick.innerText = key.nick;
+                spanMsg.innerText = key.message;
+                spanDate.innerText = timeConverter(key.timestamp);
+
+                div.append(spanNick, spanMsg, spanDate)
+
+                chatWindow.append(div)
+            }
+        })
+}
+
+setInterval(chatWindowShower, 2000)
+
+//stage 5
+async function sendMessage(nick, message) {
+
+}
+
+async function getMessages() {
+
+}
+
+async function sendAndCheck() {
+
+}
+
+async function checkLoop() {
+
+}
+
+//stage 6
+/*
+async function jsonPost(url, data) {
+    const response = await fetch(url, { method: 'POST', body: JSON.stringify(data) });
+    let result = await response.json()
+    return result;
+}
+*/