First commit

This commit is contained in:
Fergal Moran
2014-08-24 20:16:59 +01:00
commit ff32d35b71
16 changed files with 644 additions and 0 deletions

3
.bowerrc Normal file
View File

@@ -0,0 +1,3 @@
{
"directory": "public/bower_components"
}

13
.editorconfig Normal file
View File

@@ -0,0 +1,13 @@
# http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

28
.gitignore vendored Normal file
View File

@@ -0,0 +1,28 @@
# Logs
logs
*.log
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directory
# Deployed apps should consider commenting this line out:
# see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git
node_modules
bower_components
.idea
.DS_Store

21
.jshintrc Normal file
View File

@@ -0,0 +1,21 @@
{
"node": true,
"esnext": true,
"bitwise": true,
"camelcase": true,
"curly": true,
"eqeqeq": true,
"immed": true,
"indent": 4,
"latedef": true,
"newcap": true,
"noarg": true,
"quotmark": "single",
"regexp": true,
"undef": true,
"unused": true,
"strict": true,
"trailing": true,
"smarttabs": true,
"white": true
}

2
.nodemonignore Normal file
View File

@@ -0,0 +1,2 @@
# Generated by grunt-nodemon
node_modules/**

210
Gruntfile.js Normal file
View File

@@ -0,0 +1,210 @@
// Generated on 2014-08-23 using generator-socketio 0.0.3
'use strict';
var moment = require('moment');
var LIVERELOAD_PORT = 35729;
var RUNNING_PORT = 8001; // <- if you change this, you need to change in public/js/app.js and recompile
var lrSnippet = require('connect-livereload')({port: LIVERELOAD_PORT});
var mountFolder = function (connect, dir) {
return connect.static(require('path').resolve(dir));
};
module.exports = function (grunt) {
// load all grunt tasks
require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
grunt.initConfig({
cssmin: {
combine: {
files: {
'public/css/core.css': 'public/bower_components/bootstrap.css/css/bootstrap.css'
}
}
},
less: {
options: {
//report:'gzip'
},
production: {
options: {
cleancss: true
},
files: {
"public/css/core.css": "public/bower_components/bootstrap/less/bootstrap.less"
}
}
},
sass: {
dist: {
options: {
style: 'compressed'
},
files: {
'public/css/core.css': 'public/bower_components/sass-bootstrap/lib/bootstrap.scss',
}
}
},
stylus: {
compile: {
options: {
compress:true
},
files: {
'public/css/core.css': 'public/bower_components/bootstrap-stylus/stylus/bootstrap.styl'
}
}
},
concat: {
options: {
separator: ';',
stripBanners:true
},
dist: {
src: ['public/js/app.js'],
dest: 'public/js/concat.js',
},
},
//this is currently turned off, since jquery KILLS it
jshint: {
options: {
curly: true,
eqeqeq: false,
eqnull: true,
browser: true,
globals: {
jQuery: true
}
},
files:{
src:['public/js/concat.js']
}
},
uglify: {
options: {
mangle: false
},
my_target: {
files: {
'public/js/app.min.js': ['public/js/concat.js']
}
}
},
// Watch Config
watch: {
files: ['views/**/*'],
options: {
livereload: true
},
scripts: {
files: [
'public/js/**/*.js'
],
tasks:['build']
},
css: {
files: [
'public/css/**/*.css',
],
},
less: {
files: ['public/bower_components/bootstrap/less/**/*.less'],
tasks: ['build']
},
express: {
files: [ 'server.js', '!**/node_modules/**', '!Gruntfile.js' ],
tasks: [ 'watch' ],
options: {
nospawn: true // Without this option specified express won't be reloaded
}
},
},
connect: {
options: {
port: RUNNING_PORT,//variable at top of this file
// change this to '0.0.0.0' to access the server from outside
hostname: 'localhost'
},
livereload: {
options: {
middleware: function (connect) {
return [
lrSnippet,
mountFolder(connect, '.')
];
}
}
}
},
nodemon:{
dev: {
options: {
file: 'server.js',
//args: ['dev'],
//nodeArgs: ['--debug'],
ignoredFiles: ['node_modules/**'],
//watchedExtensions: ['js'],
watchedFolders: ['views', 'routes'],
//delayTime: 1,
legacyWatch: true,
env: {
PORT: RUNNING_PORT
},
cwd: __dirname
}
}
},
// run 'watch' and 'nodemon' indefinitely, together
// 'launch' will just kick it off, and won't stay running
concurrent: {
target: {
tasks: ['nodemon', 'watch', 'launch'],
options: {
logConcurrentOutput: true
}
}
},
wait:{
options: {
delay: 1000
},
pause:{
options:{
before:function(options){
console.log('pausing %dms before launching page', options.delay);
},
after : function() {
console.log('pause end, heading to page (using default browser)');
}
}
}
},
open: {
server: {
path: 'http://localhost:' + RUNNING_PORT
}
}
});
//grunt.registerTask('server', ['build', 'connect:livereload', 'open', 'watch']);
grunt.registerTask('build', ['cssmin', 'concat', 'uglify']);
grunt.registerTask('launch', ['wait', 'open']);
grunt.registerTask('default', ['build', 'concurrent']);
};

0
README.md Normal file
View File

7
bower.json Normal file
View File

@@ -0,0 +1,7 @@
{
"name": "dss-realtime",
"version": "0.0.0",
"dependencies": {
"bootstrap.css": "~2.3.2"
}
}

42
package.json Normal file
View File

@@ -0,0 +1,42 @@
{
"name": "dss-realtime",
"description": "",
"author": "",
"version": "0.0.1",
"main": "server.js",
"private": true,
"repository": "",
"dependencies": {
"body-parser": "*",
"connect": "*",
"cookie": "^0.1.2",
"cookie-parser": "*",
"express": "*",
"express-session": "*",
"jade": "*",
"socket.io": "*"
},
"devDependencies": {
"grunt": "~0.4.1",
"bower": "~0.9.2",
"grunt-concurrent": "~0.4.2",
"grunt-nodemon": "~0.1.2",
"grunt-contrib-connect": "~0.2.0",
"grunt-contrib-cssmin": "^0.9.0",
"grunt-contrib-less": "~0.8.2",
"grunt-contrib-sass": "~0.6.0",
"grunt-contrib-stylus": "~0.11.0",
"grunt-contrib-watch": "~0.5.3",
"grunt-contrib-jshint": "~0.8.0",
"grunt-contrib-concat": "~0.3.0",
"grunt-contrib-uglify": "~0.2.7",
"grunt-open": "~0.2.2",
"grunt-wait": "~0.1.0",
"matchdep": "~0.1.2",
"connect-livereload": "~0.1.3",
"moment": "~2.0.0"
},
"engines": {
"node": ">=0.8.0"
}
}

9
public/css/core.css Normal file

File diff suppressed because one or more lines are too long

54
public/js/app.js Normal file
View File

@@ -0,0 +1,54 @@
/*************************************
//
// dss-realtime app
//
**************************************/
// connect to our socket server
var socket = io.connect('http://127.0.0.1:8001/');
var app = app || {};
// shortcut for document.ready
$(function(){
//setup some common vars
var $blastField = $('#blast'),
$allPostsTextArea = $('#allPosts'),
$clearAllPosts = $('#clearAllPosts'),
$sendBlastButton = $('#send');
//SOCKET STUFF
socket.on("blast", function(data){
var copy = $allPostsTextArea.html();
$allPostsTextArea.html('<p>' + copy + data.msg + "</p>");
$allPostsTextArea.scrollTop($allPostsTextArea[0].scrollHeight - $allPostsTextArea.height());
//.css('scrollTop', $allPostsTextArea.css('scrollHeight'));
});
$clearAllPosts.click(function(e){
$allPostsTextArea.text('');
});
$sendBlastButton.click(function(e){
var blast = $blastField.val();
if(blast.length){
socket.emit("blast", {msg:blast},
function(data){
$blastField.val('');
});
}
});
$blastField.keydown(function (e){
if(e.keyCode == 13){
$sendBlastButton.trigger('click');//lazy, but works
}
})
});

1
public/js/app.min.js vendored Normal file
View File

@@ -0,0 +1 @@
var socket=io.connect("http://127.0.0.1:8001/"),app=app||{};$(function(){var $blastField=$("#blast"),$allPostsTextArea=$("#allPosts"),$clearAllPosts=$("#clearAllPosts"),$sendBlastButton=$("#send");socket.on("blast",function(data){var copy=$allPostsTextArea.html();$allPostsTextArea.html("<p>"+copy+data.msg+"</p>"),$allPostsTextArea.scrollTop($allPostsTextArea[0].scrollHeight-$allPostsTextArea.height())}),$clearAllPosts.click(function(){$allPostsTextArea.text("")}),$sendBlastButton.click(function(){var blast=$blastField.val();blast.length&&socket.emit("blast",{msg:blast},function(){$blastField.val("")})}),$blastField.keydown(function(e){13==e.keyCode&&$sendBlastButton.trigger("click")})});

48
public/js/concat.js Normal file
View File

@@ -0,0 +1,48 @@
// connect to our socket server
var socket = io.connect('http://127.0.0.1:8001/');
var app = app || {};
// shortcut for document.ready
$(function(){
//setup some common vars
var $blastField = $('#blast'),
$allPostsTextArea = $('#allPosts'),
$clearAllPosts = $('#clearAllPosts'),
$sendBlastButton = $('#send');
//SOCKET STUFF
socket.on("blast", function(data){
var copy = $allPostsTextArea.html();
$allPostsTextArea.html('<p>' + copy + data.msg + "</p>");
$allPostsTextArea.scrollTop($allPostsTextArea[0].scrollHeight - $allPostsTextArea.height());
//.css('scrollTop', $allPostsTextArea.css('scrollHeight'));
});
$clearAllPosts.click(function(e){
$allPostsTextArea.text('');
});
$sendBlastButton.click(function(e){
var blast = $blastField.val();
if(blast.length){
socket.emit("blast", {msg:blast},
function(data){
$blastField.val('');
});
}
});
$blastField.keydown(function (e){
if(e.keyCode == 13){
$sendBlastButton.trigger('click');//lazy, but works
}
})
});

91
server.js Normal file
View File

@@ -0,0 +1,91 @@
/*************************************
//
// dss-realtime app
//
**************************************/
var express = require('express'), http = require('http'), connect = require('connect'), bodyParser = require('body-parser'), session = require('express-session'), cookieParser = require('cookie-parser'), cookie_reader = require('cookie'), io = require('socket.io');
var app = express();
var sessionStore = new connect.session.MemoryStore();
var SITE_SECRET = 'I am not wearing any pants';
var SITE_KEY = 'express.sid';
app.use(bodyParser());
app.use(cookieParser(SITE_SECRET));
app.use(session({
store: sessionStore,
key: SITE_KEY,
secret: SITE_SECRET
}));
var port = app.get('port') || 8001;
var server = http.createServer(app);
server.listen(port, function () {
console.log("Express server listening on port " + port);
});
/**
* Socket.io
*/
var sio = io.listen(server);
var sessions = {};
var clients = {};
sio.use(function ioSession(socket, next) {
// create the fake req that cookieParser will expect
var req = {
"headers": {
"cookie": socket.request.headers.cookie
}
};
next();
});
sio.set('authorization', function (data, accept) {
//create fake req object to pass to cookie parser
if (data.headers.cookie) {
data.cookie = cookie_reader.parse(data.headers.cookie);
return accept(null, true);
}
return accept('error', false);
});
sio.sockets.on('connection', function (socket) {
var hs = socket.handshake;
console.log('A socket with sessionID ' + hs.sessionID + ' connected.');
var cookie = cookie_reader.parse(socket.handshake.headers.cookie);
sessions[cookie['sessionid']] = socket.id;
clients[socket.id] = socket;
socket.on('disconnect', function () {
delete clients[socket.id]; // remove the client from the array
});
});
/**
* Web Server
*/
app.use(express.static(__dirname + '/public'));
//set the view engine
app.set('view engine', 'ejs');
app.set('views', __dirname + '/views');
app.get("/", function (req, res) {
res.render('index', {});
});
app.post("/notification", function (req, res) {
if (sessions[req.body.sessionid]) {
console.log("Data is: " + req.body.message);
clients[sessions[req.body.sessionid]].emit('notification', {message: req.body.message});
res.send(req.body);
}else{
res.send(404);
}
});

83
views/index.ejs Normal file
View File

@@ -0,0 +1,83 @@
<!DOCTYPE html>
<html class="no-js">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>dss-realtime</title>
<meta name="description" content="Dss Realtime Host">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="css/core.css">
<style>
input:focus,
select:focus,
textarea:focus,
button:focus {
outline: none !important;
}
#allPosts {
resize: none;
font-size: 12px;
border-radius: 5px;
border: #ccc solid 1px;
line-height: 14px;
height:100px;
overflow: scroll;
}
p{
margin:0;
padding:0;
}
</style>
</head>
<body>
<!--[if lt IE 8]>
<p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
<![endif]-->
<div class="container">
<div class="jumbotron">
<h1>dss-realtime</h1>
<p>Dss Realtime Host</p>
<div class="row">
<div class="col-md-4 col-sm-6 col-xs-6">
<h3>All Chatter<button id="clearAllPosts" type="button" class="btn btn-danger btn-xs pull-right">clear</button></h3>
<div id="allPosts" class="form-control"></div>
<div class="input-group">
<input id="blast" type="text" class="form-control" placeholder="send something to everyone">
<span class="input-group-btn">
<button id="send" class="btn btn-success" type="button">Send</button>
</span>
</div><!-- /input-group -->
</div>
</div>
</div>
</div>
<!-- jQuery -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="public/bower_components/jQuery/jquery.min.js"><\/script>')</script>
<!-- socket.io -->
<script src="/socket.io/socket.io.js"></script>
<!-- APP CODE -->
<script src="js/app.min.js"></script>
<!-- Google Analytics: change UA-XXXXX-X to be your site's ID. -->
<script>
(function(b,o,i,l,e,r){b.GoogleAnalyticsObject=l;b[l]||(b[l]=
function(){(b[l].q=b[l].q||[]).push(arguments)});b[l].l=+new Date;
e=o.createElement(i);r=o.getElementsByTagName(i)[0];
e.src='//www.google-analytics.com/analytics.js';
r.parentNode.insertBefore(e,r)}(window,document,'script','ga'));
ga('create','UA-XXXXX-X');ga('send','pageview');
</script>
</body>
</html>

32
views/index.jade Normal file
View File

@@ -0,0 +1,32 @@
doctype 5
html
head
title SessionSockets usage example
script(type='text/javascript', src='/socket.io/socket.io.js')
style(type='text/css')
body
padding: 30px 50px;
#t {
display: block;
margin-bottom: 15px;
outline: none;
width: 700px;
height: 100px;
}
#foo {
width: 200px;
}
body
h1 SessionSockets usage example
p='You should see below your session hash with "bar" as initial value for the "foo" key'
textarea#t(readonly='1')
input#foo(placeholder='now type in a new value for foo')
span=' then you should see foo value updated'
script(type='text/javascript')
var socket = io.connect();
socket.on('session', function (session) {
document.getElementById('t').value = JSON.stringify(session);
});
document.getElementById('foo').addEventListener('keyup', function () {
socket.emit('foo', this.value);
});