接著上次的文章
Node.js+socket.io即時(shí)通訊+HTML5桌面提醒(notification(上)
寫的下篇:
二
1.打開node_modules文件,打開socket.io文件,找到socket.io.js,在package.json所在的目錄,新建www文件夾.
2.在www文件夾里,建立自己的 index.html ,css樣式,js文件,以及socket.io.js,文件目錄如下:
3.文件內(nèi)容為:
index.html:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>hichat</title>
<link rel="stylesheet" href="styles/main.css">
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
<link rel="icon" href="favicon.ico" type="image/x-icon">
</head>
<body>
<div class="wrapper">
<div class="banner">
<h1>HiChat :)</h1>
<span id="status"></span>
</div>
<div id="historyMsg">
</div>
<div class="controls" >
<div class="items">
<input id="colorStyle" type="color" placeHolder='#000' title="font color" />
<input id="emoji" type="button" value="emoji" title="emoji" />
<label for="sendImage" class="imageLable">
<input type="button" value="image" />
<input id="sendImage" type="file" value="image"/>
</label>
<input id="clearBtn" type="button" value="clear" title="clear screen" />
<input id="notifBtn" type="button" value="通知" title="Notification">
</div>
<textarea id="messageInput" placeHolder="enter to send"></textarea>
<input id="sendBtn" type="button" value="SEND">
<div id="emojiWrapper">
</div>
</div>
</div>
<div id="loginWrapper">
<p id="info">connecting to server...</p>
<div id="nickWrapper">
<input type="text" placeHolder="nickname" id="nicknameInput" />
<input type="button" value="OK" id="loginBtn" />
</div>
</div>
<script src="/socket.io/socket.io.js"></script>
<script src="scripts/hichat.js"></script>
</body>
</html>
main.css
html, body {
margin: 0;
background-color: #efefef;
font-family: sans-serif;
}
.wrapper {
width: 500px;
height: 640px;
padding: 5px;
margin: 0 auto;
background-color: #ddd;
}
#loginWrapper {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(5, 5, 5, .6);
text-align: center;
color: #fff;
display: block;
padding-top: 200px;
}
#nickWrapper {
display: none;
}
.banner {
height: 80px;
width: 100%;
}
.banner p {
float: left;
display: inline-block;
}
.controls {
height: 100px;
margin: 5px 0px;
position: relative;
}
#historyMsg {
height: 400px;
background-color: #fff;
overflow: auto;
padding: 2px;
}
#historyMsg img {
max-width: 99%;
}
.timespan {
color: #ddd;
}
.items {
height: 30px;
}
#colorStyle {
width: 50px;
border: none;
padding: 0;
}
/*custom the file input*/
.imageLable {
position: relative;
}
#sendImage {
position: absolute;
width: 52px;
left: 0;
opacity: 0;
overflow: hidden;
}
/*end custom file input*/
#messageInput {
width: 440px;
max-width: 440px;
height: 90px;
max-height: 90px;
float:left;
}
#sendBtn {
width: 50px;
height: 96px;
float: right;
}
#emojiWrapper {
display: none;
width: 500px;
bottom: 105px;
position: absolute;
background-color: #aaa;
box-shadow: 0 0 10px #555;
}
#emojiWrapper img {
margin: 2px;
padding: 2px;
width: 25px;
height: 25px;
}
#emojiWrapper img:hover {
background-color: blue;
}
.emoji{
display: inline;
}
footer {
text-align: center;
}
main.js
window.onload = function() {
var hichat = new HiChat();
hichat.init();
if(window.Notification){
if(Notification.permission === 'granted'){
}else{
Notification.requestPermission();
}
}
};
var HiChat = function() {
this.socket = null;
};
HiChat.prototype = {
init: function() {
var that = this;
this.socket = io.connect();
this.socket.on('connect', function() {
document.getElementById('info').textContent = 'get yourself a nickname :)';
document.getElementById('nickWrapper').style.display = 'block';
document.getElementById('nicknameInput').focus();
});
this.socket.on('nickExisted', function() {
document.getElementById('info').textContent = '!nickname is taken, choose another pls';
});
this.socket.on('loginSuccess', function() {
document.title = 'hichat | ' + document.getElementById('nicknameInput').value;
document.getElementById('loginWrapper').style.display = 'none';
document.getElementById('messageInput').focus();
});
this.socket.on('error', function(err) {
if (document.getElementById('loginWrapper').style.display == 'none') {
document.getElementById('status').textContent = '!fail to connect :(';
} else {
document.getElementById('info').textContent = '!fail to connect :(';
}
});
this.socket.on('system', function(nickName, userCount, type) {
var msg = nickName + (type == 'login' ? ' joined' : ' left');
that._displayNewMsg('system ', msg, 'red');
document.getElementById('status').textContent = userCount + (userCount > 1 ? ' users' : ' user') + ' online';
});
this.socket.on('newMsg', function(user, msg, color) {
that._displayNewMsg(user, msg, color);
});
this.socket.on('newImg', function(user, img, color) {
that._displayImage(user, img, color);
});
this.socket.on('notification',function(user,config){
that._consoleText(user,config);
});
document.getElementById('loginBtn').addEventListener('click', function() {
var nickName = document.getElementById('nicknameInput').value;
if (nickName.trim().length != 0) {
that.socket.emit('login', nickName);
} else {
document.getElementById('nicknameInput').focus();
};
}, false);
document.getElementById('nicknameInput').addEventListener('keyup', function(e) {
if (e.keyCode == 13) {
var nickName = document.getElementById('nicknameInput').value;
if (nickName.trim().length != 0) {
that.socket.emit('login', nickName);
};
};
}, false);
document.getElementById('sendBtn').addEventListener('click', function() {
var messageInput = document.getElementById('messageInput'),
msg = messageInput.value,
color = document.getElementById('colorStyle').value;
messageInput.value = '';
messageInput.focus();
if (msg.trim().length != 0) {
that.socket.emit('postMsg', msg, color);
that._displayNewMsg('me', msg, color);
return;
};
}, false);
document.getElementById('messageInput').addEventListener('keyup', function(e) {
var messageInput = document.getElementById('messageInput'),
msg = messageInput.value,
color = document.getElementById('colorStyle').value;
if (e.keyCode == 13 && msg.trim().length != 0) {
messageInput.value = '';
that.socket.emit('postMsg', msg, color);
that._displayNewMsg('me', msg, color);
};
}, false);
document.getElementById('clearBtn').addEventListener('click', function() {
document.getElementById('historyMsg').innerHTML = '';
}, false);
document.getElementById('sendImage').addEventListener('change', function() {
if (this.files.length != 0) {
var file = this.files[0],
reader = new FileReader(),
color = document.getElementById('colorStyle').value;
if (!reader) {
that._displayNewMsg('system', '!your browser doesn\'t support fileReader', 'red');
this.value = '';
return;
};
reader.onload = function(e) {
this.value = '';
that.socket.emit('img', e.target.result, color);
that._displayImage('me', e.target.result, color);
};
reader.readAsDataURL(file);
};
}, false);
this._initialEmoji();
document.getElementById('emoji').addEventListener('click', function(e) {
var emojiwrapper = document.getElementById('emojiWrapper');
emojiwrapper.style.display = 'block';
e.stopPropagation();
}, false);
document.body.addEventListener('click', function(e) {
var emojiwrapper = document.getElementById('emojiWrapper');
if (e.target != emojiwrapper) {
emojiwrapper.style.display = 'none';
};
});
document.getElementById('emojiWrapper').addEventListener('click', function(e) {
var target = e.target;
if (target.nodeName.toLowerCase() == 'img') {
var messageInput = document.getElementById('messageInput');
messageInput.focus();
messageInput.value = messageInput.value + '[emoji:' + target.title + ']';
};
}, false); document.getElementById('notifBtn').addEventListener('click',function(){
var config = {
body: '我發(fā)起了一個(gè)描述~', //正文內(nèi)容
dir: 'auto',//文本顯示方向 auto ,ltr,rtl
lang:'en', //文本語言
icon: 'http://img4.imgtn.bdimg.com/it/u=196405673,1932175745&fm=23&gp=0.jpg' //圖片的URL,將被用于顯示通知的圖標(biāo)
};
that.socket.emit('noti',config);
return;
}),false;
},
_initialEmoji: function() {
var emojiContainer = document.getElementById('emojiWrapper'),
docFragment = document.createDocumentFragment();
for (var i = 69; i > 0; i--) {
var emojiItem = document.createElement('img');
emojiItem.src = '../content/emoji/' + i + '.gif';
emojiItem.title = i;
docFragment.appendChild(emojiItem);
};
emojiContainer.appendChild(docFragment);
},
_displayNewMsg: function(user, msg, color) {
var container = document.getElementById('historyMsg'),
msgToDisplay = document.createElement('p'),
date = new Date().toTimeString().substr(0, 8),
//determine whether the msg contains emoji
msg = this._showEmoji(msg);
msgToDisplay.style.color = color || '#000';
msgToDisplay.innerHTML = user + '<span class="timespan">(' + date + '): </span>' + msg;
container.appendChild(msgToDisplay);
container.scrollTop = container.scrollHeight;
},
_displayImage: function(user, imgData, color) {
var container = document.getElementById('historyMsg'),
msgToDisplay = document.createElement('p'),
date = new Date().toTimeString().substr(0, 8);
msgToDisplay.style.color = color || '#000';
msgToDisplay.innerHTML = user + '<span class="timespan">(' + date + '): </span> <br/>' + '<a href="' + imgData + '" target="_blank">![](' + imgData + ')</a>';
container.appendChild(msgToDisplay);
container.scrollTop = container.scrollHeight;
},
_showEmoji: function(msg) {
var match, result = msg,
reg = /\[emoji:\d+\]/g,
emojiIndex,
totalEmojiNum = document.getElementById('emojiWrapper').children.length;
while (match = reg.exec(msg)) {
emojiIndex = match[0].slice(7, -1);
if (emojiIndex > totalEmojiNum) {
result = result.replace(match[0], '[X]');
} else {
result = result.replace(match[0], '![](../content/emoji/' + emojiIndex + '.gif)');//todo:fix this in chrome it will cause a new request for the image
};
};
return result;
},
_consoleText: function(user,config){
if(window.Notification){
if(Notification.permission === 'granted'){
var notification = new Notification(user,config);
delete notification;
}else{
Notification.requestPermission();
}
}
}
};
-
socket.io
我們要求連接的用戶需要首先設(shè)置一個(gè)昵稱搬素,且這個(gè)昵稱還要唯一,也就是不能與別人同名小渊。一是方便用戶區(qū)分麦向,二是為了統(tǒng)計(jì)在線人數(shù)突硝,同時(shí)也方便維護(hù)一個(gè)保存所有用戶昵稱的數(shù)組再悼。
為此在后臺(tái)server.js中,我們創(chuàng)建一個(gè)名叫users的全局?jǐn)?shù)組變量,當(dāng)一個(gè)用戶設(shè)置好昵稱發(fā)送到服務(wù)器的時(shí)候阅签,將昵稱壓入users數(shù)組矿瘦。同時(shí)注意枕面,如果用戶斷線離開了,也要相應(yīng)地從users數(shù)組中移除以保證數(shù)據(jù)的正確性缚去。
在前臺(tái)潮秘,輸入昵稱點(diǎn)擊OK提交后,我們需要發(fā)起一個(gè)設(shè)置昵稱的事件以便服務(wù)器偵聽到易结。將以下代碼添加到之前的init方法中枕荞。
//昵稱設(shè)置的確定按鈕
document.getElementById('loginBtn').addEventListener('click', function() {
var nickName = document.getElementById('nicknameInput').value;
//檢查昵稱輸入框是否為空
if (nickName.trim().length != 0) {
//不為空,則發(fā)起一個(gè)login事件并將輸入的昵稱發(fā)送到服務(wù)器
that.socket.emit('login', nickName);
} else {
//否則輸入框獲得焦點(diǎn)
document.getElementById('nicknameInput').focus();
};
}, false);
服務(wù)器端:
//socket部分
io.on('connection', function(socket) {
//昵稱設(shè)置
socket.on('login', function(nickname) {
if (users.indexOf(nickname) > -1) {
socket.emit('nickExisted');
} else {
socket.userIndex = users.length;
socket.nickname = nickname;
users.push(nickname);
socket.emit('loginSuccess');
io.sockets.emit('system', nickname); //向所有連接到服務(wù)器的客戶端發(fā)送當(dāng)前登陸用戶的昵稱
};
});
});
在線統(tǒng)計(jì)
這里實(shí)現(xiàn)顯示在線用戶數(shù)及在聊天主界面中以系統(tǒng)身份顯示用戶連接離開等信息搞动。
上面server.js中除了loginSuccess事件躏精,后面還有一句代碼,通過io.sockets.emit 向所有用戶發(fā)送了一個(gè)system事件鹦肿,傳遞了剛登入用戶的昵稱矗烛,所有人接收到這個(gè)事件后,會(huì)在聊天窗口顯示一條系統(tǒng)消息'某某加入了聊天室'箩溃。同時(shí)考慮到在前端我們無法得知用戶是進(jìn)入還是離開瞭吃,所以在這個(gè)system事件里我們多傳遞一個(gè)數(shù)據(jù)來表明用戶是進(jìn)入還是離開碌嘀。
將server.js中l(wèi)ogin事件更改如下:
server.js
socket.on('login', function(nickname) {
if (users.indexOf(nickname) > -1) {
socket.emit('nickExisted');
} else {
socket.userIndex = users.length;
socket.nickname = nickname;
users.push(nickname);
socket.emit('loginSuccess');
io.sockets.emit('system', nickname, users.length, 'login');
};
});
較之前,多傳遞了一個(gè)login字符串歪架。
同時(shí)再添加一個(gè)用戶離開的事件股冗,這個(gè)可能通過socket.io自帶的disconnect事件完成,當(dāng)一個(gè)用戶斷開連接和蚪,disconnect事件就會(huì)觸發(fā)魁瞪。在這個(gè)事件中,做兩件事情惠呼,一是將用戶從users數(shù)組中刪除导俘,一是發(fā)送一個(gè)system事件通知所有人'某某離開了聊天室'。
將以下代碼添加到server.js中connection的回調(diào)函數(shù)中剔蹋。
server.js
//斷開連接的事件
socket.on('disconnect', function() {
//將斷開連接的用戶從users中刪除
users.splice(socket.userIndex, 1);
//通知除自己以外的所有人
socket.broadcast.emit('system', socket.nickname, users.length, 'logout');
});
發(fā)送消息
用戶連接以及斷開我們需要顯示系統(tǒng)消息旅薄,用戶還要頻繁的發(fā)送聊天消息,所以可以考慮將消息顯示到頁面這個(gè)功能單獨(dú)寫一個(gè)函數(shù)方便我們調(diào)用泣崩。為此我們向HiChat類中添加一個(gè)_displayNewMsg的方法少梁,它接收要顯示的消息,消息來自誰矫付,以及一個(gè)顏色共三個(gè)參數(shù)凯沪。因?yàn)槲覀兿胂到y(tǒng)消息區(qū)別于普通用戶的消息,所以增加一個(gè)顏色參數(shù)买优。同時(shí)這個(gè)參數(shù)也方便我們之后實(shí)現(xiàn)讓用戶自定義文本顏色做準(zhǔn)備妨马。
將以下代碼添加到的我的HiChat類當(dāng)中。
//向原型添加業(yè)務(wù)方法
HiChat.prototype = {
init: function() { //此方法初始化程序
//...
},
_displayNewMsg: function(user, msg, color) {
var container = document.getElementById('historyMsg'),
msgToDisplay = document.createElement('p'),
date = new Date().toTimeString().substr(0, 8);
msgToDisplay.style.color = color || '#000';
msgToDisplay.innerHTML = user + '<span class="timespan">(' + date + '): </span>' + msg;
container.appendChild(msgToDisplay);
container.scrollTop = container.scrollHeight;
}
};
在_displayNewMsg方法中杀赢,我們還向消息添加了一個(gè)日期烘跺。我們也判斷了該方法在調(diào)用時(shí)有沒有傳遞顏色參數(shù),沒有傳遞顏色的話默認(rèn)使用#000即黑色脂崔。
同時(shí)修改我們?cè)趕ystem事件中顯示系統(tǒng)消息的代碼滤淳,讓它調(diào)用這個(gè)_displayNewMsg方法。
this.socket.on('system', function(nickName, userCount, type) {
var msg = nickName + (type == 'login' ? ' joined' : ' left');
//指定系統(tǒng)消息顯示為紅色
that._displayNewMsg('system ', msg, 'red');
document.getElementById('status').textContent = userCount + (userCount > 1 ? ' users' : ' user') + ' online';
});
有了這個(gè)顯示消息的方法后砌左,下面就開始實(shí)現(xiàn)用戶之間的聊天功能了脖咐。
做法也很簡(jiǎn)單,如果你掌握了上面所描述的emit發(fā)送事件汇歹,on接收事件屁擅,那么用戶聊天消息的發(fā)送接收也就輕車熟路了。
首先為頁面的發(fā)送按鈕寫一個(gè)click事件處理程序秤朗,我們通過addEventListner來監(jiān)聽這個(gè)click事件煤蹭,當(dāng)用戶點(diǎn)擊發(fā)送的時(shí)候,先檢查輸入框是否為空,如果不為空硝皂,則向服務(wù)器發(fā)送postMsg事件常挚,將用戶輸入的聊天文本發(fā)送到服務(wù)器,由服務(wù)器接收并分發(fā)到除自己外的所有用戶稽物。
將以下代碼添加到main.js的inti方法中奄毡。
document.getElementById('sendBtn').addEventListener('click', function() {
var messageInput = document.getElementById('messageInput'),
msg = messageInput.value;
messageInput.value = '';
messageInput.focus();
if (msg.trim().length != 0) {
that.socket.emit('postMsg', msg); //把消息發(fā)送到服務(wù)器
that._displayNewMsg('me', msg); //把自己的消息顯示到自己的窗口中
};
}, false);
在server.js中添加代碼以接收postMsg事件。
io.on('connection', function(socket) {
//其他代碼贝或。吼过。。
//接收新消息
socket.on('postMsg', function(msg) {
//將消息發(fā)送到除自己外的所有用戶
socket.broadcast.emit('newMsg', socket.nickname, msg);
});
});
然后在客戶端接收服務(wù)器發(fā)送的newMsg事件咪奖,并將聊天消息顯示到頁面盗忱。
將以下代碼顯示添加到main.js的init方法中了。
this.socket.on('newMsg', function(user, msg) {
that._displayNewMsg(user, msg);
});
發(fā)送圖片
圖片不同于文字羊赵,但通過將圖片轉(zhuǎn)化為字符串形式后趟佃,便可以像發(fā)送普通文本消息一樣發(fā)送圖片了,只是在顯示的時(shí)候?qū)⑺€原為圖片昧捷。
在這之前闲昭,我們已經(jīng)將圖片按鈕在頁面放好了,其實(shí)是一個(gè)文件類型的input靡挥,下面只需在它身上做功夫便可序矩。
用戶點(diǎn)擊圖片按鈕后,彈出文件選擇窗口供用戶選擇圖片跋破。之后我們可以在JavaScript代碼中使用FileReader來將圖片讀取為base64格式的字符串形式進(jìn)行發(fā)送簸淀。而base64格式的圖片直接可以指定為圖片的src,這樣就可以將圖片用img標(biāo)簽顯示在頁面了幔烛。
為此我們監(jiān)聽圖片按鈕的change事件啃擦,一但用戶選擇了圖片囊蓝,便顯示到自己的屏幕上同時(shí)讀取為文本發(fā)送到服務(wù)器饿悬。
將以下代碼添加到main.js的init方法中。
document.getElementById('sendImage').addEventListener('change', function() {
//檢查是否有文件被選中
if (this.files.length != 0) {
//獲取文件并用FileReader進(jìn)行讀取
var file = this.files[0],
reader = new FileReader();
if (!reader) {
that._displayNewMsg('system', '!your browser doesn\'t support fileReader', 'red');
this.value = '';
return;
};
reader.onload = function(e) {
//讀取成功聚霜,顯示到頁面并發(fā)送到服務(wù)器
this.value = '';
that.socket.emit('img', e.target.result);
that._displayImage('me', e.target.result);
};
reader.readAsDataURL(file);
};
}, false);
上面圖片讀取成功后狡恬,調(diào)用_displayNImage方法將圖片顯示在自己的屏幕同時(shí)向服務(wù)器發(fā)送了一個(gè)img事件,在server.js中蝎宇,我們通過這個(gè)事件來接收并分發(fā)圖片到每個(gè)用戶弟劲。同時(shí)也意味著我們還要在前端寫相應(yīng)的代碼來接收。
這個(gè)_displayNImage還沒有實(shí)現(xiàn)姥芥,將會(huì)在下面介紹兔乞。
將以下代碼添加到server.js的socket回調(diào)函數(shù)中。
server.js
//接收用戶發(fā)來的圖片
socket.on('img', function(imgData) {
//通過一個(gè)newImg事件分發(fā)到除自己外的每個(gè)用戶
socket.broadcast.emit('newImg', socket.nickname, imgData);
});
main.js
this.socket.on('newImg', function(user, img) {
that._displayImage(user, img);
});
有個(gè)問題就是如果圖片過大,會(huì)破壞整個(gè)窗口的布局庸追,或者會(huì)出現(xiàn)水平滾動(dòng)條霍骄,所以我們對(duì)圖片進(jìn)行樣式上的設(shè)置讓它最多只能以聊天窗口的99%寬度來顯示,這樣過大的圖片就會(huì)自己縮小了淡溯。
#historyMsg img {
max-width: 99%;
}
但考慮到縮小后的圖片有可能失真读整,用戶看不清,我們需要提供一個(gè)方法讓用戶可以查看原尺寸大小的圖片咱娶,所以將圖片用一個(gè)鏈接進(jìn)行包裹米间,當(dāng)點(diǎn)擊圖片的時(shí)候我們打開一個(gè)新的窗口頁面,并將圖片按原始大小呈現(xiàn)到這個(gè)新頁面中讓用戶查看膘侮。
所以最后我們實(shí)現(xiàn)的_displayNImage方法應(yīng)該是這樣的屈糊。
將以下代碼添加到main.js的HiChat類中。
_displayImage: function(user, imgData, color) {
var container = document.getElementById('historyMsg'),
msgToDisplay = document.createElement('p'),
date = new Date().toTimeString().substr(0, 8);
msgToDisplay.style.color = color || '#000';
msgToDisplay.innerHTML = user + '<span class="timespan">(' + date + '): </span> <br/>' + '<a href="' + imgData + '" target="_blank">![](' + imgData + ')</a>';
container.appendChild(msgToDisplay);
container.scrollTop = container.scrollHeight;
}
發(fā)送表情
規(guī)定了一種格式來代表表情琼了,[emoji:xx]另玖,中括號(hào)括起來然后'emoji'加個(gè)冒號(hào),后面跟一個(gè)數(shù)字表伦,這個(gè)數(shù)字表示某個(gè)gif圖片的編號(hào)谦去。程序中,如果我們點(diǎn)擊表情按扭蹦哼,然后呈現(xiàn)所有可用的表情圖片鳄哭,當(dāng)用戶選擇一個(gè)表情后,生成對(duì)應(yīng)的代碼插入到當(dāng)前待發(fā)送的文字消息中纲熏。發(fā)出去后妆丘,每個(gè)人接收到的也是代碼形式的消息,只是在將消息顯示到頁面前局劲,我們將表情代碼提取出來勺拣,獲取圖片編號(hào),然后用相應(yīng)的圖片替換鱼填。
文字顏色
_displayNewMsg方法可以接收一個(gè)color參數(shù)药有,現(xiàn)在要做的就是每次發(fā)送消息到服務(wù)器的時(shí)候,多加一個(gè)color參數(shù)就可以了苹丸,同時(shí)愤惰,在顯示消息時(shí)調(diào)用_displayNewMsg的時(shí)候?qū)⑦@個(gè)color傳遞過去。
下面是修改main.js中消息發(fā)送按鈕代碼的示例:
document.getElementById('sendBtn').addEventListener('click', function() {
var messageInput = document.getElementById('messageInput'),
msg = messageInput.value,
//獲取顏色值
color = document.getElementById('colorStyle').value;
messageInput.value = '';
messageInput.focus();
if (msg.trim().length != 0) {
//顯示和發(fā)送時(shí)帶上顏色值參數(shù)
that.socket.emit('postMsg', msg, color);
that._displayNewMsg('me', msg, color);
};
}, false);
同樣socket的綁定事件 newMsg
this.socket.on('newMsg', function(user, msg, color) {
that._displayNewMsg(user, msg, color);
});
這只是展示了發(fā)送按鈕的修改赘理,改動(dòng)非常小宦言,只是每次消息發(fā)送時(shí)獲取一下顏色值,同時(shí)emit事件到服務(wù)器的時(shí)候也帶上這個(gè)顏色值商模,這樣前端在顯示時(shí)就可以根據(jù)這個(gè)顏色值為每個(gè)不兩只用戶顯示他們自己設(shè)置的顏色了奠旺。
三.HTML5桌面提醒(Notification)
在聊天中,雖然已經(jīng)有顯示,某位用戶登錄.但如果用戶不在該頁面時(shí),如果A用戶要通知B用戶,例如QQ的抖一抖;
HTML5提供最新的API: Notification
微信用Notification綁定socket,來做即時(shí)通訊,通知用戶.Notification的兼容最新瀏覽器,如圖
同理,server.js:
//new Notification
socket.on('noti',function(config){
socket.broadcast.emit('notification',socket.nickname,config);
});
main.js:
this.socket.on('notification',function(user,config){
that._consoleText(user,config);
});
document.getElementById('notifBtn').addEventListener('click',function(){
var config = {
body: '我發(fā)起了一個(gè)描述~', //正文內(nèi)容
dir: 'auto',//文本顯示方向 auto ,ltr,rtl
lang:'en', //文本語言
icon: 'http://img4.imgtn.bdimg.com/it/u=196405673,1932175745&fm=23&gp=0.jpg' //圖片的URL,將被用于顯示通知的圖標(biāo)
};
that.socket.emit('noti',config);
return;
}, false);
同樣,需要把_consoleText添加到HiChat類中:
_consoleText: function(user,config){
if(window.Notification){
if(Notification.permission === 'granted'){
var notification = new Notification(user,config);
delete notification;
}else{
Notification.requestPermission();
}
}
}