From 96e160d7ee00706d2ea4477509cc7a0d053e8439 Mon Sep 17 00:00:00 2001 From: m-sato Date: Wed, 30 Sep 2026 14:06:13 +0900 Subject: [PATCH 1/6] =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=BD=A2=E3=81=AE=20scri?= =?UTF-8?q?pt.js=20=E3=81=8B=E3=82=89=E3=80=81=E3=82=B9=E3=83=A9=E3=82=A4?= =?UTF-8?q?=E3=83=89=E3=81=A7=E6=B6=88=E3=81=97=E3=81=9F=E6=97=A73?= =?UTF-8?q?=E7=AB=A0=E5=BF=9C=E7=94=A8=E8=AA=B2=E9=A1=8C=E3=81=AE=E6=8A=95?= =?UTF-8?q?=E7=A8=BF=E5=A4=B1=E6=95=97=E6=99=82=E3=81=AE=20alert=20?= =?UTF-8?q?=E3=82=92=E5=A4=96=E3=81=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 2026/board-advanced/completed/public/script.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/2026/board-advanced/completed/public/script.js b/2026/board-advanced/completed/public/script.js index b2c92058..db23df49 100644 --- a/2026/board-advanced/completed/public/script.js +++ b/2026/board-advanced/completed/public/script.js @@ -36,18 +36,12 @@ async function addPost() { const name = document.getElementById('name-input').value; const text = document.getElementById('text-input').value; - const res = await fetch(`${API}/posts`, { + await fetch(`${API}/posts`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: name, text: text }), }); - if (!res.ok) { - const { message } = await res.json(); - alert(message); - return; - } - document.getElementById('text-input').value = ''; } From fe53bde522f3d600400dcd2327aed63a45968489 Mon Sep 17 00:00:00 2001 From: m-sato Date: Wed, 30 Sep 2026 14:06:23 +0900 Subject: [PATCH 2/6] =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=BD=A2=E3=81=AE=20extr?= =?UTF-8?q?a.js=20=E3=81=AB2=E7=AB=A0=E3=81=AE=E5=BF=9C=E7=94=A8=E8=AA=B2?= =?UTF-8?q?=E9=A1=8C=E3=81=AE=E7=AD=94=E3=81=88=E3=82=92=E5=85=A5=E3=82=8C?= =?UTF-8?q?=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 2026/board-advanced/completed/public/extra.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/2026/board-advanced/completed/public/extra.js b/2026/board-advanced/completed/public/extra.js index 94998966..b42d17cb 100644 --- a/2026/board-advanced/completed/public/extra.js +++ b/2026/board-advanced/completed/public/extra.js @@ -3,6 +3,25 @@ // script.js のあとに読み込むので、script.js の source や posts をそのまま使える。 // このファイルが途中で止まっても、script.js は動き続ける。 +// 2章の応用課題: 見ていない間に届いた件数をタブに出す +const title = document.title; +let unread = 0; + +function countUnread() { + if (!document.hidden) return; + unread = unread + 1; + document.title = `(${unread}) ${title}`; +} +function resetTitle() { + if (document.hidden) return; + unread = 0; + document.title = title; +} + +source.addEventListener('message', countUnread); +document.addEventListener('visibilitychange', resetTitle); + +// 4章の応用課題: 接続状態を画面に出す const status = document.getElementById('status'); function showOnline() { From 7cbebbfae20d71b512a65340ff0c90985a2fcf65 Mon Sep 17 00:00:00 2001 From: m-sato Date: Wed, 30 Sep 2026 14:06:29 +0900 Subject: [PATCH 3/6] =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=BD=A2=E3=81=AE=20extr?= =?UTF-8?q?a.js=20=E3=81=AB3=E7=AB=A0=E3=81=AE=E5=BF=9C=E7=94=A8=E8=AA=B2?= =?UTF-8?q?=E9=A1=8C=E3=81=AE=E7=AD=94=E3=81=88=E3=82=92=E5=85=A5=E3=82=8C?= =?UTF-8?q?=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 2026/board-advanced/completed/public/extra.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/2026/board-advanced/completed/public/extra.js b/2026/board-advanced/completed/public/extra.js index b42d17cb..8bad32a5 100644 --- a/2026/board-advanced/completed/public/extra.js +++ b/2026/board-advanced/completed/public/extra.js @@ -21,6 +21,17 @@ function resetTitle() { source.addEventListener('message', countUnread); document.addEventListener('visibilitychange', resetTitle); +// 3章の応用課題: 名前を呼ばれたら知らせる +function notifyMention(e) { + const post = JSON.parse(e.data); + const me = document.getElementById('name-input').value; + if (me === '' || post.name === me) return; + if (!post.text.includes(me)) return; + alert(`${post.name}さんに呼ばれました: ${post.text}`); +} + +source.addEventListener('message', notifyMention); + // 4章の応用課題: 接続状態を画面に出す const status = document.getElementById('status'); From 09ac5c359912aeb81ed123ef439c65ee2da4c14f Mon Sep 17 00:00:00 2001 From: m-sato Date: Wed, 30 Sep 2026 14:06:37 +0900 Subject: [PATCH 4/6] =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=BD=A2=E3=81=AE=20serv?= =?UTF-8?q?er.js=20=E3=81=AB5=E7=AB=A0=E3=81=AE=E5=BF=9C=E7=94=A8=E8=AA=B2?= =?UTF-8?q?=E9=A1=8C1=E3=81=AE=E3=83=8F=E3=83=BC=E3=83=88=E3=83=93?= =?UTF-8?q?=E3=83=BC=E3=83=88=E3=82=92=E5=85=A5=E3=82=8C=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 2026/board-advanced/completed/server.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/2026/board-advanced/completed/server.js b/2026/board-advanced/completed/server.js index 6315d0c9..a8bf3d1e 100644 --- a/2026/board-advanced/completed/server.js +++ b/2026/board-advanced/completed/server.js @@ -17,6 +17,14 @@ const posts = []; // 現在の接続の一覧。接続した順に並ぶ。 const connections = []; +// 15 秒ごとにコメント行を送り、データが流れない接続が切られないようにする +function sendPing() { + for (let i = 0; i < connections.length; i++) { + connections[i].write(': ping\n\n'); + } +} +setInterval(sendPing, 15000); + const server = createServer(async (req, res) => { const url = new URL(req.url, `http://${req.headers.host}`); From 770b9c8d126851f803537b2177fd2040674ef9cc Mon Sep 17 00:00:00 2001 From: m-sato Date: Wed, 30 Sep 2026 14:06:43 +0900 Subject: [PATCH 5/6] =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=BD=A2=E3=81=AE=20serv?= =?UTF-8?q?er.js=20=E3=81=AB5=E7=AB=A0=E3=81=AE=E5=BF=9C=E7=94=A8=E8=AA=B2?= =?UTF-8?q?=E9=A1=8C2=E3=81=AE=E7=A9=BA=E3=81=AE=E6=8A=95=E7=A8=BF?= =?UTF-8?q?=E3=82=92=E5=8F=97=E3=81=91=E4=BB=98=E3=81=91=E3=81=AA=E3=81=84?= =?UTF-8?q?=E5=87=A6=E7=90=86=E3=82=92=E5=85=A5=E3=82=8C=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 2026/board-advanced/completed/server.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/2026/board-advanced/completed/server.js b/2026/board-advanced/completed/server.js index a8bf3d1e..a57902b7 100644 --- a/2026/board-advanced/completed/server.js +++ b/2026/board-advanced/completed/server.js @@ -53,6 +53,11 @@ const server = createServer(async (req, res) => { // 投稿を 1 件受け取る if (req.method === 'POST' && url.pathname === '/posts') { const post = await readPost(req); + if (post.text === '') { + res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' }); + res.end(JSON.stringify({ message: 'text が空です' })); + return; + } posts.push(post); if (posts.length > MAX_POSTS) posts.shift(); From cbde05cdf6414062e6d2b6962a4126a45f5f08bd Mon Sep 17 00:00:00 2001 From: m-sato Date: Wed, 30 Sep 2026 14:06:52 +0900 Subject: [PATCH 6/6] =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=BD=A2=E3=81=AB5?= =?UTF-8?q?=E7=AB=A0=E3=81=AE=E5=BF=9C=E7=94=A8=E8=AA=B2=E9=A1=8C3?= =?UTF-8?q?=E3=81=AE=E6=8E=A5=E7=B6=9A=E6=95=B0=E3=82=92=E5=85=A8=E5=93=A1?= =?UTF-8?q?=E3=81=AB=E9=80=81=E3=81=A3=E3=81=A6=E7=94=BB=E9=9D=A2=E3=81=AB?= =?UTF-8?q?=E5=87=BA=E3=81=99=E5=87=A6=E7=90=86=E3=82=92=E5=85=A5=E3=82=8C?= =?UTF-8?q?=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 2026/board-advanced/completed/public/extra.js | 7 +++++++ 2026/board-advanced/completed/public/index.html | 1 + 2026/board-advanced/completed/server.js | 9 +++++++++ 3 files changed, 17 insertions(+) diff --git a/2026/board-advanced/completed/public/extra.js b/2026/board-advanced/completed/public/extra.js index 8bad32a5..241099b9 100644 --- a/2026/board-advanced/completed/public/extra.js +++ b/2026/board-advanced/completed/public/extra.js @@ -46,3 +46,10 @@ function showOffline() { source.addEventListener('open', showOnline); source.addEventListener('error', showOffline); + +// 5章の応用課題3: 接続数を画面に出す +function showCount(e) { + document.getElementById('count').textContent = `${e.data}人が接続中`; +} + +source.addEventListener('count', showCount); diff --git a/2026/board-advanced/completed/public/index.html b/2026/board-advanced/completed/public/index.html index 3cba6187..e7cf62d5 100644 --- a/2026/board-advanced/completed/public/index.html +++ b/2026/board-advanced/completed/public/index.html @@ -18,6 +18,7 @@

みんなの掲示板

みんなの投稿

+ —
diff --git a/2026/board-advanced/completed/server.js b/2026/board-advanced/completed/server.js index a57902b7..08c33caf 100644 --- a/2026/board-advanced/completed/server.js +++ b/2026/board-advanced/completed/server.js @@ -25,6 +25,13 @@ function sendPing() { } setInterval(sendPing, 15000); +// いまの接続数を、接続している全員に送る +function sendCount() { + for (let i = 0; i < connections.length; i++) { + connections[i].write(`event: count\ndata: ${connections.length}\n\n`); + } +} + const server = createServer(async (req, res) => { const url = new URL(req.url, `http://${req.headers.host}`); @@ -41,10 +48,12 @@ const server = createServer(async (req, res) => { res.flushHeaders(); connections.push(res); console.log(`接続数: ${connections.length}`); + sendCount(); function removeConnection() { connections.splice(connections.indexOf(res), 1); console.log(`接続数: ${connections.length}`); + sendCount(); } req.on('close', removeConnection); return;