diff --git a/2026/board-advanced/completed/public/extra.js b/2026/board-advanced/completed/public/extra.js index 94998966..241099b9 100644 --- a/2026/board-advanced/completed/public/extra.js +++ b/2026/board-advanced/completed/public/extra.js @@ -3,6 +3,36 @@ // 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); + +// 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'); function showOnline() { @@ -16,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/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 = ''; } diff --git a/2026/board-advanced/completed/server.js b/2026/board-advanced/completed/server.js index 6315d0c9..08c33caf 100644 --- a/2026/board-advanced/completed/server.js +++ b/2026/board-advanced/completed/server.js @@ -17,6 +17,21 @@ const posts = []; // 現在の接続の一覧。接続した順に並ぶ。 const connections = []; +// 15 秒ごとにコメント行を送り、データが流れない接続が切られないようにする +function sendPing() { + for (let i = 0; i < connections.length; i++) { + connections[i].write(': ping\n\n'); + } +} +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}`); @@ -33,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; @@ -45,6 +62,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();