diff --git a/js/websocket/demos/example/index.html b/js/websocket/demos/example/index.html index 06065de2ee..3b6fbeb5c5 100644 --- a/js/websocket/demos/example/index.html +++ b/js/websocket/demos/example/index.html @@ -36,9 +36,19 @@ max-width: 480px; display: flex; flex-direction: column; - gap: 20px; + gap: 16px; } + /* Строка с адресом сервера */ + + .server-url { + font-family: monospace; + font-size: 14px; + color: #FFD829; + } + + /* Индикатор состояния соединения */ + .status { display: flex; align-items: center; @@ -50,6 +60,7 @@ } .status-dot { + flex-shrink: 0; width: 10px; height: 10px; border-radius: 50%; @@ -84,11 +95,84 @@ font-size: 14px; } - .status-code { + .status-ready-state { font-family: monospace; + color: rgb(255 255 255 / 0.5); + } + + .handshake { + display: flex; + flex-direction: column; + gap: 10px; + padding: 14px 16px; + border: 1px solid rgb(255 255 255 / 0.12); + border-radius: 10px; + background-color: #282A2E; + transition: border-color 0.3s ease; + } + + .handshake[data-active="true"] { + border-color: rgb(255 216 41 / 0.35); + } + + .handshake-title { + font-size: 13px; + font-weight: 500; + color: rgb(255 255 255 / 0.4); + transition: color 0.3s ease; + } + + .handshake[data-active="true"] .handshake-title { color: #FFD829; } + .handshake-step { + display: flex; + flex-direction: column; + gap: 4px; + } + + .handshake-step-label { + font-size: 12px; + color: rgb(255 255 255 / 0.4); + } + + .handshake-step pre { + margin: 0; + padding: 10px 12px; + overflow-x: auto; + border-radius: 6px; + background-color: #18191C; + font-family: monospace; + font-size: 12px; + line-height: 1.5; + color: rgb(255 255 255 / 0.3); + transition: color 0.3s ease; + } + + /* Активный, ещё не полученный шаг — мигает, привлекает внимание */ + .handshake-step.is-pending pre { + color: rgb(255 216 41 / 0.5); + animation: blink 1s ease-in-out infinite; + } + + /* Шаг получен во время текущего (ещё живого) рукопожатия — зелёный */ + .handshake[data-active="true"] .handshake-step.is-received pre { + color: #58E28C; + } + + /* Рукопожатие когда-то прошло, но уже не актуально — просто приглушённый след */ + .handshake[data-active="false"] .handshake-step.is-received pre { + color: rgb(255 255 255 / 0.4); + } + + .handshake-note { + font-size: 12px; + color: rgb(255 255 255 / 0.4); + } + + /* Кнопки управления */ + .controls { display: flex; gap: 10px; @@ -96,11 +180,18 @@ .message-row { display: flex; + align-items: flex-start; gap: 10px; } - input[type="text"] { + .message-field { flex-grow: 1; + display: flex; + flex-direction: column; + gap: 2px; + } + + input[type="text"] { padding: 10px 14px; border: 1px solid rgb(255 255 255 / 0.12); border-radius: 8px; @@ -115,6 +206,21 @@ outline-offset: -1px; } + input[type="text"]:disabled { + color: rgb(255 255 255 / 0.3); + } + + .message-counter { + align-self: flex-end; + font-family: monospace; + font-size: 10px; + color: rgb(255 255 255 / 0.35); + } + + .message-counter.is-near-limit { + color: #F498AD; + } + button { padding: 10px 16px; border: none; @@ -143,8 +249,10 @@ color: #FFFFFF; } + /* Журнал событий */ + .log { - height: 220px; + height: 200px; padding: 14px 16px; overflow-y: auto; border: 1px solid rgb(255 255 255 / 0.12); @@ -155,6 +263,10 @@ line-height: 1.6; } + .log-placeholder { + color: rgb(255 255 255 / 0.3); + } + .log-entry { color: rgb(255 255 255 / 0.6); } @@ -171,6 +283,39 @@ color: #F498AD; } + .legend { + display: flex; + flex-wrap: wrap; + gap: 6px 16px; + font-size: 12px; + color: rgb(255 255 255 / 0.5); + } + + .legend-item { + display: flex; + align-items: center; + gap: 6px; + } + + .legend-dot { + flex-shrink: 0; + width: 8px; + height: 8px; + border-radius: 50%; + } + + .legend-dot.sent { + background-color: #FFD829; + } + + .legend-dot.received { + background-color: #58E28C; + } + + .legend-dot.error { + background-color: #F498AD; + } + @media (width <= 480px) { body { padding: 24px; @@ -190,9 +335,28 @@
-
+
wss://echo.websocket.org
+ +
- Не подключено + Не подключено + +
+ +
+
Рукопожатие: HTTP-запрос на переключение протокола
+ +
+ Клиент → сервер +
— ждём подключения —
+
+ +
+ Сервер → клиент +
— ждём подключения —
+
+ +
Значения заголовков иллюстративные: браузер формирует их сам и не отдаёт в JavaScript, поэтому увидеть настоящие можно только во вкладке «Сеть» инструментов разработчика.
@@ -201,112 +365,213 @@
- +
+ + 0 / 200 +
-
+
+ Здесь появятся события соединения +
+ +
+ Отправлено клиентом + Получено от сервера + Ошибка или закрытие +
diff --git a/js/websocket/index.md b/js/websocket/index.md index c02c9b2e6b..37a290b66b 100644 --- a/js/websocket/index.md +++ b/js/websocket/index.md @@ -28,7 +28,7 @@ tags: `WebSocket` — браузерный API для постоянного соединения с сервером. Клиент и сервер обмениваются данными в реальном времени, клиенту не нужно постоянно отправлять HTTP-запросы. - +