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 0000000..d4a1c44 Binary files /dev/null and b/public/img/nodejslogo.png differ diff --git a/public/img/unnamed.jpg b/public/img/unnamed.jpg new file mode 100644 index 0000000..c95c656 Binary files /dev/null and b/public/img/unnamed.jpg differ diff --git a/public/img/waffle-bg.gif b/public/img/waffle-bg.gif new file mode 100644 index 0000000..658b38e Binary files /dev/null and b/public/img/waffle-bg.gif differ diff --git a/public/img/wafflechat-logo.gif b/public/img/wafflechat-logo.gif new file mode 100644 index 0000000..f43b986 Binary files /dev/null and b/public/img/wafflechat-logo.gif differ 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); - }); -});