From d972229a3bff2f72939c8df3e95209fe48e31e26 Mon Sep 17 00:00:00 2001 From: Catlin Buckley Date: Mon, 8 Dec 2014 20:37:09 -0500 Subject: [PATCH] Overhauled chat system --- LICENSE | 21 -- Procfile | 1 + app.js | 19 + config.js | 17 + dokku | 30 ++ dokku.pub | 1 + package.json | 21 ++ public/chat.js | 33 -- public/chat.js~ | 27 -- public/css/stylesheet.css | 637 +++++++++++++++++++++++++++++++++ public/img/nodejslogo.png | Bin 0 -> 18759 bytes public/img/unnamed.jpg | Bin 0 -> 5543 bytes public/img/waffle-bg.gif | Bin 0 -> 3170 bytes public/img/wafflechat-logo.gif | Bin 0 -> 22571 bytes public/js/chat.js | 337 +++++++++++++++++ public/js/moment.min.js | 6 + routes.js | 154 ++++++++ tpl/page.jade | 14 - tpl/page.jade~ | 11 - views/chat.html | 129 +++++++ views/home.html | 39 ++ wafflechat.js | 22 -- 22 files changed, 1391 insertions(+), 128 deletions(-) delete mode 100644 LICENSE create mode 100644 Procfile create mode 100644 app.js create mode 100644 config.js create mode 100644 dokku create mode 100644 dokku.pub create mode 100644 package.json delete mode 100644 public/chat.js delete mode 100644 public/chat.js~ create mode 100644 public/css/stylesheet.css create mode 100644 public/img/nodejslogo.png create mode 100644 public/img/unnamed.jpg create mode 100644 public/img/waffle-bg.gif create mode 100644 public/img/wafflechat-logo.gif create mode 100644 public/js/chat.js create mode 100644 public/js/moment.min.js create mode 100644 routes.js delete mode 100644 tpl/page.jade delete mode 100644 tpl/page.jade~ create mode 100644 views/chat.html create mode 100644 views/home.html delete mode 100644 wafflechat.js diff --git a/LICENSE b/LICENSE deleted file mode 100644 index fb31fce..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014 catlinbuckley - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..e1d4131 --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: node app.js diff --git a/app.js b/app.js new file mode 100644 index 0000000..0e3c0e9 --- /dev/null +++ b/app.js @@ -0,0 +1,19 @@ +var express = require('express'), + app = express(); + +// This is needed for Dokku: + +var port = process.env.PORT || 8080; + +// Initialize a new socket.io object. It is bound to +// the express app, which allows them to coexist. + +var io = require('socket.io').listen(app.listen(port)); + +// Require the configuration and the routes files, and pass +// the app and io as arguments to the returned functions. + +require('./config')(app, io); +require('./routes')(app, io); + +console.log('Your application is running on http://localhost:' + port); \ No newline at end of file diff --git a/config.js b/config.js new file mode 100644 index 0000000..166e8a8 --- /dev/null +++ b/config.js @@ -0,0 +1,17 @@ +var express = require('express'); + +module.exports = function(app, io){ + + // Set .html as the default template extension + app.set('view engine', 'html'); + + // Initialize the ejs template engine + app.engine('html', require('ejs').renderFile); + + // Tell express where it can find the templates + app.set('views', __dirname + '/views'); + + // Make the files in the public folder available to the world + app.use(express.static(__dirname + '/public')); + +}; diff --git a/dokku b/dokku new file mode 100644 index 0000000..d412a38 --- /dev/null +++ b/dokku @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-128-CBC,4AD33A921DB32908BFF69ABE4D646100 + +B6/L/8Y3lOYlv3doaNfy10fphP1/n6ZNk9Ys/cIBhnbI6tzAMNt3M1+KcM/nmKY9 +miGY7F3XUI87Jc6F6EzIMkBw7Pae1zSoj/CCynVtgezxbT2FQJNTPZJ+GsbP1gXH +nbWMTUVcAfLMyw1HPg4oPFI/0btb3AJxxkayqILx0tWAKJRSJz4ZiOijFsJdd15J +5Njw/0EdW0ds7IG++h7zLKt0AaFC3liwaD5HxfUmZrhgsFOQ3d2WTK+pGRox0XDn +oRO4vOETfk6zx+W/91BoM+xtot/FBTt3hStOBsB4xB7P37hHm+0oclS29KD9sxVo +2J9bn5PE2XF40GVycJCLLBWJgDZKroCIoGhgIZnlP3QPrEqYyHbq1SYO2awzWgzm +AAV7dbqxzIXDGtM0x1MjDX33EeHBtu63tlE+uPfxD4jClYaQUb7UWwEW+ASkZveL +EKoDNFGEBwXvdDW67mmjOOk5M+GSybS4RMw3OnHU5KzYEEx5qpfbPqpJoRCyq41w +jlVxoUqCVd2DrS0e74gfgyEL5Apy9Tj8sQ9DHVMEwjmOznFoZY8zu3C7ap91tm/R +XKsoXNmYFbUzT8nSV6tSNfOy3vyNcLP0PdzAWPgiNQ8d99QI3k+UudX1qZvLF8rq +7HS6XHFzXoitAeWegLC0Goif+qYBs6EmjVcF7KFCY08lX4KgZLMbI45X2RBNadhj +liYiJHDVII9nak8kt/lUT/bkGrLUVnQ1wjlQbBbcu73Tx9FXJwMna5v/CDPGDNfS +X5FMeLe8Kop8F8yz0MU9Hn+KS/Gpic3nZeQCVlI/8e4DAunSS0T3Z8pEksh/lFNb +KmkFX+dlmgJ7QnA2/TI/56fmK+bPjXYcuE69OSnSQATHO/5D7s38lDMPVvhuA2E8 +js7tgAHZYZ3//+inUqBAbvnyLkSlCjJ5cWwtX7bJJPZg35XzIowX4nwdYuqTx00/ +iBN6z03YqzoaxXqIpT8Ec2JYkcjYu41j6Z2eXdDAy0Q+BGl0/SdNCYStTTAMHhE5 +iiNpCYChlzYy6a2RlBgqTl9dGAAyobPwC17dLMkAtdJSHrzaqRow7HgCGlMHh/a8 +0HnBGThb+kJga0vB2lbPWqICtZIq8i2mtcuS5rG5NK3vtTSSQnIhIju8FT1Cf9vv +CLz5iZb8ez3G+VCy9N7PqATSzkmy/a7ArzxNkDc8iYrkCtLwSvrwOgRtBxTCNsiM +kMpD0dbpiAvQiL9eMq+FB7TigkonxWVfmq2y/Koy7nK6nc4hLf91uIE5Kipi7mzu +5KuAP/5sjhvMz3eaN3aB3R1ZNToQZKq93LKKTCevZdomyDrOO3+w/w7zsJXsCyOX +5UgCaG4pDbraYWa1T5z+ddhFzoWiHFahocCQiNiwe5aqNA5vHF0oG8r7XExUlG9d +2nP6N4pf04IxFk61gDeu/oDe2dcv8BfOxQIStPMii8s659fzrR3yuHrJrGKlG4Ia +dCqPiLu+Pq0KpgIJzx70g+q6pwGx6ZtconfoUWgPCRNbBnGlq1rVfY5/M9n986+H +AN3jDl7ksUBwDg6Pf8Z8tsXGFyZ6jvXzSIvuFwjb5SwY9NAPzrg+cVh3B8Woww3z +-----END RSA PRIVATE KEY----- diff --git a/dokku.pub b/dokku.pub new file mode 100644 index 0000000..d2073dc --- /dev/null +++ b/dokku.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC2+qldoWVHGjPU4vqKdUvlS3VAmPZI9+X0O1uODcc9Vq8efducR82MloqPx67mxt7xkhE2Q+jD0kdsJsE+IHTtspsTyTCPc+x2dVEzUjOiw904FGa9lHEYSE8c2/H1GCKn9Olss2vV4V43aoH9X1O6Lj2cW1avDFXSyEmBbw1BWBaU2TyJW310YG9sgu1+1jnYro1YuGIwN/FsSKLGUf+U3E+YqN3wMRzStwo/svxgOF9qgptD5u86Fc1Nf4gEGXY+AEtDCPpHc84L8CWanUUaW80Cij4a09T6MLowz5qwc/EFIoSd4lD2yNpQptOV6G3CwlpMBScId9BzILxtONmL cbuckley@cats-mbp.home diff --git a/package.json b/package.json new file mode 100644 index 0000000..0bac441 --- /dev/null +++ b/package.json @@ -0,0 +1,21 @@ +{ + "name": "WaffleChat", + "version": "0.0.2", + "description": "Real-time chat", + "main": "app.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [ + "waffle", + "chat" + ], + "author": "Catlin Buckley", + "license": "MIT", + "dependencies": { + "ejs": "^1.0.0", + "express": "^4.8.2", + "gravatar": "~1.0.6", + "socket.io": "^1.0.6" + } +} diff --git a/public/chat.js b/public/chat.js deleted file mode 100644 index 89bf253..0000000 --- a/public/chat.js +++ /dev/null @@ -1,33 +0,0 @@ -window.onload = function() { - - var messages = []; - var socket = io.connect('http://107.170.47.159:80'); - var field = document.getElementById("field"); - var sendButton = document.getElementById("send"); - var content = document.getElementById("content"); - var name = document.getElementById("name"); - - socket.on('message', function (data) { - if(data.message) { - messages.push(data); - var html = ''; - for(var i=0; i'; - html += messages[i].message + '
'; - } - content.innerHTML = html; - } else { - console.log("There is a problem:", data); - } - }); - - sendButton.onclick = function() { - if(name.value == "") { - alert("Please type your name!"); - } else { - var text = field.value; - socket.emit('send', { message: text, username: name.value }); - } - }; - -} diff --git a/public/chat.js~ b/public/chat.js~ deleted file mode 100644 index 2b9c951..0000000 --- a/public/chat.js~ +++ /dev/null @@ -1,27 +0,0 @@ -window.onload = function() { - - var messages = []; - var socket = io.connect('http://107.170.47.159:80'); - var field = document.getElementById("field"); - var sendButton = document.getElementById("send"); - var content = document.getElementById("content"); - - socket.on('message', function (data) { - if(data.message) { - messages.push(data.message); - var html = ''; - for(var i=0; i'; - } - content.innerHTML = html; - } else { - console.log("There is a problem:", data); - } - }); - - sendButton.onclick = function() { - var text = field.value; - socket.emit('send', { message: text }); - }; - -} diff --git a/public/css/stylesheet.css b/public/css/stylesheet.css new file mode 100644 index 0000000..1a57412 --- /dev/null +++ b/public/css/stylesheet.css @@ -0,0 +1,637 @@ +/*------------- Browser reset ------------- */ +* { + padding: 0; + margin: 0; + box-sizing: border-box; +} + +:focus {outline-color:#f6cb7c;} + +/* ------------ Body styles ------------ */ +html { + background-image: url("/img/waffle-bg.gif") +} + +body { + background: none; + color:#667073; + font: 16px/1.3 'Arial',sans-serif; +} + +/* ------ Section ------ */ +.section { + margin: 20px; +} + +/* ------ Home ------ */ +.homebanner { + height: 120px; + background-color: #3c4446; +} + +.homebannertext { + text-align:center; + padding-top: 35px; + font-family: 'Open Sans Condensed',serif; + font-weight: bold; + color:white; +} +.homebannertext span { + color: #d6441b; +} + +#logo { + text-decoration: none; + color:white; +} +#logo:visited { + color: white; +} + + + +/* ------ Invite ------ */ + + +.banner { + height: 70px; + background-color: #3c4446; + margin-bottom: 200px; +} + +.bannertext { + text-align:center; + padding-top: 15px; + font-family: 'Open Sans Condensed',serif; + font-weight: bold; + color:white; + font-size:25px; +} +.bannertext span { + color: #d6441b; +} + + + + +/* ------------ Section styles ------------ */ +html { + background-image: url("/img/waffle-bg.gif") +} + + +/* ------ Home ------ */ + + +.homesection { + text-align:center; + margin-top:140px; +} + +.logowrapper { + padding-top: 20px; + text-align:center; +} +.logowrapper #chat { + font-family: 'Open Sans Condensed'; + font-weight: normal; + color: #707368; +} + +#logo { + max-width: 410px; + margin-bottom: 35px; +} + +#create { + width: 300px; + height: 100px; + background-color: #f1ae5d; + text-align:center; + display: block; + margin:0px auto; + border-radius: 3px; + box-shadow: 0px 5px 5px #e4e8e7; + text-decoration: none; + margin-bottom: 70px; + color: #eeffff; +} +#create:visited { + color: #eeffff; + text-decoration: none; +} +#createbutton { + padding-top: 28px; +} +#little { + font-weight: normal; + font-size: 13px; +} +#big { + font-weight: bold; + font-size: 23px; +} +.tutorial{ + margin-bottom:90px; +} +#tutorial { + color: #88bfd4; +} +#tutorial:visited { + color: #88bfd4; +} + + + +/* ------ Connected ------*/ + +.connected { + text-align:center; + display: block; + margin:0px auto; + width: 700px; + height: 400px; + background-color: #ffffff; + border-radius: 3px; + box-shadow:0px 3px 3px #e3e4e6; + color: #637277; +} +.connected h2 { + padding-top: 20px; +} +.infoConnected { + text-align: left; + float: right; + margin: 65px 165px 0 0; +} +#creatorImage { + float: left; + margin: 90px 0 0 140px; + width: 100px; + height: 100px; + border-radius: 50%; +} + +#yourName { + float:left; + padding-left:10px; + width: 150px; + height: 30px; + border-radius: 3px; + box-shadow:0px 3px 3px #e3e4e6; + background-color: #f0f1f3; + border: 1px solid #d1d1d1; + border-radius: 3px; + box-shadow:0px 3px 3px #e3e4e6; + margin-bottom:20px; + overflow: hidden; +} + +#yourEmail { + float:left; + padding-left: 10px; + width: 200px; + height: 30px; + border-radius: 3px; + box-shadow:0px 3px 3px #e3e4e6; + background-color: #f0f1f3; + border: 1px solid #d1d1d1; + border-radius: 3px; + box-shadow:0px 3px 3px #e3e4e6; + margin-bottom:40px; +} + +#yourEnter { + float:left; + width: 110px; + height: 40px; + text-align:center; + background-color: #f1ae5d; + border: none; + box-shadow: 3px 3px 3px #efedee; + border-radius: 2px; + color:white; + font-weight: bold; + font-size: 15px; +} + + + +/* ------ Person Inside ------*/ + +.personinside { + text-align:center; + display: block; + margin:0px auto; + width: 700px; + height: 400px; + background-color: #ffffff; + border-radius: 3px; + box-shadow:0px 3px 3px #e3e4e6; + color: #637277; +} +.personinside h2 { + padding-top: 20px; + width: 210px; + overflow: hidden; +} + +.infoInside { + text-align: left; + float: right; + margin: 65px 165px 0 0; +} + +#ownerImage { + float: left; + margin: 90px 0 0 140px; + width: 100px; + height: 100px; + border-radius: 50%; +} + +#hisName { + float:left; + padding-left:10px; + width: 150px; + height: 30px; + border-radius: 3px; + box-shadow:0px 3px 3px #e3e4e6; + background-color: #f0f1f3; + border: 1px solid #d1d1d1; + border-radius: 3px; + box-shadow:0px 3px 3px #e3e4e6; + margin-bottom:20px; +} + +#hisEmail { + float:left; + padding-left: 10px; + width: 200px; + height: 30px; + border-radius: 3px; + box-shadow:0px 3px 3px #e3e4e6; + background-color: #f0f1f3; + border: 1px solid #d1d1d1; + border-radius: 3px; + box-shadow:0px 3px 3px #e3e4e6; + margin-bottom:40px; +} + +#hisEnter { + float:left; + width: 110px; + height: 40px; + text-align:center; + background-color: #f1ae5d; + border: none; + box-shadow: 3px 3px 3px #efedee; + border-radius: 2px; + color:white; + font-weight: bold; + font-size: 15px; +} + + +/* ------ Invite ------ */ + + +.invite-textfield { + text-align:center; + display: block; + margin:0px auto; + max-width: 750px; + background-color: #ffffff; + border-radius: 3px; + box-shadow:0px 3px 3px #e3e4e6; + color: #637277; + padding:30px 15px; +} +.invite-textfield h5 { + font-weight: normal; + margin: 10px 0 35px; + } +.invite-textfield .link { + max-width: 400px; + padding: 15px; + text-align:center; + display: block; + margin:0px auto; + border-radius: 4px; + background-color: #f0f1f3; +} +.invite-textfield #link{ + text-decoration: none; + color: #637277; +} + + +/* ------ Left ------*/ + +.left { + text-align:center; + display: block; + margin:0px auto; + width: 750px; + height: 300px; + background-color: #ffffff; + border-radius: 3px; + box-shadow:0px 3px 3px #e3e4e6; + color: #637277; + margin-bottom: 400px; +} +.left h2 { + padding-top: 50px; + padding-bottom: 6px; +} +.left h5 { + font-weight: normal; + margin-bottom: 100px; +} + +#leftImage { + float: left; + margin: 90px 0 0 140px; + width: 100px; + height: 100px; + border-radius: 50%; +} +.nickname-left { + width: 40px; + overflow: hidden; +} + +/* ------ Too many People ------*/ + + +.toomanypeople { + text-align:center; + display: block; + margin:0px auto; + width: 750px; + height: 300px; + background-color: #ffffff; + border-radius: 3px; + box-shadow:0px 3px 3px #e3e4e6; + color: #637277; +} +.toomanypeople h2 { + padding-top: 100px; + padding-bottom: 8px; +} +.toomanypeople h5 { + font-weight: normal; + margin-bottom: 100px; +} + +#room:visited { + color: #88bfd4; +} + + + +/* ------ No Messages ------ */ + + +.nomessages { + text-align:center; + display: block; + margin:0px auto; + width: 750px; + height: 300px; + background-color: #ffffff; + border-radius: 3px; + box-shadow:0px 3px 3px #e3e4e6; + color: #637277; + margin-bottom: 400px; +} +.nomessages h2 { + padding-top: 50px; + overflow: hidden; + padding-bottom: 6px; +} +.nomessages h5 { + font-weight: normal; + margin-bottom: 100px; +} + +#noMessagesImage { + float: left; + margin: 90px 0 0 140px; + width: 100px; + height: 100px; + border-radius: 50%; +} + +#img { + float: left; + margin: 90px 0 0 140px; + width: 100px; + height: 100px; + border-radius: 50%; +} +.info { + text-align: left; + float: right; + margin: 65px 60px 0 0; + width: 405px; + overflow: hidden; +} +.nickname-chat { + overflow: hidden; +} + + +/* ------ Chat Screen ------ */ + + + +.image { + clear:both; + float:left; + height: 160px; + width: 80px; + text-align:center; + overflow: hidden; +} + +.image img { + float: left; + width: 80px; + height: 80px; + border-radius: 50%; +} + +.body { + text-align:center; + width: 40%; + display: block; + margin:0px auto 650px; + background-color: #ffffff; + color: #637277; +} + +.chats { + list-style-type: none; + margin-top:10px; +} + +.me { + clear:both; + float:left; + margin-bottom:10px; +} + +.you { + clear:both; + float:right; + margin-bottom:10px; +} + +.you .image{ + float:right; +} + +.chats .me p { + text-align:left; + float: left; + display: inline-block; + margin-left: 20px; + margin-bottom:30px; + padding: 25px 34px; + min-width: 160px; + min-height: 10px; + max-width: 510px; + background-color: #FFF; + border-radius: 3px; + box-shadow: 0px 3px 3px #E3E4E6; + color: #637277; + line-height: 1.4; + word-wrap: break-word; +} + +.chats .you p { + text-align:left; + float: left; + display: inline-block; + margin-right:20px; + margin-bottom:30px; + padding: 25px 34px; + min-width: 160px; + min-height: 10px; + max-width: 510px; + background-color: #FFF; + border-radius: 3px; + box-shadow: 0px 3px 3px #E3E4E6; + color: #637277; + line-height: 1.4; + word-wrap: break-word; +} + +.image b { + overflow: hidden; + display: block; + clear: both; + padding-top: 7px; +} + +.image i{ + font-size: 12px; + line-height: 1.2; + display: block; + opacity: 0.8; + padding-top: 4px; +} + + +/* ------------ Footer styles ------------ */ + +footer { + position:fixed; + bottom:0; + left:0; + width:100%; + padding: 20px; + background-color: white; + height: 100px; +} +#chatform { + max-width:740px; + margin: 0 auto; + background-color: white; +} + +#message { + width: 80%; + height: 60px; + display: block; + float:left; + margin: 0 auto; + background-color: #f9f9f9; + border: 1px solid #cccccc; + border-radius: 2px; + padding-left: 20px; + padding-top: 20px; + resize: none; + font:inherit; + color:inherit; +} + +#submit { + width: 15%; + height: 60px; + float:right; + text-align:center; + background-color: #f1ae5d; + display: block; + margin: 0 auto; + border: none; + box-shadow: 3px 3px 3px #efedee; + border-radius: 2px; + color:white; + font-weight: bold; + font-size: 17px; + outline: none; + cursor:pointer; +} + + + + +/* ---------------------- HIDE -------------------------- */ + + +.connected { + display: none; +} + +.personinside { + display: none; +} + +.invite-textfield { + display:none; +} + +.left { + display:none; +} + +.toomanypeople { + display:none; +} + +.nomessages{ + display:none; +} + +footer { + display:none; +} + +.chatscreen{ + display:none; + width:700px; + margin: 0 auto 200px; + overflow:hidden; +} \ No newline at end of file diff --git a/public/img/nodejslogo.png b/public/img/nodejslogo.png new file mode 100644 index 0000000000000000000000000000000000000000..d4a1c447fac7e0f4edfabd41032c70abd856380f GIT binary patch literal 18759 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 literal 0 HcmV?d00001 diff --git a/public/img/unnamed.jpg b/public/img/unnamed.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c95c656eb7adcb1a14d2a41b02eb8ca9dcddf831 GIT binary patch literal 5543 zcmbtXXHb(-vwlNDlOmy4r35e#giu148VCp|y@^6VloG0RkR}L(7Mc_RsS=umj!KiF zf~fRfrHgdILb>>TGk50xzI*1(nKOI#nVmDc`|O@ioG$`C~00;yEFc%9rp9VDk z-Tq(l59I#^@Xz?X1AtNi@jyHn#1D``L0~B8yc@UzfB+B#eBti@3MGhwikb{U4!(4u zS7rdnKxE`(5C}PloCkKml?_J|u-2C6l2Yzb9dridizeK%IqEz-SSsf%S?Y zbq*T8+q*F5xB&h?-~e!84kEu$U55f7Fd3Kib*ateY{RyZDNcJepmgru$t zNddT1&`&?@BAp#=jP>;fSlC&lXcDaIyQ8OP@XvUUcxfWB=-ArL1KrKlRhn^9JMUBot^pfx81U&t6y3EGgo}MPZ+{Ckovv)#F@{YNVA->)4`BZmROuN!P)#=l-vzh@JMal^C@Xlr=QsW#jY<+$X zd~I)Off?VnRpXtT%UNnpsy(a7<0q}c*R=H8CBn^2Tb5sdxaq=S#HrQOojB)akwQzS zWlO_11#A>Yd{NuQToGJe=$=jp!Plc}XCs;_)9&9+r2o!Y*Fwz+cf`5^Tqz+{pjY)p;*hzb#os9PX2Q&f38$dBKx<>98&4$yI9_R^A+N3&6BX z2;vGq_#zc6B_CWO=)@ly4ys8`csoXto%?e;hlK=VRNZZ}4mtSo7}v3YixBP`+ZHQSO z@=wl8*PlR74ULOUyVhCAUI&6HN_%^u zeQGMLiSw0SPKdpIt4zseH^PUL#;w|)19qkZ9mCKzC{*!C0 z;K}}WM$-=q4{W4#loVZ3#j3LNFg?e}E|Uhkqq9^)o)0L`hLT^NDwW<+Y5MYgl{h&q z7(oGV{rTyWm1y>)z*{|6lD<=5Bv1PHTkv?=Ch1`vvoY&@!6_$Vd1a%5(`HE;oV+l8 zmQ}s6`=~}mqPJr{>@pSuaieCHtBjZ)Vj19jXSJ}X`{B!z;SAlPi?9p-Gk@wiRrspB zf91fbSoG}S#~UVL2di2r`w6bOx#+RYWHr*-&JM1Xn!QxsXB4p_-+JQ#-O%8dE5oW7 z#LJUDabNWtd<{K^xgEme-QxPjGTehB#v~nkS;{{a_a1r9-m0obimU`Ym(P{RMwX&$ z2Uy3o=f9q1oVtV@5<+&-8;cj&UDEU6u<^7Bb=9~LQC&X3fy?MPLKNyu8Z6vf6)rW>hOj_$Zx#TJ4p{65|UKFKXEPiY-H+hD`17*$qFL1$C!m{u3%vrKH zF05u5H;sn|Cym>k1MVlDaTiBHXl~P)M<>(J^i0__39B9%ZRRF{q3>hP`0vkx zGhm6ame0p2@6;i#YiHiJK9C7CC@zdv?Jj)kRBY_CKWQ<~QEGoPZRKZ6?xP41rM8T~ z@~2o}9~=Ls3>IFkZSmqZhLp+RhZ>hP{V5n~zSi*jhqvTMbE!E0$doh_-AA3;WVr)Q?(KKFD9#(vmd1Io13=a zIPsOtgCDWB#bIwWAT+j0>3F>-(uo>xxcxgUtZ}UX*=!@%<>UzuR3l(vo$#??$0Y?9 zL@&o)Ez`lu@OH`JBXL}zRF0*k^{GI}K+l^*`9JaAT@cNYcpjbWu_7prT=U8j`0Jt&nxt&`cp+YfFTbXsSv) zcc+)wEv?8fxg34j4;_?J%>Zhi}thNZ}J@L4+FQ{P5A?j}veF%Zd_7N2I#=LwJ#k z?AX1!ujo+=;XYmgcIkB^O_ z_+xWZsZUc zvsIO4thMl$eRAjVc<=jHAwRG>us}vP?Jf8C=D8hd8sEMU$iqz^kVF@)QG>YOOA)Jl z=~#ookqXri8ks!tViNwCN&#Q>raa48l*~ygfoZWgg>S>PAXvP~{Y>hksP(p>x%vmM(5HO=D}Kh8WyvMxilgeJ(riDq1jKJ!X=Q? z(4I&qyUX*D^kD|Z42tyq16_c7`~07)xBV!wplRB>bv74229@Yy9uaptIhwGHfz8`K zl3<%5xVT+M3;&W$Yr`!GY45TRPZ$RFgv2>k41k%qZ-+E2i=T7=$`TaeF!dMEYf*k*TfxX8o)1rfPg{0ozLcjPF9K@wm zrk;FD+$9|M3fDZ5ihDzIZPC=M4;2^wLHycwBrU9t{~@Lr(}y1Q=%V#up(X*5t;bW- zG!TPV1(1CuxO&ay;axKaazmG%>)_$u3%2O7iD17Y zo8TDsSHIfl>x02tePyIVtu`x>a^BkjW&|jUxxs7-h?GqL;?0fnp;v=(TRO5zP^M>ELyPO_UKgPJ0=d1n(e%|2dItf?APf8U{tRsuay z@?^x+SQVi++{3>5&DaUH^%z^S`4ZZO{~aN}92l%tEpZKDi0%+Y1z z0A|byayhwK7ev?DHj%15+uC*xxI%+h5**_&&us*?5}ua7P8Uub-|2Z3-4(j2gCG(;jIMY2IMNA`JeW~EYHVmJ(x6~!ipEa~mgtqs1j zckgdy((tLWq^zM{Q$;xl#(^;6g{&ir$KSe^%1tkpnlXMqXwb}jpj0<{Q%qm;m9plL zQr%6(`r3X0rgC#a!jzGF0FT4y2Tch7etB75TcPt*%UpG7tyUS4n1$Cjl&*9Lu=y>d zr4X~|Ug8VB%8R)1H|Lu@J3H?^DdIptb7o?HY zggGrz#_HcNXpbjzlc(s2@NH7WTUPpk!snJHCg?3}@w{(gd%i`2Wu+U{W#vv@mMfSt zDfqHqj!3o^A76&nue@k8EXx@m7)npzcK-DV?O@AsDGe(v$yMZHwBF}OTPxmOU0ig} zQI>u5jo7w4#lG&wUo2@`lqGhRv!rMq>NrAZG(K^ z!-Iz$6Vap3il`TC*)v&hTTtDd+{;uRfZD45wK@uZ7%!`nEuHJ+ohx)IQY-BS`UxZv zfTV@J4+}d{Z;s~9#@Oc9I)2LWRNjK&_i(s30L6l{&@@okF*VlHIsDt$eDrq;@uW(g zj&EKsg>Hz?R>Mt04h8au&Cq^#_wj$U0xEoA?&(xsB^`DS=q794Y@S#jvheisL(MJp zu-TG_HI8wCaFucs9?GOUP^3DjSqX|o@g^=rh}n1kWUprDPgHmcbCwO9y59;{$Yr=D zy`^)V^6DZBWYdKlMcF7rS{gS$2Z9vZ+AQ+T%+rv4wLNB{&{EqkfN@K_W26OxqomxuJ~OM3W!N%bGGa^D0n%VC@yM3m4tFBksm0q8Nh zrv}~6v-MJ@>cfE*_nLTWUsZp(J@IAgXd!twLS;_-+JRj*pRe>!sfw~V)o%qs)AlV* zJbx{`G(1YwjOM8nwhOIy-*AQwh|sQF;nz&>rW`0LUFr{EA35ehL2H7Q=N%P)3Lt=!+LlkVGs*C|+( z>pgotSQPdkDsizi!VU%@@=ZyaW?_U}3yY$ovlRk;Knz|1ek$eK%bWJ?ir|;F6k^-) z>nBA8ul>X~-lhoaia4mDMMw_S50>rWUOK-4qCN3)z+ z;ik#4f|b;Ll`Tq<2TSUxVXcPUUIb_1ugNhuZpXVF)l^aybnkb2LHBgb>TNaV z`vyYbs}{3CE(Pkzxm+%ZHiKbX8?`n;#OOs_8@qe)fe#NCiN33?91q15RY=6=Q1 zUF~}IgaconKkHkNp71H_F)n8~Y64(* z)X9_RDW4~Zs(r?rbw<6yQdTvdiN|eT`TK|L@yqZ~FJ!IXiO4UL&y`GNU*RfbYnM!` z-5tlZwn9`)e>Ci^8$M=#%U>d!BmAk3Wwfls(Jzyqk*>GkS-TulHjT(2inQh7-4~)_lYGyAOlM7!IkFjz6Fv+HG*1-Ja>JNoe zd0z|HN318KmQPHzIgG0wwo7jI4W==Q@=nfaFD5-bMQvQaIV8`+y{@L)SP)m;;z|V) zt%%ZhaA}8rZbAurAcHr!-6&t6+Q!(LY!NDUK}(d}%L;kV66+={1~PiK3nJ+@vbgsx z2#Y(5=6oOXXuni_x8Kw~{51|Qv2?1%-19K=yu1rkm0C%V5mOda zlCG~&)7RJMMBlolPwSxuF$^PeOY~MSKMb=plQuQ14Wm#5Ks8;=@;$ve2VW2kG6}W- WjYXy~;?G53Cc;ZEqEq~Q@_zu$K>mgR literal 0 HcmV?d00001 diff --git a/public/img/waffle-bg.gif b/public/img/waffle-bg.gif new file mode 100644 index 0000000000000000000000000000000000000000..658b38e2230106e9d699e568bd255e0c7ca372ea GIT binary patch literal 3170 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 literal 0 HcmV?d00001 diff --git a/public/img/wafflechat-logo.gif b/public/img/wafflechat-logo.gif new file mode 100644 index 0000000000000000000000000000000000000000..f43b986798d6744420b0cafcd7287872fcbf13b9 GIT binary patch literal 22571 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 literal 0 HcmV?d00001 diff --git a/public/js/chat.js b/public/js/chat.js new file mode 100644 index 0000000..f8478c1 --- /dev/null +++ b/public/js/chat.js @@ -0,0 +1,337 @@ +// This file is executed in the browser, when people visit /chat/ + +$(function(){ + + // getting the id of the room from the url + var id = Number(window.location.pathname.match(/\/chat\/(\d+)$/)[1]); + + // connect to the socket + var socket = io.connect('/socket'); + + // variables which hold the data for each person + var name = "", + email = "", + img = "", + friend = ""; + + // cache some jQuery objects + var section = $(".section"), + footer = $("footer"), + onConnect = $(".connected"), + inviteSomebody = $(".invite-textfield"), + personInside = $(".personinside"), + chatScreen = $(".chatscreen"), + left = $(".left"), + noMessages = $(".nomessages"), + tooManyPeople = $(".toomanypeople"); + + // some more jquery objects + var chatNickname = $(".nickname-chat"), + leftNickname = $(".nickname-left"), + loginForm = $(".loginForm"), + yourName = $("#yourName"), + yourEmail = $("#yourEmail"), + hisName = $("#hisName"), + hisEmail = $("#hisEmail"), + chatForm = $("#chatform"), + textarea = $("#message"), + messageTimeSent = $(".timesent"), + chats = $(".chats"); + + // these variables hold images + var ownerImage = $("#ownerImage"), + leftImage = $("#leftImage"), + noMessagesImage = $("#noMessagesImage"); + + + // on connection to server get the id of person's room + socket.on('connect', function(){ + + socket.emit('load', id); + }); + + // save the gravatar url + socket.on('img', function(data){ + img = data; + }); + + // receive the names and avatars of all people in the chat room + socket.on('peopleinchat', function(data){ + + if(data.number === 0){ + + showMessage("connected"); + + loginForm.on('submit', function(e){ + + e.preventDefault(); + + name = $.trim(yourName.val()); + + if(name.length < 1){ + alert("Please enter a nick name longer than 1 character!"); + return; + } + + email = yourEmail.val(); + + if(!isValid(email)) { + alert("Please enter a valid email!"); + } + else { + + showMessage("inviteSomebody"); + + // call the server-side function 'login' and send user's parameters + socket.emit('login', {user: name, avatar: email, id: id}); + } + + }); + } + + else if(data.number === 1) { + + showMessage("personinchat",data); + + loginForm.on('submit', function(e){ + + e.preventDefault(); + + name = $.trim(hisName.val()); + + if(name.length < 1){ + alert("Please enter a nick name longer than 1 character!"); + return; + } + + if(name == data.user){ + alert("There already is a \"" + name + "\" in this room!"); + return; + } + email = hisEmail.val(); + + if(!isValid(email)){ + alert("Wrong e-mail format!"); + } + else { + socket.emit('login', {user: name, avatar: email, id: id}); + } + + }); + } + + else { + showMessage("tooManyPeople"); + } + + }); + + // Other useful + + socket.on('startChat', function(data){ + console.log(data); + if(data.boolean && data.id == id) { + + chats.empty(); + + if(name === data.users[0]) { + + showMessage("youStartedChatWithNoMessages",data); + } + else { + + showMessage("heStartedChatWithNoMessages",data); + } + + chatNickname.text(friend); + } + }); + + socket.on('leave',function(data){ + + if(data.boolean && id==data.room){ + + showMessage("somebodyLeft", data); + chats.empty(); + } + + }); + + socket.on('tooMany', function(data){ + + if(data.boolean && name.length === 0) { + + showMessage('tooManyPeople'); + } + }); + + socket.on('receive', function(data){ + + showMessage('chatStarted'); + + if(data.msg.trim().length) { + createChatMessage(data.msg, data.user, data.img, moment()); + scrollToBottom(); + } + }); + + textarea.keypress(function(e){ + + // Submit the form on enter + + if(e.which == 13) { + e.preventDefault(); + chatForm.trigger('submit'); + } + + }); + + chatForm.on('submit', function(e){ + + e.preventDefault(); + + // Create a new chat message and display it directly + + showMessage("chatStarted"); + + if(textarea.val().trim().length) { + createChatMessage(textarea.val(), name, img, moment()); + scrollToBottom(); + + // Send the message to the other person in the chat + socket.emit('msg', {msg: textarea.val(), user: name, img: img}); + + } + // Empty the textarea + textarea.val(""); + }); + + // Update the relative time stamps on the chat messages every minute + + setInterval(function(){ + + messageTimeSent.each(function(){ + var each = moment($(this).data('time')); + $(this).text(each.fromNow()); + }); + + },60000); + + // Function that creates a new chat message + + function createChatMessage(msg,user,imgg,now){ + + var who = ''; + + if(user===name) { + who = 'me'; + } + else { + who = 'you'; + } + + var li = $( + '
  • '+ + '
    ' + + '' + + '' + + ' ' + + '
    ' + + '

    ' + + '
  • '); + + // use the 'text' method to escape malicious user input + li.find('p').text(msg); + li.find('b').text(user); + + chats.append(li); + + messageTimeSent = $(".timesent"); + messageTimeSent.last().text(now.fromNow()); + } + + function scrollToBottom(){ + $("html, body").animate({ scrollTop: $(document).height()-$(window).height() },1000); + } + + function isValid(thatemail) { + + var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + return re.test(thatemail); + } + + function showMessage(status,data){ + + if(status === "connected"){ + + section.children().css('display', 'none'); + onConnect.fadeIn(1200); + } + + else if(status === "inviteSomebody"){ + + // Set the invite link content + $("#link").text(window.location.href); + + onConnect.fadeOut(1200, function(){ + inviteSomebody.fadeIn(1200); + }); + } + + else if(status === "personinchat"){ + + onConnect.css("display", "none"); + personInside.fadeIn(1200); + + chatNickname.text(data.user); + ownerImage.attr("src",data.avatar); + } + + else if(status === "youStartedChatWithNoMessages") { + + left.fadeOut(1200, function() { + inviteSomebody.fadeOut(1200,function(){ + noMessages.fadeIn(1200); + footer.fadeIn(1200); + }); + }); + + friend = data.users[1]; + noMessagesImage.attr("src",data.avatars[1]); + } + + else if(status === "heStartedChatWithNoMessages") { + + personInside.fadeOut(1200,function(){ + noMessages.fadeIn(1200); + footer.fadeIn(1200); + }); + + friend = data.users[0]; + noMessagesImage.attr("src",data.avatars[0]); + } + + else if(status === "chatStarted"){ + + section.children().css('display','none'); + chatScreen.css('display','block'); + } + + else if(status === "somebodyLeft"){ + + leftImage.attr("src",data.avatar); + leftNickname.text(data.user); + + section.children().css('display','none'); + footer.css('display', 'none'); + left.fadeIn(1200); + } + + else if(status === "tooManyPeople") { + + section.children().css('display', 'none'); + tooManyPeople.fadeIn(1200); + } + } + +}); diff --git a/public/js/moment.min.js b/public/js/moment.min.js new file mode 100644 index 0000000..29e1cef --- /dev/null +++ b/public/js/moment.min.js @@ -0,0 +1,6 @@ +//! moment.js +//! version : 2.5.1 +//! authors : Tim Wood, Iskren Chernev, Moment.js contributors +//! license : MIT +//! momentjs.com +(function(a){function b(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1}}function c(a,b){return function(c){return k(a.call(this,c),b)}}function d(a,b){return function(c){return this.lang().ordinal(a.call(this,c),b)}}function e(){}function f(a){w(a),h(this,a)}function g(a){var b=q(a),c=b.year||0,d=b.month||0,e=b.week||0,f=b.day||0,g=b.hour||0,h=b.minute||0,i=b.second||0,j=b.millisecond||0;this._milliseconds=+j+1e3*i+6e4*h+36e5*g,this._days=+f+7*e,this._months=+d+12*c,this._data={},this._bubble()}function h(a,b){for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return b.hasOwnProperty("toString")&&(a.toString=b.toString),b.hasOwnProperty("valueOf")&&(a.valueOf=b.valueOf),a}function i(a){var b,c={};for(b in a)a.hasOwnProperty(b)&&qb.hasOwnProperty(b)&&(c[b]=a[b]);return c}function j(a){return 0>a?Math.ceil(a):Math.floor(a)}function k(a,b,c){for(var d=""+Math.abs(a),e=a>=0;d.lengthd;d++)(c&&a[d]!==b[d]||!c&&s(a[d])!==s(b[d]))&&g++;return g+f}function p(a){if(a){var b=a.toLowerCase().replace(/(.)s$/,"$1");a=Tb[a]||Ub[b]||b}return a}function q(a){var b,c,d={};for(c in a)a.hasOwnProperty(c)&&(b=p(c),b&&(d[b]=a[c]));return d}function r(b){var c,d;if(0===b.indexOf("week"))c=7,d="day";else{if(0!==b.indexOf("month"))return;c=12,d="month"}db[b]=function(e,f){var g,h,i=db.fn._lang[b],j=[];if("number"==typeof e&&(f=e,e=a),h=function(a){var b=db().utc().set(d,a);return i.call(db.fn._lang,b,e||"")},null!=f)return h(f);for(g=0;c>g;g++)j.push(h(g));return j}}function s(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=b>=0?Math.floor(b):Math.ceil(b)),c}function t(a,b){return new Date(Date.UTC(a,b+1,0)).getUTCDate()}function u(a){return v(a)?366:365}function v(a){return a%4===0&&a%100!==0||a%400===0}function w(a){var b;a._a&&-2===a._pf.overflow&&(b=a._a[jb]<0||a._a[jb]>11?jb:a._a[kb]<1||a._a[kb]>t(a._a[ib],a._a[jb])?kb:a._a[lb]<0||a._a[lb]>23?lb:a._a[mb]<0||a._a[mb]>59?mb:a._a[nb]<0||a._a[nb]>59?nb:a._a[ob]<0||a._a[ob]>999?ob:-1,a._pf._overflowDayOfYear&&(ib>b||b>kb)&&(b=kb),a._pf.overflow=b)}function x(a){return null==a._isValid&&(a._isValid=!isNaN(a._d.getTime())&&a._pf.overflow<0&&!a._pf.empty&&!a._pf.invalidMonth&&!a._pf.nullInput&&!a._pf.invalidFormat&&!a._pf.userInvalidated,a._strict&&(a._isValid=a._isValid&&0===a._pf.charsLeftOver&&0===a._pf.unusedTokens.length)),a._isValid}function y(a){return a?a.toLowerCase().replace("_","-"):a}function z(a,b){return b._isUTC?db(a).zone(b._offset||0):db(a).local()}function A(a,b){return b.abbr=a,pb[a]||(pb[a]=new e),pb[a].set(b),pb[a]}function B(a){delete pb[a]}function C(a){var b,c,d,e,f=0,g=function(a){if(!pb[a]&&rb)try{require("./lang/"+a)}catch(b){}return pb[a]};if(!a)return db.fn._lang;if(!m(a)){if(c=g(a))return c;a=[a]}for(;f0;){if(c=g(e.slice(0,b).join("-")))return c;if(d&&d.length>=b&&o(e,d,!0)>=b-1)break;b--}f++}return db.fn._lang}function D(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function E(a){var b,c,d=a.match(vb);for(b=0,c=d.length;c>b;b++)d[b]=Yb[d[b]]?Yb[d[b]]:D(d[b]);return function(e){var f="";for(b=0;c>b;b++)f+=d[b]instanceof Function?d[b].call(e,a):d[b];return f}}function F(a,b){return a.isValid()?(b=G(b,a.lang()),Vb[b]||(Vb[b]=E(b)),Vb[b](a)):a.lang().invalidDate()}function G(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(wb.lastIndex=0;d>=0&&wb.test(a);)a=a.replace(wb,c),wb.lastIndex=0,d-=1;return a}function H(a,b){var c,d=b._strict;switch(a){case"DDDD":return Ib;case"YYYY":case"GGGG":case"gggg":return d?Jb:zb;case"Y":case"G":case"g":return Lb;case"YYYYYY":case"YYYYY":case"GGGGG":case"ggggg":return d?Kb:Ab;case"S":if(d)return Gb;case"SS":if(d)return Hb;case"SSS":if(d)return Ib;case"DDD":return yb;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":return Cb;case"a":case"A":return C(b._l)._meridiemParse;case"X":return Fb;case"Z":case"ZZ":return Db;case"T":return Eb;case"SSSS":return Bb;case"MM":case"DD":case"YY":case"GG":case"gg":case"HH":case"hh":case"mm":case"ss":case"ww":case"WW":return d?Hb:xb;case"M":case"D":case"d":case"H":case"h":case"m":case"s":case"w":case"W":case"e":case"E":return xb;default:return c=new RegExp(P(O(a.replace("\\","")),"i"))}}function I(a){a=a||"";var b=a.match(Db)||[],c=b[b.length-1]||[],d=(c+"").match(Qb)||["-",0,0],e=+(60*d[1])+s(d[2]);return"+"===d[0]?-e:e}function J(a,b,c){var d,e=c._a;switch(a){case"M":case"MM":null!=b&&(e[jb]=s(b)-1);break;case"MMM":case"MMMM":d=C(c._l).monthsParse(b),null!=d?e[jb]=d:c._pf.invalidMonth=b;break;case"D":case"DD":null!=b&&(e[kb]=s(b));break;case"DDD":case"DDDD":null!=b&&(c._dayOfYear=s(b));break;case"YY":e[ib]=s(b)+(s(b)>68?1900:2e3);break;case"YYYY":case"YYYYY":case"YYYYYY":e[ib]=s(b);break;case"a":case"A":c._isPm=C(c._l).isPM(b);break;case"H":case"HH":case"h":case"hh":e[lb]=s(b);break;case"m":case"mm":e[mb]=s(b);break;case"s":case"ss":e[nb]=s(b);break;case"S":case"SS":case"SSS":case"SSSS":e[ob]=s(1e3*("0."+b));break;case"X":c._d=new Date(1e3*parseFloat(b));break;case"Z":case"ZZ":c._useUTC=!0,c._tzm=I(b);break;case"w":case"ww":case"W":case"WW":case"d":case"dd":case"ddd":case"dddd":case"e":case"E":a=a.substr(0,1);case"gg":case"gggg":case"GG":case"GGGG":case"GGGGG":a=a.substr(0,2),b&&(c._w=c._w||{},c._w[a]=b)}}function K(a){var b,c,d,e,f,g,h,i,j,k,l=[];if(!a._d){for(d=M(a),a._w&&null==a._a[kb]&&null==a._a[jb]&&(f=function(b){var c=parseInt(b,10);return b?b.length<3?c>68?1900+c:2e3+c:c:null==a._a[ib]?db().weekYear():a._a[ib]},g=a._w,null!=g.GG||null!=g.W||null!=g.E?h=Z(f(g.GG),g.W||1,g.E,4,1):(i=C(a._l),j=null!=g.d?V(g.d,i):null!=g.e?parseInt(g.e,10)+i._week.dow:0,k=parseInt(g.w,10)||1,null!=g.d&&ju(e)&&(a._pf._overflowDayOfYear=!0),c=U(e,0,a._dayOfYear),a._a[jb]=c.getUTCMonth(),a._a[kb]=c.getUTCDate()),b=0;3>b&&null==a._a[b];++b)a._a[b]=l[b]=d[b];for(;7>b;b++)a._a[b]=l[b]=null==a._a[b]?2===b?1:0:a._a[b];l[lb]+=s((a._tzm||0)/60),l[mb]+=s((a._tzm||0)%60),a._d=(a._useUTC?U:T).apply(null,l)}}function L(a){var b;a._d||(b=q(a._i),a._a=[b.year,b.month,b.day,b.hour,b.minute,b.second,b.millisecond],K(a))}function M(a){var b=new Date;return a._useUTC?[b.getUTCFullYear(),b.getUTCMonth(),b.getUTCDate()]:[b.getFullYear(),b.getMonth(),b.getDate()]}function N(a){a._a=[],a._pf.empty=!0;var b,c,d,e,f,g=C(a._l),h=""+a._i,i=h.length,j=0;for(d=G(a._f,g).match(vb)||[],b=0;b0&&a._pf.unusedInput.push(f),h=h.slice(h.indexOf(c)+c.length),j+=c.length),Yb[e]?(c?a._pf.empty=!1:a._pf.unusedTokens.push(e),J(e,c,a)):a._strict&&!c&&a._pf.unusedTokens.push(e);a._pf.charsLeftOver=i-j,h.length>0&&a._pf.unusedInput.push(h),a._isPm&&a._a[lb]<12&&(a._a[lb]+=12),a._isPm===!1&&12===a._a[lb]&&(a._a[lb]=0),K(a),w(a)}function O(a){return a.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e})}function P(a){return a.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function Q(a){var c,d,e,f,g;if(0===a._f.length)return a._pf.invalidFormat=!0,a._d=new Date(0/0),void 0;for(f=0;fg)&&(e=g,d=c));h(a,d||c)}function R(a){var b,c,d=a._i,e=Mb.exec(d);if(e){for(a._pf.iso=!0,b=0,c=Ob.length;c>b;b++)if(Ob[b][1].exec(d)){a._f=Ob[b][0]+(e[6]||" ");break}for(b=0,c=Pb.length;c>b;b++)if(Pb[b][1].exec(d)){a._f+=Pb[b][0];break}d.match(Db)&&(a._f+="Z"),N(a)}else a._d=new Date(d)}function S(b){var c=b._i,d=sb.exec(c);c===a?b._d=new Date:d?b._d=new Date(+d[1]):"string"==typeof c?R(b):m(c)?(b._a=c.slice(0),K(b)):n(c)?b._d=new Date(+c):"object"==typeof c?L(b):b._d=new Date(c)}function T(a,b,c,d,e,f,g){var h=new Date(a,b,c,d,e,f,g);return 1970>a&&h.setFullYear(a),h}function U(a){var b=new Date(Date.UTC.apply(null,arguments));return 1970>a&&b.setUTCFullYear(a),b}function V(a,b){if("string"==typeof a)if(isNaN(a)){if(a=b.weekdaysParse(a),"number"!=typeof a)return null}else a=parseInt(a,10);return a}function W(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function X(a,b,c){var d=hb(Math.abs(a)/1e3),e=hb(d/60),f=hb(e/60),g=hb(f/24),h=hb(g/365),i=45>d&&["s",d]||1===e&&["m"]||45>e&&["mm",e]||1===f&&["h"]||22>f&&["hh",f]||1===g&&["d"]||25>=g&&["dd",g]||45>=g&&["M"]||345>g&&["MM",hb(g/30)]||1===h&&["y"]||["yy",h];return i[2]=b,i[3]=a>0,i[4]=c,W.apply({},i)}function Y(a,b,c){var d,e=c-b,f=c-a.day();return f>e&&(f-=7),e-7>f&&(f+=7),d=db(a).add("d",f),{week:Math.ceil(d.dayOfYear()/7),year:d.year()}}function Z(a,b,c,d,e){var f,g,h=U(a,0,1).getUTCDay();return c=null!=c?c:e,f=e-h+(h>d?7:0)-(e>h?7:0),g=7*(b-1)+(c-e)+f+1,{year:g>0?a:a-1,dayOfYear:g>0?g:u(a-1)+g}}function $(a){var b=a._i,c=a._f;return null===b?db.invalid({nullInput:!0}):("string"==typeof b&&(a._i=b=C().preparse(b)),db.isMoment(b)?(a=i(b),a._d=new Date(+b._d)):c?m(c)?Q(a):N(a):S(a),new f(a))}function _(a,b){db.fn[a]=db.fn[a+"s"]=function(a){var c=this._isUTC?"UTC":"";return null!=a?(this._d["set"+c+b](a),db.updateOffset(this),this):this._d["get"+c+b]()}}function ab(a){db.duration.fn[a]=function(){return this._data[a]}}function bb(a,b){db.duration.fn["as"+a]=function(){return+this/b}}function cb(a){var b=!1,c=db;"undefined"==typeof ender&&(a?(gb.moment=function(){return!b&&console&&console.warn&&(b=!0,console.warn("Accessing Moment through the global scope is deprecated, and will be removed in an upcoming release.")),c.apply(null,arguments)},h(gb.moment,c)):gb.moment=db)}for(var db,eb,fb="2.5.1",gb=this,hb=Math.round,ib=0,jb=1,kb=2,lb=3,mb=4,nb=5,ob=6,pb={},qb={_isAMomentObject:null,_i:null,_f:null,_l:null,_strict:null,_isUTC:null,_offset:null,_pf:null,_lang:null},rb="undefined"!=typeof module&&module.exports&&"undefined"!=typeof require,sb=/^\/?Date\((\-?\d+)/i,tb=/(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,ub=/^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/,vb=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g,wb=/(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,xb=/\d\d?/,yb=/\d{1,3}/,zb=/\d{1,4}/,Ab=/[+\-]?\d{1,6}/,Bb=/\d+/,Cb=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,Db=/Z|[\+\-]\d\d:?\d\d/gi,Eb=/T/i,Fb=/[\+\-]?\d+(\.\d{1,3})?/,Gb=/\d/,Hb=/\d\d/,Ib=/\d{3}/,Jb=/\d{4}/,Kb=/[+-]?\d{6}/,Lb=/[+-]?\d+/,Mb=/^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,Nb="YYYY-MM-DDTHH:mm:ssZ",Ob=[["YYYYYY-MM-DD",/[+-]\d{6}-\d{2}-\d{2}/],["YYYY-MM-DD",/\d{4}-\d{2}-\d{2}/],["GGGG-[W]WW-E",/\d{4}-W\d{2}-\d/],["GGGG-[W]WW",/\d{4}-W\d{2}/],["YYYY-DDD",/\d{4}-\d{3}/]],Pb=[["HH:mm:ss.SSSS",/(T| )\d\d:\d\d:\d\d\.\d{1,3}/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],Qb=/([\+\-]|\d\d)/gi,Rb="Date|Hours|Minutes|Seconds|Milliseconds".split("|"),Sb={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6},Tb={ms:"millisecond",s:"second",m:"minute",h:"hour",d:"day",D:"date",w:"week",W:"isoWeek",M:"month",y:"year",DDD:"dayOfYear",e:"weekday",E:"isoWeekday",gg:"weekYear",GG:"isoWeekYear"},Ub={dayofyear:"dayOfYear",isoweekday:"isoWeekday",isoweek:"isoWeek",weekyear:"weekYear",isoweekyear:"isoWeekYear"},Vb={},Wb="DDD w W M D d".split(" "),Xb="M D H h m s w W".split(" "),Yb={M:function(){return this.month()+1},MMM:function(a){return this.lang().monthsShort(this,a)},MMMM:function(a){return this.lang().months(this,a)},D:function(){return this.date()},DDD:function(){return this.dayOfYear()},d:function(){return this.day()},dd:function(a){return this.lang().weekdaysMin(this,a)},ddd:function(a){return this.lang().weekdaysShort(this,a)},dddd:function(a){return this.lang().weekdays(this,a)},w:function(){return this.week()},W:function(){return this.isoWeek()},YY:function(){return k(this.year()%100,2)},YYYY:function(){return k(this.year(),4)},YYYYY:function(){return k(this.year(),5)},YYYYYY:function(){var a=this.year(),b=a>=0?"+":"-";return b+k(Math.abs(a),6)},gg:function(){return k(this.weekYear()%100,2)},gggg:function(){return k(this.weekYear(),4)},ggggg:function(){return k(this.weekYear(),5)},GG:function(){return k(this.isoWeekYear()%100,2)},GGGG:function(){return k(this.isoWeekYear(),4)},GGGGG:function(){return k(this.isoWeekYear(),5)},e:function(){return this.weekday()},E:function(){return this.isoWeekday()},a:function(){return this.lang().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.lang().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return s(this.milliseconds()/100)},SS:function(){return k(s(this.milliseconds()/10),2)},SSS:function(){return k(this.milliseconds(),3)},SSSS:function(){return k(this.milliseconds(),3)},Z:function(){var a=-this.zone(),b="+";return 0>a&&(a=-a,b="-"),b+k(s(a/60),2)+":"+k(s(a)%60,2)},ZZ:function(){var a=-this.zone(),b="+";return 0>a&&(a=-a,b="-"),b+k(s(a/60),2)+k(s(a)%60,2)},z:function(){return this.zoneAbbr()},zz:function(){return this.zoneName()},X:function(){return this.unix()},Q:function(){return this.quarter()}},Zb=["months","monthsShort","weekdays","weekdaysShort","weekdaysMin"];Wb.length;)eb=Wb.pop(),Yb[eb+"o"]=d(Yb[eb],eb);for(;Xb.length;)eb=Xb.pop(),Yb[eb+eb]=c(Yb[eb],2);for(Yb.DDDD=c(Yb.DDD,3),h(e.prototype,{set:function(a){var b,c;for(c in a)b=a[c],"function"==typeof b?this[c]=b:this["_"+c]=b},_months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),months:function(a){return this._months[a.month()]},_monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),monthsShort:function(a){return this._monthsShort[a.month()]},monthsParse:function(a){var b,c,d;for(this._monthsParse||(this._monthsParse=[]),b=0;12>b;b++)if(this._monthsParse[b]||(c=db.utc([2e3,b]),d="^"+this.months(c,"")+"|^"+this.monthsShort(c,""),this._monthsParse[b]=new RegExp(d.replace(".",""),"i")),this._monthsParse[b].test(a))return b},_weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdays:function(a){return this._weekdays[a.day()]},_weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysShort:function(a){return this._weekdaysShort[a.day()]},_weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),weekdaysMin:function(a){return this._weekdaysMin[a.day()]},weekdaysParse:function(a){var b,c,d;for(this._weekdaysParse||(this._weekdaysParse=[]),b=0;7>b;b++)if(this._weekdaysParse[b]||(c=db([2e3,1]).day(b),d="^"+this.weekdays(c,"")+"|^"+this.weekdaysShort(c,"")+"|^"+this.weekdaysMin(c,""),this._weekdaysParse[b]=new RegExp(d.replace(".",""),"i")),this._weekdaysParse[b].test(a))return b},_longDateFormat:{LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D YYYY",LLL:"MMMM D YYYY LT",LLLL:"dddd, MMMM D YYYY LT"},longDateFormat:function(a){var b=this._longDateFormat[a];return!b&&this._longDateFormat[a.toUpperCase()]&&(b=this._longDateFormat[a.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a]=b),b},isPM:function(a){return"p"===(a+"").toLowerCase().charAt(0)},_meridiemParse:/[ap]\.?m?\.?/i,meridiem:function(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},calendar:function(a,b){var c=this._calendar[a];return"function"==typeof c?c.apply(b):c},_relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},relativeTime:function(a,b,c,d){var e=this._relativeTime[c];return"function"==typeof e?e(a,b,c,d):e.replace(/%d/i,a)},pastFuture:function(a,b){var c=this._relativeTime[a>0?"future":"past"];return"function"==typeof c?c(b):c.replace(/%s/i,b)},ordinal:function(a){return this._ordinal.replace("%d",a)},_ordinal:"%d",preparse:function(a){return a},postformat:function(a){return a},week:function(a){return Y(a,this._week.dow,this._week.doy).week},_week:{dow:0,doy:6},_invalidDate:"Invalid date",invalidDate:function(){return this._invalidDate}}),db=function(c,d,e,f){var g;return"boolean"==typeof e&&(f=e,e=a),g={},g._isAMomentObject=!0,g._i=c,g._f=d,g._l=e,g._strict=f,g._isUTC=!1,g._pf=b(),$(g)},db.utc=function(c,d,e,f){var g;return"boolean"==typeof e&&(f=e,e=a),g={},g._isAMomentObject=!0,g._useUTC=!0,g._isUTC=!0,g._l=e,g._i=c,g._f=d,g._strict=f,g._pf=b(),$(g).utc()},db.unix=function(a){return db(1e3*a)},db.duration=function(a,b){var c,d,e,f=a,h=null;return db.isDuration(a)?f={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(f={},b?f[b]=a:f.milliseconds=a):(h=tb.exec(a))?(c="-"===h[1]?-1:1,f={y:0,d:s(h[kb])*c,h:s(h[lb])*c,m:s(h[mb])*c,s:s(h[nb])*c,ms:s(h[ob])*c}):(h=ub.exec(a))&&(c="-"===h[1]?-1:1,e=function(a){var b=a&&parseFloat(a.replace(",","."));return(isNaN(b)?0:b)*c},f={y:e(h[2]),M:e(h[3]),d:e(h[4]),h:e(h[5]),m:e(h[6]),s:e(h[7]),w:e(h[8])}),d=new g(f),db.isDuration(a)&&a.hasOwnProperty("_lang")&&(d._lang=a._lang),d},db.version=fb,db.defaultFormat=Nb,db.updateOffset=function(){},db.lang=function(a,b){var c;return a?(b?A(y(a),b):null===b?(B(a),a="en"):pb[a]||C(a),c=db.duration.fn._lang=db.fn._lang=C(a),c._abbr):db.fn._lang._abbr},db.langData=function(a){return a&&a._lang&&a._lang._abbr&&(a=a._lang._abbr),C(a)},db.isMoment=function(a){return a instanceof f||null!=a&&a.hasOwnProperty("_isAMomentObject")},db.isDuration=function(a){return a instanceof g},eb=Zb.length-1;eb>=0;--eb)r(Zb[eb]);for(db.normalizeUnits=function(a){return p(a)},db.invalid=function(a){var b=db.utc(0/0);return null!=a?h(b._pf,a):b._pf.userInvalidated=!0,b},db.parseZone=function(a){return db(a).parseZone()},h(db.fn=f.prototype,{clone:function(){return db(this)},valueOf:function(){return+this._d+6e4*(this._offset||0)},unix:function(){return Math.floor(+this/1e3)},toString:function(){return this.clone().lang("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._offset?new Date(+this):this._d},toISOString:function(){var a=db(this).utc();return 00:!1},parsingFlags:function(){return h({},this._pf)},invalidAt:function(){return this._pf.overflow},utc:function(){return this.zone(0)},local:function(){return this.zone(0),this._isUTC=!1,this},format:function(a){var b=F(this,a||db.defaultFormat);return this.lang().postformat(b)},add:function(a,b){var c;return c="string"==typeof a?db.duration(+b,a):db.duration(a,b),l(this,c,1),this},subtract:function(a,b){var c;return c="string"==typeof a?db.duration(+b,a):db.duration(a,b),l(this,c,-1),this},diff:function(a,b,c){var d,e,f=z(a,this),g=6e4*(this.zone()-f.zone());return b=p(b),"year"===b||"month"===b?(d=432e5*(this.daysInMonth()+f.daysInMonth()),e=12*(this.year()-f.year())+(this.month()-f.month()),e+=(this-db(this).startOf("month")-(f-db(f).startOf("month")))/d,e-=6e4*(this.zone()-db(this).startOf("month").zone()-(f.zone()-db(f).startOf("month").zone()))/d,"year"===b&&(e/=12)):(d=this-f,e="second"===b?d/1e3:"minute"===b?d/6e4:"hour"===b?d/36e5:"day"===b?(d-g)/864e5:"week"===b?(d-g)/6048e5:d),c?e:j(e)},from:function(a,b){return db.duration(this.diff(a)).lang(this.lang()._abbr).humanize(!b)},fromNow:function(a){return this.from(db(),a)},calendar:function(){var a=z(db(),this).startOf("day"),b=this.diff(a,"days",!0),c=-6>b?"sameElse":-1>b?"lastWeek":0>b?"lastDay":1>b?"sameDay":2>b?"nextDay":7>b?"nextWeek":"sameElse";return this.format(this.lang().calendar(c,this))},isLeapYear:function(){return v(this.year())},isDST:function(){return this.zone()+db(a).startOf(b)},isBefore:function(a,b){return b="undefined"!=typeof b?b:"millisecond",+this.clone().startOf(b)<+db(a).startOf(b)},isSame:function(a,b){return b=b||"ms",+this.clone().startOf(b)===+z(a,this).startOf(b)},min:function(a){return a=db.apply(null,arguments),this>a?this:a},max:function(a){return a=db.apply(null,arguments),a>this?this:a},zone:function(a){var b=this._offset||0;return null==a?this._isUTC?b:this._d.getTimezoneOffset():("string"==typeof a&&(a=I(a)),Math.abs(a)<16&&(a=60*a),this._offset=a,this._isUTC=!0,b!==a&&l(this,db.duration(b-a,"m"),1,!0),this)},zoneAbbr:function(){return this._isUTC?"UTC":""},zoneName:function(){return this._isUTC?"Coordinated Universal Time":""},parseZone:function(){return this._tzm?this.zone(this._tzm):"string"==typeof this._i&&this.zone(this._i),this},hasAlignedHourOffset:function(a){return a=a?db(a).zone():0,(this.zone()-a)%60===0},daysInMonth:function(){return t(this.year(),this.month())},dayOfYear:function(a){var b=hb((db(this).startOf("day")-db(this).startOf("year"))/864e5)+1;return null==a?b:this.add("d",a-b)},quarter:function(){return Math.ceil((this.month()+1)/3)},weekYear:function(a){var b=Y(this,this.lang()._week.dow,this.lang()._week.doy).year;return null==a?b:this.add("y",a-b)},isoWeekYear:function(a){var b=Y(this,1,4).year;return null==a?b:this.add("y",a-b)},week:function(a){var b=this.lang().week(this);return null==a?b:this.add("d",7*(a-b))},isoWeek:function(a){var b=Y(this,1,4).week;return null==a?b:this.add("d",7*(a-b))},weekday:function(a){var b=(this.day()+7-this.lang()._week.dow)%7;return null==a?b:this.add("d",a-b)},isoWeekday:function(a){return null==a?this.day()||7:this.day(this.day()%7?a:a-7)},get:function(a){return a=p(a),this[a]()},set:function(a,b){return a=p(a),"function"==typeof this[a]&&this[a](b),this},lang:function(b){return b===a?this._lang:(this._lang=C(b),this)}}),eb=0;eb= 2) { + + chat.emit('tooMany', {boolean: true}); + } + }); + + // When the client emits 'login', save his name and avatar, + // and add them to the room + socket.on('login', function(data) { + + var room = findClientsSocket(io, data.id, '/socket'); + // Only two people per room are allowed + if (room.length < 2) { + + // Use the socket object to store data. Each client gets + // their own unique socket object + + socket.username = data.user; + socket.room = data.id; + socket.avatar = gravatar.url(data.avatar, {s: '140', r: 'x', d: 'mm'}); + + // Tell the person what he should use for an avatar + socket.emit('img', socket.avatar); + + + // Add the client to the room + socket.join(data.id); + + if (room.length == 1) { + + var usernames = [], + avatars = []; + + usernames.push(room[0].username); + usernames.push(socket.username); + + avatars.push(room[0].avatar); + avatars.push(socket.avatar); + + // Send the startChat event to all the people in the + // room, along with a list of people that are in it. + + chat.in(data.id).emit('startChat', { + boolean: true, + id: data.id, + users: usernames, + avatars: avatars + }); + } + } + else { + socket.emit('tooMany', {boolean: true}); + } + }); + + // Somebody left the chat + socket.on('disconnect', function() { + + // Notify the other person in the chat room + // that his partner has left + + socket.broadcast.to(this.room).emit('leave', { + boolean: true, + room: this.room, + user: this.username, + avatar: this.avatar + }); + + // leave the room + socket.leave(socket.room); + }); + + + // Handle the sending of messages + socket.on('msg', function(data){ + + // When the server receives a message, it sends it to the other person in the room. + socket.broadcast.to(socket.room).emit('receive', {msg: data.msg, user: data.user, img: data.img}); + }); + }); +}; + +function findClientsSocket(io,roomId, namespace) { + var res = [], + ns = io.of(namespace ||"/"); // the default namespace is "/" + + if (ns) { + for (var id in ns.connected) { + if(roomId) { + var index = ns.connected[id].rooms.indexOf(roomId) ; + if(index !== -1) { + res.push(ns.connected[id]); + } + } + else { + res.push(ns.connected[id]); + } + } + } + return res; +} + + diff --git a/tpl/page.jade b/tpl/page.jade deleted file mode 100644 index 7517b2e..0000000 --- a/tpl/page.jade +++ /dev/null @@ -1,14 +0,0 @@ -doctype -html -head - title= "WaffleChat" - script(src='/chat.js') - script(src='/socket.io/socket.io.js') -body - #content(style='width: 500px; height: 300px; margin: 0 0 20px 0; border: solid 1px #999; overflow-y: scroll;') - .controls - | Name: - input#name(style='width:350px;') - br - input#field(style='width:350px;') - input#send(type='button', value='send') \ No newline at end of file diff --git a/tpl/page.jade~ b/tpl/page.jade~ deleted file mode 100644 index 3fad8d3..0000000 --- a/tpl/page.jade~ +++ /dev/null @@ -1,11 +0,0 @@ -doctype -html -head - title= "WaffleChat" - script(src='/chat.js') - script(src='/socket.io/socket.io.js') -body - #content(style='width: 500px; height: 300px; margin: 0 0 20px 0; border: solid 1px #999; overflow-y: scroll;') - .controls - input.field(style='width:350px;') - input.send(type='button', value='send') \ No newline at end of file diff --git a/views/chat.html b/views/chat.html new file mode 100644 index 0000000..f57ce7a --- /dev/null +++ b/views/chat.html @@ -0,0 +1,129 @@ + + + + + + + + + Private chat room | WaffleChat + + + + + + + + + +
    + + + +
    + + + +
    +

    Who are you?

    +
    + +
    +
    +
    + +
    + +
    + +
    + +
    + + + +
    +

    Chat with

    +
    + +
    +
    +
    + +
    + +
    + +
    + +
    + +

    Oops, there are no other people in this chat!

    +
    Invite a friend by sending them this URL
    + + + +
    + +
    + + + +
    +

    has left the chat.

    +
    Invite somebody else by sending them this page.
    +
    + +
    + +
    + +

    Sorry. This chat is unavailable.

    +
    There are already two people in this room. Would you like to start a new room?
    + +
    + +
    + + + +
    +

    You are chatting with .

    +
    Send them a message from the form below!
    +
    + +
    + +
    + +
      + +
    + +
    + +
    + +
    + +
    + + + + +
    + +
    + + + + + + + + + \ No newline at end of file diff --git a/views/home.html b/views/home.html new file mode 100644 index 0000000..fc84148 --- /dev/null +++ b/views/home.html @@ -0,0 +1,39 @@ + + + + + + + + + Create a chat room | WaffleChat + + + + + + + + +
    + + + +
    + + + diff --git a/wafflechat.js b/wafflechat.js deleted file mode 100644 index 4df3c56..0000000 --- a/wafflechat.js +++ /dev/null @@ -1,22 +0,0 @@ -var express = require("express"); -var app = express(); -var port = 80; - -app.set('views', __dirname + '/tpl'); -app.set('view engine', "jade"); -app.engine('jade', require('jade').__express); -app.get("/", function(req, res){ - res.render("page"); -}); - -app.use(express.static(__dirname + '/public')); - -var io = require('socket.io').listen(app.listen(port)); -console.log("Listening on port " + port); - -io.sockets.on('connection', function (socket) { - socket.emit('message', { message: 'welcome to the chat' }); - socket.on('send', function (data) { - io.sockets.emit('message', data); - }); -});