$(document).ready(function () { var connection, username = 'Tester', password = 'Tester', historyCounter = 0, members = {},
// node.js code var http = require('http'), url = require('url'), path = require('path'), fs = require('fs'), nano = require('nano')('http://localhost:5984'), chatroomDb = nano.use('chatroom'), websocket = require('websocket'), chatHistory = [], activeUsers = {}; var filesDir = path.join(process.cwd(), 'web'); var mimeTypes = { '.html': 'text/html', '.css': 'text/css', '.js': 'text/javascript' }; var getContentType = function (extension) { var mimeType = mimeTypes[extension]; return mimeType ? mimeType : 'application/octet-stream'; }; var server = http.createServer(function (request, response) { var relativePath = url.parse(request.url).pathname, absolutePath = path.join(filesDir, relativePath); var handler = function (err, stats) { if (stats) { if (stats.isDirectory()) { absolutePath = path.join(absolutePath, 'index.html'); fs.stat(absolutePath, handler); return; } if (stats.isFile()) { response.writeHead(200, getContentType(path.extname(absolutePath))); var stream = fs.createReadStream(absolutePath); stream.pipe(response); return; } } response.writeHead(404, {'Content-Type': 'text/plain'}); response.write('Not found\r\n'); response.end(); }; console.log('HTTP request for ' + relativePath); fs.stat(absolutePath, handler); }); server.listen(8080, function () {}); wsServer = new websocket.server({ 'httpServer': server }); function addLine (type, nick, line) { var msg = { 'type': type, 'nick': nick, 'line': line }, jsonMsg = JSON.stringify(msg), username; chatHistory.push(msg); while (chatHistory.length > 100) chatHistory.shift(); for (username in activeUsers) { activeUsers[username].sendMessage(jsonMsg); } } wsServer.on('request', function (request) { console.log('New websocket connection from ' + request.origin); // TODO: verify that request.origin is our web site var connection = request.accept(null, request.origin); var username = null; connection.on('message', function (message) { if (message.type !== 'utf8') { console.log('Refusing a non-utf8 message'); return; } console.log('Processing message: ' + message.utf8Data); try { var m = JSON.parse(message.utf8Data); switch (m.type) { case 'login': chatroomDb.get(m.username, function (err, body) { if (err || (body.password !== m.password)) { connection.close(); return; } username = m.username; addLine('join', username, null); activeUsers[username] = { 'sendMessage': function (jsonMsg) { connection.sendUTF(jsonMsg); } }; var users = [], u; for (u in activeUsers) users.push(u); connection.sendUTF(JSON.stringify({ 'type': 'state', 'history': chatHistory, 'users': users })); }); break; case 'line': if (!username) { connection.close(); break; } addLine('line', username, m.line); break; } } catch (e) { console.log(e); } }); connection.on('close', function (connection) { console.log('Connection closed'); if (username) { delete activeUsers[username]; addLine('leave', username, null); } }); }); console.log('Server running');
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Chatroom</title> <style> html, body { width: 100%; height: 100%; padding: 0; border: none; margin: 0; } #heading { position: absolute; top: 0; left: 0; right: 0; height: 30px; margin: 0; padding: 0; line-height: 30px; text-align: center; font-size: 20px; background-color: green; } #outer { position: absolute; top: 30px; bottom: 0; left: 0; right: 0; margin: 20px; min-height: 400px; min-width: 400px; background-color: lime; } #inner { height: 100%; background-color: #ffc0cb; } #chat { position: absolute; top: 0; left: 0; right: 200px; bottom: 0; background-color: #ffd700; } #members { position: absolute; top: 0; right: 10px; width: 180px; bottom: 0; background-color: #ff00ff; list-style-type: none; padding: 10px; padding: 0; border: none; } #history { position: absolute; top: 0; left: 0; bottom: 2em; right: 0; background-color: #00ffff; padding: 10px; } #input { position: absolute; height: 2em; left: 0; right: 0; bottom: 0; background-color: #90ee90; line-height: 2em; } #line { width: 100%; margin: 0; border: none; padding: 0; } #history > p { margin: 2px; } .nick { white-space: pre; display: table-cell; } .line { display: table-cell; } #login { height: 100%; display: table; margin: 0 auto; } #login > .svg { vertical-align: middle; display: table-cell; } #login-wrapper1 { display: table; height: 100%; width: 100%; } #login-wrapper2 { display: table-cell; vertical-align: middle; } #login-table { margin: 0 auto; } #login-table .label { text-align: right; } #waiting { position: fixed; top: 0; bottom: 0; left: 0; right: 0; opacity: 0.3; } </style> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> <script src="client.js"></script> </head> <body> <div id="login"> <div class="svg"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 400 400" width="400" height="400"> <defs> <path id="curved-text" d="M0,0 c 50 -50 150 -50 200 0" /> </defs> <g> <text transform="translate(-100,40)" font-weight="bold" font-variant="small-caps" font-family="Arial sans-serif" font-size="30" fill="none" stroke="orange" text-anchor="middle"> <textPath xlink:href="#curved-text" startOffset="50%">Chatroom</textPath> </text> <animateTransform attributeName="transform" attributeType="XML" type="rotate" from="0" to="360" dur="5s" fill="remove" additive="sum" repeatCount="indefinite" /> <animateMotion dur="10s" repeatCount="indefinite" path="M100,200 a100,100 0 1 1 200,0 a100,100 0 1 1 -200,0" /> </g> <foreignObject x="0" y="0" width="400" height="400" style="height:400px;"> <div xmlns="http://www.w3.org/1999/xhtml" id="login-wrapper1"> <div id="login-wrapper2"> <table id="login-table"> <tbody> <tr> <td class="label">Vzdevek:</td><td><input type="text" id="nickname" /></td> </tr> <tr> <td class="label">Geslo:</td><td><input type="password" id="password" /></td> </tr> </tbody> </table> </div> </div> </foreignObject> </svg> </div> </div> <div id="chatroom" style="display:none;"> <h1 id="heading">Chatroom</h1> <div id="outer"> <div id="inner"> <div id="chat"> <div id="history"> <p><span class="nick">Matej: </span><span class="line">Hi</span></p> <p><span class="nick">Borut: </span><span class="line">How are you?</span></p> <p><span class="nick">Martina: </span><span class="line">Ok, thanks!</span></p> </div> <div id="input"><input id="line" type="text"></div> </div> <ul id="members"> <li>Matej</li> <li>Borut</li> <li>Martina</li> </ul> </div> </div> </div> <div id="waiting" style="display:none;"></div> </body> </html>