Skip to content

Instantly share code, notes, and snippets.

@toofusan
Created December 29, 2016 01:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save toofusan/acd86ee75cd626e5b4deac488de9989f to your computer and use it in GitHub Desktop.
Save toofusan/acd86ee75cd626e5b4deac488de9989f to your computer and use it in GitHub Desktop.
<!doctype html>
<html>
<head>
<title>Socket.IO chat</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font: 13px "Source Sans Pro", Helvetica, Arial, 游ゴシック体, YuGothic, メイリオ, Meiryo, sans-serif; }
#top-fixed {padding 5px 0px; position: fixed; top: 0; width: 100%;}
#bottom-fixed {padding 5px; position: fixed; bottom: 0; width: 100%;}
#container { padding: 15px 5px;}
input { border: 0; padding: 10px; width: 80%; margin-right: .5%; }
button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
form#inputArea { background: #000; padding: 3px;}
#messages { list-style-type: none; margin: 0; padding: 0; }
#messages li { padding: 5px 10px; background: #eeeeee;}
#messages li:nth-child(odd) { background: #e2e2e2; }
#messages li.sysmessage{background: #fff; padding: 20px 10px; text-align: center; color: #aaaaaa}
#modalWindow {position: fixed; top: 0; left: 0; width: 100%; height: 100%; padding: 10px; box-sizing: border-box; background-color: rgba(0,0,0,0.8); z-index: 101}
#modalWindow p {color: #fff; margin-bottom: 10px;}
#container {z-index: 100;}
</style>
</head>
<body>
<div id="container">
<ul id="messages"></ul>
<div id="top-fixed">
<p id="members">Now online member is <span></span></p>
</div>
<div id="bottom-fixed">
<p id="system-text"></p>
<form id="inputArea" action="" onsubmit="return false;">
<input id="m" autocomplete="off" placeholder="message"/>
<button>Send</button>
</form>
</div>
</div>
<div id="modalWindow">
<div>
<form id="registNickname" action="" onsubmit="return false;">
<p>Enter your name</p>
<input id="nickname" autocomplete="off" placeholder="your name"/>
<button>Enter</button>
</form>
</div>
</div>
<script src="/socket.io/socket.io.js"></script>
<script>
'use strict';
const socket = io();
document.addEventListener('DOMContentLoaded', (e) => {
const $sendBtn = document.querySelector('button');
const $m = document.querySelector('#m');
const $systemText = document.querySelector('#system-text');
const $messages = document.querySelector('#messages');
const $members = document.querySelector('#members span');
const $modalWindow = document.querySelector('#modalWindow')
const $nickname = document.querySelector('#nickname');
const $modalBtn = document.querySelector('#registNickname button');
// ==============================
// クライアントから送信
// ==============================
// 入室
$modalBtn.addEventListener('click', (e) => {
socket.emit('enter room', $nickname.value);
$modalWindow.parentNode.removeChild($modalWindow);
});
// テキスト入力
let nowTyping = false;
$m.addEventListener('keydown', (e) => {
socket.emit('start typing');
});
// テキスト送信
$sendBtn.addEventListener("click", (e) => {
socket.emit('chat message', $m.value);
$m.value = "";
}, false);
// ==============================
// サーバーからの受信後処理
// ==============================
socket.on('newcomer joined', (nickname) => { // 誰かが入室した時
$messages.innerHTML += '<li class="sysmessage">' + nickname + ' joined</li>';
});
socket.on('the number of users', (login_users) => { // 参加者に変動があったとき
$members.innerHTML = Object.values(login_users).join(", ");
});
socket.on('user disconnect', (exituser) => { // 参加者が退出した時
$messages.innerHTML += '<li class="sysmessage">' + exituser + ' exited</li>';
});
socket.on('start typing', (typinguser) => { // 誰かが文字入力を初めた時
$systemText.innerHTML += typinguser + ' is now typing...';
});
socket.on('stop typing', () => { // 誰かが文字入力を止めた時
$systemText.innerHTML = '';
});
socket.on('chat message', (data) => { // 誰かがテキストを送信した時
$messages.innerHTML += '<li><span>' + data.nickname + ':</span>' + data.msg + '</li>';
$systemText.innerHTML = '';
});
socket.on('reject message', (msg) => { // 自分が直前と同じテキストを送信した時
$systemText.innerHTML = 'same text already posted "' + msg + '"';
});
});
</script>
</body>
</html>
'use strict';
// モジュール
const app = require('express')();
const http = require('http').Server(app);
const io = require('socket.io')(http);
let login_users = {}; // 参加者管理
app.get('/', (req, res) => {
res.sendfile('index.html');
});
io.on('connection', (socket) => {
// 入室処理
socket.on('enter room', (nickname) => {
login_users[socket.id] = nickname;
socket.broadcast.emit('newcomer joined', login_users[socket.id]); // 入室したことを他の人に通知
io.emit('the number of users', login_users);     // 参加者一覧を更新
});
// 退室処理
socket.on('disconnect', () => {
socket.broadcast.emit('user disconnect', login_users[socket.id]); // 退室したおとを他の人に通知
delete login_users[socket.id];
io.emit('the number of users', login_users); // 参加者一覧を更新
});
// テキスト入力処理
let nowTyping = 0;
socket.on('start typing', () => {
if (nowTyping <= 0) {
socket.broadcast.emit('start typing', login_users[socket.id]); // 入力開始を他の人に通知
}
// 一文字打つごとにカウントアップ。打ってから3秒後にカウントダウンし、カウントが0になると入力停止したとみなす
nowTyping++;
setTimeout(() => {
nowTyping--;
if (nowTyping <= 0) {
socket.broadcast.emit('stop typing'); // 入力停止を他の人に通知
}
}, 3000);
});
// テキスト投稿処理
let latestmsg = "";
socket.on('chat message', (msg) => {
// 直前の投稿と同じ時はエラー文を出す
if (msg === latestmsg) {
io.to(socket.id).emit('reject message', msg);
return;
}
latestmsg = msg;
io.emit('chat message', { // テキスト投稿
nickname: login_users[socket.id],
msg: msg
});
});
});
http.listen(3000, () => {
console.log('listening on *:3000');
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment