I am trying to add socket.io to my angularjs project. My reference is http://www.html5rocks.com/en/tutorials/frameworks/angular-websockets/?redirect_from_locale=zh#disqus_thread. I am trying to modify it as below:
About the socket.io server: app.js:
var express = require('express');
var app = module.exports = express();
var server = require('http').createServer(app);
// Hook Socket.io into Express
var io = require('socket.io').listen(server);
// Socket.io Communication
var socket = require('./scripts/socket.js');
io.sockets.on('connection', socket);
// Start server at http://127.0.0.1:3000
server.listen(3000, function() {
console.log("Express server listening on port %d in %s mode", this.address().port, app.settings.env);
});
scripts/socket.js:
// Keep track of which names are used so that there are no duplicates
var userNames = (function () {
var names = {};
var claim = function (name) {
if (!name || names[name]) {
return false;
} else {
names[name] = true;
return true;
}
};
// find the lowest unused "guest" name and claim it
var getGuestName = function () {
var name,
nextUserId = 1;
do {
name = 'Guest ' + nextUserId;
nextUserId += 1;
} while (!claim(name));
return name;
};
// serialize claimed names as an array
var get = function () {
var res = [];
for (user in names) {
res.push(user);
}
return res;
};
var free = function (name) {
if (names[name]) {
delete names[name];
}
};
return {
claim: claim,
free: free,
get: get,
getGuestName: getGuestName
};
}());
// export function for listening to the socket
module.exports = function (socket) {
var name = userNames.getGuestName();
// send the new user their name and a list of users
socket.emit('init', {
name: name,
users: userNames.get()
});
// notify other clients that a new user has joined
socket.broadcast.emit('user:join', {
name: name
});
// broadcast a user's message to other users
socket.on('send:message', function (data) {
socket.broadcast.emit('send:message', {
user: name,
text: data.message
});
});
// validate a user's name change, and broadcast it on success
socket.on('change:name', function (data, fn) {
if (userNames.claim(data.name)) {
var oldName = name;
userNames.free(oldName);
name = data.name;
socket.broadcast.emit('change:name', {
oldName: oldName,
newName: name
});
fn(true);
} else {
fn(false);
}
});
// clean up when a user leaves, and broadcast it to other users
socket.on('disconnect', function () {
socket.broadcast.emit('user:left', {
name: name
});
userNames.free(name);
});
};
These are all the files for socket.io. After node app.js, it displays "Express server listening on port 3000 in development mode"
The angular part is modified from the angular seed: https://github.com/angular/angular-seed index.html:
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta charset="UTF-8">
<title>Angular Socket.io IM Demo App</title>
<link rel="stylesheet" href="css/app.css"></head>
<body>
<h1>Angular Socket.io IM Demo App</h1>
<div ng-controller="AppCtrl">
<div class="col">
<h3>Messages</h3>
<div class="overflowable">
<p ng-repeat="message in messages" ng-class="{alert: message.user == 'chatroom'}">: </p>
</div>
</div>
<div class="col">
<h3>Users</h3>
<div class="overflowable">
<p ng-repeat="user in users"></p>
</div>
</div>
<div class="clr">
<form ng-submit="sendMessage()">
Message:
<input size="60" ng-model="message">
<input type="submit" value="Send"></form>
</div>
<div class="clr">
<h3>Change your name</h3>
<p>Your current user name is </p>
<form ng-submit="changeName()">
<input ng-model="newName">
<input type="submit" value="Change Name"></form>
</div>
</div>
<script src="lib/angular/angular.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script src="js/app.js"></script>
<script src="js/services.js"></script>
<script src="js/controllers.js"></script>
<script src="js/filters.js"></script>
<script src="js/directives.js"></script>
</body>
</html>
js/app.js:
angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives']);
js/services.js:
angular.module('myApp.services', [])
.value('version', '0.1')
.factory('socket', function($rootScope) {
var socket = io.connect();
return {
on: function(eventName, callback) {
socket.on(eventName, function() {
var args = arguments;
$rootScope.$apply(function() {
callback.apply(socket, args);
});
});
},
emit: function(eventName, data, callback) {
socket.emit(eventName, data, function() {
var args = arguments;
$rootScope.$apply(function() {
if (callback) {
callback.apply(socket, args);
}
});
})
}
};
});
js/controllers.js:
/* Controllers */
function AppCtrl($scope, socket) {
// Socket listeners
// ================
socket.on('init', function (data) {
$scope.name = data.name;
$scope.users = data.users;
});
socket.on('send:message', function (message) {
$scope.messages.push(message);
});
socket.on('change:name', function (data) {
changeName(data.oldName, data.newName);
});
socket.on('user:join', function (data) {
$scope.messages.push({
user: 'chatroom',
text: 'User ' + data.name + ' has joined.'
});
$scope.users.push(data.name);
});
// add a message to the conversation when a user disconnects or leaves the room
socket.on('user:left', function (data) {
$scope.messages.push({
user: 'chatroom',
text: 'User ' + data.name + ' has left.'
});
var i, user;
for (i = 0; i < $scope.users.length; i++) {
user = $scope.users[i];
if (user === data.name) {
$scope.users.splice(i, 1);
break;
}
}
});
// Private helpers
// ===============
var changeName = function (oldName, newName) {
// rename user in list of users
var i;
for (i = 0; i < $scope.users.length; i++) {
if ($scope.users[i] === oldName) {
$scope.users[i] = newName;
}
}
$scope.messages.push({
user: 'chatroom',
text: 'User ' + oldName + ' is now known as ' + newName + '.'
});
}
// Methods published to the scope
// ==============================
$scope.changeName = function () {
socket.emit('change:name', {
name: $scope.newName
}, function (result) {
if (!result) {
alert('There was an error changing your name');
} else {
changeName($scope.name, $scope.newName);
$scope.name = $scope.newName;
$scope.newName = '';
}
});
};
$scope.messages = [];
$scope.sendMessage = function () {
socket.emit('send:message', {
message: $scope.message
});
// add the message to our model locally
$scope.messages.push({
user: $scope.name,
text: $scope.message
});
// clear message box
$scope.message = '';
};
}
Then I run the angularjs in localhost:8000. In the webpage it seems I can send something which caused the bower to update:
[Mon, 28 Jul 2014 20:10:13 GMT] "GET /app/lib/angular/angular.js" "Mozilla/5.0 (
Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.1
53 Safari/537.36"
[Mon, 28 Jul 2014 20:10:13 GMT] "GET /socket.io/socket.io.js" "Mozilla/5.0 (Wind
ows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 S
afari/537.36"
However the socket.io running on localhost:3000 receives nothing.
I guess I must have something wrong in the connection between angularjs and socket.io, such as the
<script src="/socket.io/socket.io.js"></script>
in the index.html, or the
var socket = io.connect();
in the js/services.js.
I tried to change them to
<script src="http://127.0.0.1:3000/socket.io/socket.io.js"></script>
or
<script src="http://localhost:3000/socket.io/socket.io.js"></script>
or
var socket = io.connect('http://127.0.0.1:3000');
or
var socket = io.connect('http://localhost:3000');
or
var socket = io.connect('http://localhost');
but nothing works. Maybe I am on a completely wrong way.
So I copy paste my code here, hope someone can help me. Any help or suggestions will be grateful.
UPDATE Now it seems the client can connect to the server, but can't load the controller correctly. Not sure how to fix it.