Browse Source

before socket

windhamdavid 3 years ago
parent
commit
3f96d3cb56

+ 3 - 0
.nodemonignore

@@ -0,0 +1,3 @@
+/.*
+*.md
+/node_modules/*

+ 15 - 6
app.js

@@ -1,11 +1,20 @@
-var express = require('express'),
-    http = require('http')
+/*global require:true, __dirname:true */
+
+var conf = {
+    port: 8888,
+    debug: false
+};
+
+
+var express = require('express');
+var http = require('http');
+var path = require('path');
+var bodyParser = require('body-parser');
 
 var app = express(),
     server = http.createServer(app);
     server.listen(conf.port);
 
-app.get('/', function(req, res){
-  res.sendFile(__dirname + '/index.html');
-});
-
+app.use(bodyParser.json());
+app.use(bodyParser.urlencoded({ extended: false }));
+app.use(express.static(path.join(__dirname, 'app')));

File diff suppressed because it is too large
+ 11 - 0
app/css/style.min.css


+ 110 - 0
app/index.html

@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<head>
+   <meta charset="utf-8">
+   <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+   <title>Daveo Radio</title>
+   <meta name="description" content="">
+   <meta name="viewport" content="width=device-width">
+   <link rel="stylesheet" href="css/style.min.css">
+</head>
+<body>
+
+<div class="container">
+<div class="col-lg-6 text-center">
+<section id="audo" class="bg-light-gray">
+
+</section>
+</div>
+</div>
+<div class="container">
+<div class="col-lg-6 text-center">
+<section id="request-line" class="bg-light-gray">
+   <div class="row-fluid">
+       <div class="span12 well" style="background-color:white; border:0px"> 
+           <!-- Tabs -->
+           <div class="row-fluid">
+               <div class="span12">
+                   <ul id="rooms_tabs" class="nav nav-tabs">
+                       <li class="dropdown">
+                           <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-th"></i>&nbsp;Options&nbsp;<b class="caret"></b></a>
+                           <ul class="dropdown-menu">
+                               <li><a href="#modal_joinroom" data-toggle="modal"><i class="icon-plus"></i>&nbsp;Join room</a></li>
+                               <li><a id="b_leave_room" href="#"><i class="icon-minus"></i>&nbsp;Leave current room</a></li>
+                               <li class="divider"></li>
+                               <li><a href="#modal_setnick" data-toggle="modal"><i class="icon-user"></i>&nbsp;Set nickname</a></li>
+                           </ul>
+                       </li>
+                       <li id="MainRoom_tab" class="active"><a href="#MainRoom" data-toggle="tab">MainRoom</a></li>
+                   </ul>
+               </div>
+           </div>
+           <div id="rooms" class="tab-content">
+               <div class="tab-pane active" id="MainRoom">
+                   <div class="row-fluid">
+                       <div class="span12 well">
+                           <div id="room_messages" style="min-height:220px; max-height:220px; overflow:auto;">
+                               <span class="label label-info">ServerBot</span>&nbsp;&nbsp;Welcome to the room :)<br/>
+                           </div>
+                       </div>
+                   </div>
+                   <div class="row-fluid">
+                       <div class="span12">
+                           <h3>Now chatting...</h3>
+                       </div>
+                   </div>
+                   <div class="row-fluid">
+                       <div id="room_users" class="span12">
+                           <span class="badge badge-inverse">ServerBot</span>
+                       </div>
+                   </div>
+               </div>
+           </div>
+       </div>
+   </div>
+   <div class="row-fluid">
+       <div class="span12"> 
+           <div class="navbar">
+               <div class="navbar-inner">
+                   <form class="navbar-form">
+                       <input id="message_text" type="text" class="span9">
+                       <button id="b_send_message" class="btn btn-primary">Send</button>
+                   </form>
+               </div>
+           </div>
+       </div>
+   </div>
+   <div id="modal_joinroom" class="modal hide fade">
+      <div class="modal-header">
+          <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+          <h3>Join room</h3>
+      </div>
+      <div class="modal-body">
+          <input id="room_name" type="text" class="input-xlarge" placeholder="Room name">
+          <p><small>Room will be created if it doesn't exist</small></p>
+      </div>
+      <div class="modal-footer">
+          <a id="b_join_room" href="#" class="btn btn-primary">Join now</a>
+      </div>
+   </div>
+   <div id="modal_setnick" class="modal hide fade">
+      <div class="modal-header">
+          <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+          <h3>Set nickname</h3>
+      </div>
+      <div class="modal-body">
+          <input id="nickname" type="text" class="input-xlarge" placeholder="Type your nickname here">
+          <p><small>Pick up something more cool than anonymous :)</small></p>
+      </div>
+      <div class="modal-footer">
+          <a id="b_set_nickname" href="#" class="btn btn-primary">Set nickname</a>
+      </div>
+   </div>
+</section>
+</div>
+</div>
+
+   <script src="js/vendor.min.js"></script>
+   <script src="/socket.io/socket.io.js"></script>
+   <script src="js/radio.min.js"></script>
+</body>
+</html>

File diff suppressed because it is too large
+ 1930 - 0
app/js/vendor.min.js


+ 45 - 0
gulpfile.js

@@ -0,0 +1,45 @@
+/*global require:true, console:true */
+
+var gulp = require('gulp');
+var nodemon = require('gulp-nodemon');
+var minify = require('gulp-minify');
+var minifycss = require('gulp-minify-css');
+var concat = require('gulp-concat');
+
+var copyTask = function() {
+  gulp.src('./src/index.html')
+    .pipe(gulp.dest('./app'));
+  gulp.src('./src/css/*.css')
+    .pipe(minifycss())
+    .pipe(concat('style.min.css'))
+    .pipe(gulp.dest('./app/css'));
+  gulp.src(['./src/js/jquery.min.js', '.src/js/bootstrap.js', '.src/js/underscore.min.js', './src/js/handlebars.js'])
+    .pipe(minify())
+    .pipe(concat('vendor.min.js'))
+    .pipe(gulp.dest('./app/js'));
+  gulp.src(['.src/js/main.js', '.src/js/radio.js'])
+    .pipe(minify())
+    .pipe(concat('radio.min.js'))
+    .pipe(gulp.dest('./app/js'));
+  console.log('Minify/Concat/Copy /src to /public');
+};
+
+gulp.task('copy', function() {
+  copyTask();
+});
+
+var nodemonTask = function() {
+  nodemon({
+    tasks: ['copy'],
+    script: 'app.js',
+    verbose: true,
+    env: { 'NODE_ENV': 'development' },
+    watch: './src/',
+    ext: 'css js html'
+  });
+};
+
+gulp.task('start', function () {
+  nodemonTask();
+});
+

+ 15 - 3
package.json

@@ -5,13 +5,25 @@
   "version": "0.0.1",
   "private": true,
   "dependencies": {
-    "express": "^4.13.3"
+    "body-parser": "^1.14.1",
+    "express": "^4.13.3",
+    "redis": "^2.4.1",
+    "socket.io": "^1.3.7",
+    "socket.io-redis": "^0.1.4",
+    "underscore": "^1.8.3",
+    "validator": "^4.3.0"
   },
   "devDependencies": {
-
+    "gulp": "^3.9.0",
+    "gulp-concat": "^2.6.0",
+    "gulp-jshint": "^2.0.0",
+    "gulp-minify": "0.0.5",
+    "gulp-minify-css": "^1.2.1",
+    "gulp-nodemon": "^2.0.4",
+    "nodemon": "^1.8.1"
   },
   "scripts": {
     "start": "node app.js",
     "test": ""
   }
-}
+}

+ 1 - 1
src/css/main.css

@@ -1,2 +1,2 @@
-/* Main CSS file */
+/*! Main CSS file */
 

BIN
src/fonts/glyphicons-halflings-regular.eot


File diff suppressed because it is too large
+ 288 - 0
src/fonts/glyphicons-halflings-regular.svg


BIN
src/fonts/glyphicons-halflings-regular.ttf


BIN
src/fonts/glyphicons-halflings-regular.woff


BIN
src/fonts/glyphicons-halflings-regular.woff2


+ 110 - 0
src/index.html

@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<head>
+   <meta charset="utf-8">
+   <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+   <title>Daveo Radio</title>
+   <meta name="description" content="">
+   <meta name="viewport" content="width=device-width">
+   <link rel="stylesheet" href="css/style.min.css">
+</head>
+<body>
+
+<div class="container">
+<div class="col-lg-6 text-center">
+<section id="audo" class="bg-light-gray">
+
+</section>
+</div>
+</div>
+<div class="container">
+<div class="col-lg-6 text-center">
+<section id="request-line" class="bg-light-gray">
+   <div class="row-fluid">
+       <div class="span12 well" style="background-color:white; border:0px"> 
+           <!-- Tabs -->
+           <div class="row-fluid">
+               <div class="span12">
+                   <ul id="rooms_tabs" class="nav nav-tabs">
+                       <li class="dropdown">
+                           <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="icon-th"></i>&nbsp;Options&nbsp;<b class="caret"></b></a>
+                           <ul class="dropdown-menu">
+                               <li><a href="#modal_joinroom" data-toggle="modal"><i class="icon-plus"></i>&nbsp;Join room</a></li>
+                               <li><a id="b_leave_room" href="#"><i class="icon-minus"></i>&nbsp;Leave current room</a></li>
+                               <li class="divider"></li>
+                               <li><a href="#modal_setnick" data-toggle="modal"><i class="icon-user"></i>&nbsp;Set nickname</a></li>
+                           </ul>
+                       </li>
+                       <li id="MainRoom_tab" class="active"><a href="#MainRoom" data-toggle="tab">MainRoom</a></li>
+                   </ul>
+               </div>
+           </div>
+           <div id="rooms" class="tab-content">
+               <div class="tab-pane active" id="MainRoom">
+                   <div class="row-fluid">
+                       <div class="span12 well">
+                           <div id="room_messages" style="min-height:220px; max-height:220px; overflow:auto;">
+                               <span class="label label-info">ServerBot</span>&nbsp;&nbsp;Welcome to the room :)<br/>
+                           </div>
+                       </div>
+                   </div>
+                   <div class="row-fluid">
+                       <div class="span12">
+                           <h3>Now chatting...</h3>
+                       </div>
+                   </div>
+                   <div class="row-fluid">
+                       <div id="room_users" class="span12">
+                           <span class="badge badge-inverse">ServerBot</span>
+                       </div>
+                   </div>
+               </div>
+           </div>
+       </div>
+   </div>
+   <div class="row-fluid">
+       <div class="span12"> 
+           <div class="navbar">
+               <div class="navbar-inner">
+                   <form class="navbar-form">
+                       <input id="message_text" type="text" class="span9">
+                       <button id="b_send_message" class="btn btn-primary">Send</button>
+                   </form>
+               </div>
+           </div>
+       </div>
+   </div>
+   <div id="modal_joinroom" class="modal hide fade">
+      <div class="modal-header">
+          <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+          <h3>Join room</h3>
+      </div>
+      <div class="modal-body">
+          <input id="room_name" type="text" class="input-xlarge" placeholder="Room name">
+          <p><small>Room will be created if it doesn't exist</small></p>
+      </div>
+      <div class="modal-footer">
+          <a id="b_join_room" href="#" class="btn btn-primary">Join now</a>
+      </div>
+   </div>
+   <div id="modal_setnick" class="modal hide fade">
+      <div class="modal-header">
+          <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+          <h3>Set nickname</h3>
+      </div>
+      <div class="modal-body">
+          <input id="nickname" type="text" class="input-xlarge" placeholder="Type your nickname here">
+          <p><small>Pick up something more cool than anonymous :)</small></p>
+      </div>
+      <div class="modal-footer">
+          <a id="b_set_nickname" href="#" class="btn btn-primary">Set nickname</a>
+      </div>
+   </div>
+</section>
+</div>
+</div>
+
+   <script src="js/vendor.min.js"></script>
+   <script src="/socket.io/socket.io.js"></script>
+   <script src="js/radio.min.js"></script>
+</body>
+</html>

+ 3 - 0
src/js/_templates/message.handlebars

@@ -0,0 +1,3 @@
+<!-- Message -->
+<span class="label label-info">{{username}}</span>&nbsp;&nbsp;{{msg}}<br/>
+<!-- End Message -->

+ 21 - 0
src/js/_templates/room.handlebars

@@ -0,0 +1,21 @@
+<!-- Room -->
+<div class="tab-pane" id="{{room}}">
+    <div class="row-fluid">
+        <div class="span12 well">
+            <div id="room_messages" style="min-height:220px; max-height:220px; overflow:auto;">
+                <span class="label label-info">ServerBot</span>&nbsp;&nbsp;Welcome to the room :)<br/>
+            </div>
+        </div>
+    </div>
+    <div class="row-fluid">
+        <div class="span12">
+            <h3>Now chatting...</h3>
+        </div>
+    </div>
+    <div class="row-fluid">
+        <div id="room_users" class="span12">
+            <span class="badge badge-inverse">ServerBot</span>
+        </div>
+    </div>
+</div>
+<!-- End Room -->

+ 3 - 0
src/js/_templates/room_tab.handlebars

@@ -0,0 +1,3 @@
+<!-- Room tab -->
+<li id="{{room}}_tab"><a href="#{{room}}" data-toggle="tab">{{room}}</a></li>
+<!-- End Room tab -->

+ 3 - 0
src/js/_templates/user.handlebars

@@ -0,0 +1,3 @@
+<!-- User -->
+<span class="badge badge-inverse" id="{{id}}">{{username}}</span>
+<!-- End User -->

File diff suppressed because it is too large
+ 2363 - 0
src/js/bootstrap.js


File diff suppressed because it is too large
+ 1920 - 0
src/js/handlebars.js


File diff suppressed because it is too large
+ 4 - 0
src/js/jquery.min.js


+ 305 - 0
src/js/main.js

@@ -0,0 +1,305 @@
+
+// Author: Sergio Castaño Arteaga
+// Email: sergio.castano.arteaga@gmail.com
+
+(function(){
+
+    var debug = false;
+
+    // ***************************************************************************
+    // Socket.io events
+    // ***************************************************************************
+    
+    var socket = io.connect(window.location.host);
+
+    // Connection established
+    socket.on('connected', function (data) {
+        console.log(data);
+
+        // Get users connected to mainroom
+        socket.emit('getUsersInRoom', {'room':'MainRoom'});
+
+        if (debug) {
+            // Subscription to rooms
+            socket.emit('subscribe', {'username':'sergio', 'rooms':['sampleroom']});
+
+            // Send sample message to room
+            socket.emit('newMessage', {'room':'sampleroom', 'msg':'Hellooooooo!'});
+
+            // Auto-disconnect after 10 minutes
+            setInterval(function() {
+                socket.emit('unsubscribe', {'rooms':['sampleroom']});
+                socket.disconnect();
+            }, 600000);
+        }
+    });
+
+    // Disconnected from server
+    socket.on('disconnect', function (data) {
+        var info = {'room':'MainRoom', 'username':'ServerBot', 'msg':'----- Lost connection to server -----'};
+        addMessage(info);
+    });
+    
+    // Reconnected to server
+    socket.on('reconnect', function (data) {
+        var info = {'room':'MainRoom', 'username':'ServerBot', 'msg':'----- Reconnected to server -----'};
+        addMessage(info);
+    });
+
+    // Subscription to room confirmed
+    socket.on('subscriptionConfirmed', function(data) {
+        // Create room space in interface
+        if (!roomExists(data.room)) {
+            addRoomTab(data.room);
+            addRoom(data.room);
+        }
+
+        // Close modal if opened
+        $('#modal_joinroom').modal('hide');
+    });
+
+    // Unsubscription to room confirmed
+    socket.on('unsubscriptionConfirmed', function(data) {
+        // Remove room space in interface
+        if (roomExists(data.room)) {
+            removeRoomTab(data.room);
+            removeRoom(data.room);
+        }
+    });
+
+    // User joins room
+    socket.on('userJoinsRoom', function(data) {
+        console.log("userJoinsRoom: %s", JSON.stringify(data));
+        // Log join in conversation
+        addMessage(data);
+    
+        // Add user to connected users list
+        addUser(data);
+    });
+
+    // User leaves room
+    socket.on('userLeavesRoom', function(data) {
+        console.log("userLeavesRoom: %s", JSON.stringify(data));
+        // Log leave in conversation
+        addMessage(data);
+
+        // Remove user from connected users list
+        removeUser(data);
+    });
+
+    // Message received
+    socket.on('newMessage', function (data) {
+        console.log("newMessage: %s", JSON.stringify(data));
+        addMessage(data);
+
+        // Scroll down room messages
+        var room_messages = '#'+data.room+' #room_messages';
+        $(room_messages).animate({
+            scrollTop: $(room_messages).height()
+        }, 300);
+    });
+
+    // Users in room received
+    socket.on('usersInRoom', function(data) {
+        console.log('usersInRoom: %s', JSON.stringify(data));
+        _.each(data.users, function(user) {
+            addUser(user);
+        });
+    });
+
+    // User nickname updated
+    socket.on('userNicknameUpdated', function(data) {
+        console.log("userNicknameUpdated: %s", JSON.stringify(data));
+        updateNickname(data);
+
+        msg = '----- ' + data.oldUsername + ' is now ' + data.newUsername + ' -----';
+        var info = {'room':data.room, 'username':'ServerBot', 'msg':msg};
+        addMessage(info);
+    });
+
+    // ***************************************************************************
+    // Templates and helpers
+    // ***************************************************************************
+    
+    var templates = {};
+    var getTemplate = function(path, callback) {
+        var source;
+        var template;
+ 
+        // Check first if we've the template cached
+        if (_.has(templates, path)) {
+            if (callback) callback(templates[path]);
+        // If not we get and compile it
+        } else {
+            $.ajax({
+                url: path,
+                success: function(data) {
+                    source = data;
+                    template = Handlebars.compile(source);
+                    // Store compiled template in cache
+                    templates[path] = template;
+                    if (callback) callback(template);
+                }
+            });
+        }
+    }
+
+    // Add room tab
+    var addRoomTab = function(room) {
+        getTemplate('js/templates/room_tab.handlebars', function(template) {
+            $('#rooms_tabs').append(template({'room':room}));
+        });
+    };
+
+    // Remove room tab
+    var removeRoomTab = function(room) {
+        var tab_id = "#"+room+"_tab";
+        $(tab_id).remove();
+    };
+
+    // Add room
+    var addRoom = function(room) {
+        getTemplate('js/templates/room.handlebars', function(template) {
+            $('#rooms').append(template({'room':room}));
+        
+            // Toogle to created room
+            var newroomtab = '[href="#'+room+'"]';
+            $(newroomtab).click();
+
+            // Get users connected to room
+            socket.emit('getUsersInRoom', {'room':room});
+        });
+    };
+    
+    // Remove room
+    var removeRoom = function(room) {
+        var room_id = "#"+room;
+        $(room_id).remove();
+    };
+
+    // Add message to room
+    var addMessage = function(msg) {
+        getTemplate('js/templates/message.handlebars', function(template) {
+            var room_messages = '#'+msg.room+' #room_messages';
+            $(room_messages).append(template(msg));
+        });
+    };
+    
+    // Add user to connected users list
+    var addUser = function(user) {
+        getTemplate('js/templates/user.handlebars', function(template) {
+            var room_users = '#'+user.room+' #room_users';
+            // Add only if it doesn't exist in the room
+            var user_badge = '#'+user.room+' #'+user.id;
+            if (!($(user_badge).length)) {
+                $(room_users).append(template(user));
+            }
+        });
+    }
+
+    // Remove user from connected users list
+    var removeUser = function(user) {
+        var user_badge = '#'+user.room+' #'+user.id;
+        $(user_badge).remove();
+    };
+
+    // Check if room exists
+    var roomExists = function(room) {
+        var room_selector = '#'+room;
+        if ($(room_selector).length) {
+            return true;
+        } else {
+            return false;
+        }
+    };
+
+    // Get current room
+    var getCurrentRoom = function() {
+        return $('li[id$="_tab"][class="active"]').text();
+    };
+
+    // Get message text from input field
+    var getMessageText = function() {
+        var text = $('#message_text').val();
+        $('#message_text').val("");
+        return text;
+    };
+
+    // Get room name from input field
+    var getRoomName = function() {
+        var name = $('#room_name').val().trim();
+        $('#room_name').val("");
+        return name;
+    };
+
+    // Get nickname from input field
+    var getNickname = function() {
+        var nickname = $('#nickname').val();
+        $('#nickname').val("");
+        return nickname;
+    };
+
+    // Update nickname in badges
+    var updateNickname = function(data) {
+        var badges = '#'+data.room+' #'+data.id;
+        $(badges).text(data.newUsername);
+    };
+
+    // ***************************************************************************
+    // Events
+    // ***************************************************************************
+
+    // Send new message
+    $('#b_send_message').click(function(eventObject) {
+        eventObject.preventDefault();
+        if ($('#message_text').val() != "") {
+            socket.emit('newMessage', {'room':getCurrentRoom(), 'msg':getMessageText()});
+        }
+    });
+
+    // Join new room
+    $('#b_join_room').click(function(eventObject) {
+        var roomName = getRoomName();
+
+        if (roomName) {
+            eventObject.preventDefault();
+            socket.emit('subscribe', {'rooms':[roomName]}); 
+
+        // Added error class if empty room name
+        } else {
+            $('#room_name').addClass('error');
+        }
+    });
+
+    // Leave current room
+    $('#b_leave_room').click(function(eventObject) {
+        eventObject.preventDefault();
+        var currentRoom = getCurrentRoom();
+        if (currentRoom != 'MainRoom') {
+            socket.emit('unsubscribe', {'rooms':[getCurrentRoom()]}); 
+
+            // Toogle to MainRoom
+            $('[href="#MainRoom"]').click();
+        } else {
+            console.log('Cannot leave MainRoom, sorry');
+        }
+    });
+
+    // Remove error style to hide modal
+    $('#modal_joinroom').on('hidden.bs.modal', function (e) {
+        if ($('#room_name').hasClass('error')) {
+            $('#room_name').removeClass('error');
+        }
+    });
+
+    // Set nickname
+    $('#b_set_nickname').click(function(eventObject) {
+        eventObject.preventDefault();
+        socket.emit('setNickname', {'username':getNickname()});
+
+        // Close modal if opened
+        $('#modal_setnick').modal('hide');
+    });
+
+})();
+

File diff suppressed because it is too large
+ 11 - 0
src/js/modernizr.min.js


+ 1 - 0
src/js/radio.js

@@ -0,0 +1 @@
+/* Radio Funtions */

File diff suppressed because it is too large
+ 5 - 0
src/js/underscore.min.js