使用 node + express + socket 來一個即時聊天~

首先需要在電腦安裝Node.js 如果基礎不好的話看下官網瞭解一下
然後我們就可以搭建一個簡單的HTTP服務器了

下面搭建一個簡單的服務器瞭解一下不是正文
首先在文件目錄裏創建server.js內容爲:

//引入http模塊
var http = require('http'),
    //創建一個服務器
    server = http.createServer(function (req, res) {
        res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); // 這個是中文防亂碼
        res.write('隨便寫點東西!!!');
        res.end();
    });
//監聽80端口
server.listen(666);
console.log('服務器在666端口打開');

然後在終端輸入:node server 就會提示 服務器在666端口打開
然後在瀏覽器輸入http://localhost:666/就可以看到我們寫的 ‘隨便寫點東西!!!’ 內容

然後下面開始進入正文
首先安裝一下express 命令爲 : npm install express 回車進行安裝
然後在server.js中通過require('express')將其引入
express是node.js中管理路由響應請求的模塊,根據請求的URL返回相應的HTML頁面。這裏我們使用一個事先寫好的靜態頁面返回給客戶端,只需使用express指定要返回的頁面的路徑即可。如果不用這個包,我們需要將HTML代碼與後臺JavaScript代碼寫在一起進行請求的響應,比較麻煩。

在存放上一步創建的server.js文件的地方,我們新建一個文件夾名字public用來存放我們的網頁文件,包括圖片以及前端的js文件等。假設已經在public文件夾下寫好了一個index.html文件(將在下一步介紹,這一步你可以放一個空的HTML文件),則可以通過以下方式使用express將該頁面返回到瀏覽器。可以看到較最開始,我們的服務器代碼簡潔了不少。
那麼 下一步我們創建一個public文件夾 裏面先創建一個index.html文件以及index.css文件

index.html

<!doctype html>
<html>

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="author" content="Wayou">
    <meta name="description" content="hichat | a simple chat application built with node.js and websocket">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>騷聊</title>
    <!-- 引入css樣式 -->
    <link rel="stylesheet" href="./index.css">
    <!-- 這裏先引入socket 以及 index.js 先引入一下一會講解 -->
    <script src="/socket.io/socket.io.js"></script>
    <script src="./index.js"></script>
</head>

<body>
    <div class="wrapper">
        <div class="banner">
            <h1>開始聊騷吧</h1>
            <!-- 頂部的人數顯示 -->
            <span id="status"></span>
        </div>
        <!-- historyMsg 寫發送的內容的 -->
        <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" />
            </div>
            <!-- 發送內容的input框 -->
            <textarea id="messageInput" placeholder="請輸入騷掉牙的話"></textarea>
            <input id="sendBtn" type="button" value="發送">
            <div id="emojiWrapper">
            </div>
        </div>
    </div>
    <div id="loginWrapper">
        <p id="info">服務器連接中...</p>
        <!-- 服務器瞭解成功後顯示這個 nickWrapper -->
        <div id="nickWrapper">
            <!-- 對應的讓這個文本框獲取焦點 -->
            <input type="text" placeholder="請輸入騷氣點的名字" id="nicknameInput" />
            <input type="button" value="OK" id="loginBtn" />
            <!-- 點擊名字的確定按鈕 -->
        </div>
    </div>
</body>
<!-- <script type="text/javascript">
        var socket = io.connect(),//與服務器進行連接
            button = document.getElementById('sendBtn');
        button.onclick = function () {
            socket.emit('foo', 'hello');//發送一個名爲foo的事件,並且傳遞一個字符串數據‘hello’
        }
    </script> -->

</html>

這裏先引入 socket 以及 index.js 一會講解 socket 是需要下載的 index.js是自己創建的

index.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;
}

ok 到這步後簡單的頁面以及樣式就已經排好了,當然還差一步就是在server.js去設置
server.js

var express = require('express'), //引入express模塊
    app = express(),
    server = require('http').createServer(app);
app.use('/', express.static(__dirname + '/public')); //指定靜態HTML文件的位置
server.listen(666);

這樣的輸入node server 就可以看到搭建的簡單樣式了 那麼功能如何實現呢?

在Node.js中使用socket的一個包。使用它可以很方便地建立服務器到客戶端的sockets連接,發送事件與接收特定事件。
同樣通過npm進行安裝 npm install socket.io 安裝後在node_modules文件夾下新生成了一個socket.io文件夾,其中我們可以找到一個socket.io.js文件。將它引入到HTML頁面,這樣我們就可以在前端使用socket.io與服務器進行通信了。
剛纔已經引入過了

同時服務器端的server.js裏跟使用express一樣,也要通過require('socket.io')將其引入到項目中,這樣就可以在服務器端使用socket.io了。
使用socket.io,其前後端句法是一致的,即通過socket.emit()來激發一個事件,通過socket.on()來偵聽和處理對應事件。這兩個事件通過傳遞的參數進行通信。具體工作模式可以看下面這個示例。

下面咱們在index.html進行測試,簡單瞭解一下

上面有個button按鈕就不寫了
<script>
	var socket=io.connect(),//與服務器進行連接
		button=document.getElementById('sendBtn');
	button.onclick=function(){
		socket.emit('foo', 'hello');//發送一個名爲foo的事件,並且傳遞一個字符串數據‘hello’
	}
</script>

然後server.js配置如下

//服務器及頁面響應部分
var express = require('express'),
    app = express(),
    server = require('http').createServer(app),
    io = require('socket.io').listen(server); //引入socket.io模塊並綁定到服務器
app.use('/', express.static(__dirname + '/public'));
server.listen(666);
console.log("服務器在666端口打開")
//socket部分
io.on('connection', function (socket) {
    //接收並處理客戶端發送的foo事件
    socket.on('foo', function (data) {
        //將消息輸出到控制檯
        console.log(data);
    })
});

這樣的話點擊過後再終端就會輸出hello 現在主要是瞭解一下這個 測試完刪掉即可

有了上面一些瞭解,下面可以進入騷聊的功能開發了

此刻打開頁面我們看到的是一個淡黑色的遮罩層,而接下來我們要實現的是用戶暱稱的輸入與服務器登入。這個遮罩層用於顯示連接到服務器的狀態信息,而當連接完成之後,會出現一個輸入框用於暱稱輸入。
也就是意味着我們只要連接成功就可以輸入騷氣點的名稱了

之前我們已經把index.js引入頁面了那麼開始搞吧
首先在index.js裏
定義一個全局變量用於我們整個程序的開發HiChat(名字隨便起),
同時使用window.onload在頁面準備好之後實例化HiChat,調用其init方法運行我們的程序。

window.onload = function() {
    //實例並初始化我們的hichat程序
    var hichat = new HiChat();
    hichat.init();
};

//定義我們的hichat類
var HiChat = function() {
    this.socket = null;
};

//向原型添加業務方法
HiChat.prototype = {
    init: function() {//此方法初始化程序
        var that = this;
        //建立到服務器的socket連接
        this.socket = io.connect();
        //監聽socket的connect事件,此事件表示連接已經建立
        this.socket.on('connect', function() {
            //連接到服務器後,顯示暱稱輸入框
            document.getElementById('info').textContent = '請輸入一個騷氣的名字';
            document.getElementById('nickWrapper').style.display = 'block';
            document.getElementById('nicknameInput').focus();
        });
    }
};

上面的代碼定義了整個程序需要使用的類HiChat,之後我們處理消息顯示消息等所有業務邏輯均寫在這個類裏面。
首先定義了一個程序的初始化方法,這裏面初始化socket,監聽連接事件,一旦連接到服務器,便顯示暱稱輸入框。當用戶輸入暱稱後,便可以在服務器後臺接收到然後進行下一步的處理了。
這樣我們從新運行就可以看到請輸入騷氣的名字了
下面呢
我們要求連接的用戶需要首先設置一個暱稱,且這個暱稱還要唯一,也就是不能與別人同名。一是方便用戶區分,二是爲了統計在線人數,同時也方便維護一個保存所有用戶暱稱的數組。
爲此在後臺server.js中,我們創建一個名叫users的全局數組變量,當一個用戶設置好暱稱發送到服務器的時候,將暱稱壓入users數組。同時注意,如果用戶斷線離開了,也要相應地從users數組中移除以保證數據的正確性。
在前臺,輸入暱稱點擊OK提交後,我們需要發起一個設置暱稱的事件以便服務器偵聽到。將以下代碼添加到之前的init方法中。
index.js

//暱稱設置的確定按鈕
 //名字的確定按鈕
        document.getElementById('loginBtn').addEventListener('click', function () {
            var nickName = document.getElementById('nicknameInput').value;
            // nicknameInput 輸入名字的input框
            //檢查暱稱輸入框是否爲空
            if (nickName.trim().length != 0) {
                //不爲空,則發起一個login事件並將輸入的暱稱發送到服務器
                that.socket.emit('login', nickName);
            } else {
                //否則輸入框獲得焦點
                document.getElementById('nicknameInput').focus();
            };
        }, false);

server.js


//服務器及頁面響應部分
var express = require('express'),
    app = express(),
    server = require('http').createServer(app),
    io = require('socket.io').listen(server); //引入socket.io模塊並綁定到服務器
    users = [];//這個用於存放一些用戶
app.use('/', express.static(__dirname + '/public'));
server.listen(666);
console.log("服務器在666端口打開")
//socket部分
// io.on('connection', function (socket) {
//     //接收並處理客戶端發送的foo事件
//     socket.on('foo', function (data) {
//         //將消息輸出到控制檯
//         console.log(data);
//     })
// });
io.sockets.on('connection', function (socket) {
    //login 這裏的login就是咱點擊輸入名字的login
    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');
        };
    });


})

需要解釋一下的是,在connection事件的回調函數中,socket表示的是當前連接到服務器的那個客戶端。所以代碼socket.emit(‘foo’)則只有自己收得到這個事件,而socket.broadcast.emit(‘foo’)則表示向除自己外的所有人發送該事件,另外,上面代碼中,io表示服務器整個socket連接,所以代碼io.sockets.emit(‘foo’)表示所有人都可以收到該事件。
上面代碼先判斷接收到的暱稱是否已經存在在users中,如果存在,則向自己發送一個nickExisted事件,在前端接收到這個事件後我們顯示一條信息通知用戶。

接下來添加一段代碼在index.js中

this.socket.on('nickExisted', function() {
     document.getElementById('info').textContent = '這個騷氣的名字已經被佔用'; //顯示暱稱被佔用的提示
 });

如果暱稱沒有被其他用戶佔用,則將這個暱稱壓入users數組,同時將其作爲一個屬性存到當前socket變量中,並且將這個用戶在數組中的索引(因爲是數組最後一個元素,所以索引就是數組的長度users.length)也作爲屬性保存到socket中,後面會用到。最後向自己發送一個loginSuccess事件,通知前端登陸成功,前端接收到這個成功消息後將灰色遮罩層移除顯示聊天界面。

將下面代碼添加到index.js的init方法中。

this.socket.on('loginSuccess', function() {
     document.title = 'hichat | ' + document.getElementById('nicknameInput').value;
     document.getElementById('loginWrapper').style.display = 'none';//隱藏遮罩層顯聊天界面
     document.getElementById('messageInput').focus();//讓消息輸入框獲得焦點
 });

// 用戶離開 在 server.js
//斷開連接的事件

socket.on('disconnect', function() {
    //將斷開連接的用戶從users中刪除
    users.splice(socket.userIndex, 1);
    //通知除自己以外的所有人
    socket.broadcast.emit('system', socket.nickname, users.length, 'logout');
});

然後在index.js中的init方法中

this.socket.on('system', function(nickName, userCount, type) {
     //判斷用戶是連接還是離開以顯示不同的信息
     var msg = nickName + (type=='login'?'上線':'離線');
     var p = document.createElement('p');
     p.textContent = msg;
     document.getElementById('historyMsg').appendChild(p);
     //將在線人數顯示到頁面頂部
     document.getElementById('status').textContent = userCount + (userCount > 1 ? ' users' : ' user') + ' 在線';
 });

現在運行程序,打開多個瀏覽器標籤,然後登陸離開,你就可以看到相應的系統提示消息了。

下面開始發送消息
用戶連接以及斷開我們需要顯示系統消息,用戶還要頻繁的發送聊天消息,所以可以考慮將消息顯示到頁面這個功能單獨寫一個函數方便我們調用。爲此我們向HiChat類中添加一個_displayNewMsg的方法,它接收要顯示的消息,消息來自誰,以及一個顏色共三個參數。因爲我們想系統消息區別於普通用戶的消息,所以增加一個顏色參數。同時這個參數也方便我們之後實現讓用戶自定義文本顏色做準備。
不是init了哈是HiChat類裏面

//向原型添加業務方法
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方法中,我們還向消息添加了一個日期。我們也判斷了該方法在調用時有沒有傳遞顏色參數,沒有傳遞顏色的話默認使用#000即黑色。

同時修改我們在system事件中顯示系統消息的代碼,讓它調用這個_displayNewMsg方法。

index.js

 this.socket.on('system', function (nickName, userCount, type) {
            var msg = nickName + (type == 'login' ? ' 上線' : ' 下線');
            //指定系統消息顯示爲紅色
            that._displayNewMsg('用戶 ', msg, 'red');
            document.getElementById('status').textContent = userCount + (userCount > 1 ? ' users' : ' user') + ' 在線';
        });

有了這個顯示消息的方法後,下面就開始實現用戶之間的聊天功能了。
做法也很簡單,如果你掌握了上面所描述的emit發送事件,on接收事件,那麼用戶聊天消息的發送接收也就輕車熟路了。
首先爲頁面的發送按鈕寫一個click事件處理程序,我們通過addEventListner來監聽這個click事件,當用戶點擊發送的時候,先檢查輸入框是否爲空,如果不爲空,則向服務器發送postMsg事件,將用戶輸入的聊天文本發送到服務器,由服務器接收並分發到除自己外的所有用戶。

將以下代碼添加到index.js的init方法中。

index.js

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); //把消息發送到服務器
        that._displayNewMsg('me', msg); //把自己的消息顯示到自己的窗口中
    };
}, false);

在server.js中添加代碼以接收postMsg事件。

server.js

// 信息內容
    socket.on('postMsg', function (msg, color) {
        socket.broadcast.emit('newMsg', socket.nickname, msg, color);
    });

然後在客戶端接收服務器發送的newMsg事件,並將聊天消息顯示到頁面。

將以下代碼顯示添加到index.js的init方法中了。

this.socket.on('newMsg', function(user, msg) {
    that._displayNewMsg(user, msg);
});

運行程序,現在可以發送聊天消息了。

發送圖片
上面已經實現了基本的聊天功能了,進一步,如果我們還想讓用戶可以發送圖片,那程序便更加完美了。

圖片不同於文字,但通過將圖片轉化爲字符串形式後,便可以像發送普通文本消息一樣發送圖片了,只是在顯示的時候將它還原爲圖片。

在這之前,我們已經將圖片按鈕在頁面放好了,其實是一個文件類型的input,下面只需在它身上做功夫便可。

用戶點擊圖片按鈕後,彈出文件選擇窗口供用戶選擇圖片。之後我們可以在JavaScript代碼中使用FileReader來將圖片讀取爲base64格式的字符串形式進行發送。而base64格式的圖片直接可以指定爲圖片的src,這樣就可以將圖片用img標籤顯示在頁面了。

爲此我們監聽圖片按鈕的change事件,一但用戶選擇了圖片,便顯示到自己的屏幕上同時讀取爲文本發送到服務器。

將以下代碼添加到index.js的init方法中。

index.js

document.getElementById('sendImage').addEventListener('change', function() {
    //檢查是否有文件被選中
     if (this.files.length != 0) {
        //獲取文件並用FileReader進行讀取
         var file = this.files[0],
             reader = new FileReader();
         if (!reader) {
             that._displayNewMsg('system', '這裏是錯誤信息', 'red');
             this.value = '';
             return;
         };
         reader.onload = function(e) {
            //讀取成功,顯示到頁面併發送到服務器
             this.value = '';
             that.socket.emit('img', e.target.result);
             that._displayImage('me', e.target.result);
         };
         reader.readAsDataURL(file);
     };
 }, false);

上面圖片讀取成功後,調用_displayNImage方法將圖片顯示在自己的屏幕同時向服務器發送了一個img事件,在server.js中,我們通過這個事件來接收並分發圖片到每個用戶。同時也意味着我們還要在前端寫相應的代碼來接收。

這個_displayNImage還沒有實現,將會在下面介紹。

將以下代碼添加到server.js的socket回調函數中。

server.js

 //image
    socket.on('img', function (imgData, color) {
        socket.broadcast.emit('newImg', socket.nickname, imgData, color);
    });

同時向index.js的init方法添加以下代碼以接收顯示圖片。

 this.socket.on('newImg', function(user, img) {
     that._displayImage(user, img);
 });

但考慮到縮小後的圖片有可能失真,用戶看不清,我們需要提供一個方法讓用戶可以查看原尺寸大小的圖片,所以將圖片用一個鏈接進行包裹,當點擊圖片的時候我們打開一個新的窗口頁面,並將圖片按原始大小呈現到這個新頁面中讓用戶查看。

所以最後我們實現的_displayNImage方法應該是這樣的。

將以下代碼添加到index.js的HiChat類中。

index.js

_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"><img src="' + imgData + '"/></a>';
    container.appendChild(msgToDisplay);
    container.scrollTop = container.scrollHeight;
}

發送表情
我們使用兔斯基作爲我們聊天程序的表情包。可以看到,有很多張gif圖,如果手動編寫的話,要花一些功夫,不斷地寫<img src='*****.gif'/>,所以考慮將這個工作交給代碼來自動完成,寫一個方法來初始化所有表情。

爲此將以下代碼添加到HiChat類中,並在init方法中調用這個方法。

index.js

_initialEmoji: function() {
    var emojiContainer = document.getElementById('emojiWrapper'),
        docFragment = document.createDocumentFragment();
    for (var i = 69; i > 0; i--) {
        var emojiItem = document.createElement('img');
        emojiItem.src = './emoji/' + i + '.gif';
        emojiItem.title = i;
        docFragment.appendChild(emojiItem);
    };
    emojiContainer.appendChild(docFragment);
}
_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], '<img class="emoji" src="./emoji/' + emojiIndex + '.gif" />');//todo:fix this in chrome it will cause a new request for the image
            };
        };
        return result;
    }

同時將以下代碼添加到index.js的init方法中。

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';
     };
 });

上面向頁面添加了兩個單擊事件,一是表情按鈕單擊顯示錶情窗口,二是點擊頁面其他地方關閉表情窗口。

現在要做的就是,具體到某個表情被選中後,需要獲取被選中的表情,然後轉換爲相應的表情代碼插入到消息框中。

爲此我們再寫一個這些圖片的click事件處理程序。將以下代碼添加到index.js的init方法中。

index.js

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);

現在表情選中後,消息輸入框中可以得到相應的代碼了。

之後的發送也普通消息發送沒區別,因爲之前已經實現了文本消息的發送了,所以這裏不用再實現什麼,只是需要更改一下之前我們用來顯示消息的代碼,首先判斷消息文本中是否含有表情符號,如果有,則轉換爲圖片,最後再顯示到頁面。

爲此我們寫一個方法接收文本消息爲參數,用正則搜索其中的表情符號,將其替換爲img標籤,最後返回處理好的文本消息。

將以下代碼添加到HiChat類中。

index.js

_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], '<img class="emoji" src="../content/emoji/' + emojiIndex + '.gif" />');
        };
    };
    return result;
}

現在去修改之前我們顯示消息的_displayNewMsg方法,讓它在顯示消息之前調用這個_showEmoji方法。

_displayNewMsg: function (user, msg, color) {
        //historyMsg 發送的內容
        var container = document.getElementById('historyMsg'),
            msgToDisplay = document.createElement('p'),
            date = new Date().toTimeString().substr(0, 8);
            //將消息中的表情轉化爲圖片
        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;
    },

_showEmoji這個我重複寫了一下 反正就一個 注意一個就好了 這裏我不進行修改了

文字顏色
HTML5新增了一個專門用於顏色選取的input標籤,並且Chrome對它的支持非常之贊,直接彈出系統的顏色拾取窗口。
IE及FF中均是一個普通的文本框,不過不影響使用,只是用戶只能通過輸入具體的顏色值來進行顏色設置,沒有Chrome裏面那麼方便也直觀。

之前我們的_displayNewMsg方法可以接收一個color參數,現在要做的就是每次發送消息到服務器的時候,多加一個color參數就可以了,同時,在顯示消息時調用_displayNewMsg的時候將這個color傳遞過去。

下面是修改index.js中消息發送按鈕代碼的示例:

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);
    };
}, false);

同時修改index.js中接收消息的代碼,讓它接收顏色值

this.socket.on('newMsg', function(user, msg, color) {
     that._displayNewMsg(user, msg, color);
 });

這只是展示了發送按鈕的修改,改動非常小,只是每次消息發送時獲取一下顏色值,同時emit事件到服務器的時候也帶上這個顏色值,這樣前端在顯示時就可以根據這個顏色值爲每個不兩隻用戶顯示他們自己設置的顏色了。剩下的就是按相同的做法把發送圖片時也加上顏色,這裏省略。

清空

 //清空
        document.getElementById('clearBtn').addEventListener('click', function () {
            document.getElementById('historyMsg').innerHTML = '';
        }, false);

按鍵操作
將以下代碼添加到index.js的init方法中,這樣在輸入暱稱後,按回車鍵就可以登陸,進入聊天界面後,回車鍵可以發送消息。

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('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);

現在搞完了可以添加一個package.json文件
這樣別人就可以拷貝過來過去我的代碼了

{
    "name": "ssl",
    "description": "a realtime chat web application",
    "version": "0.4.0",
    "main": "server.js",
    "dependencies": {
        "express": "3.4.x",
        "socket.io": "0.9.x"
    },
    "engines": {
        "node": "0.10.x",
        "npm": "1.2.x"
    }
}

最後我把他上傳到了gitHub:https://github.com/user-sunshilin/-
現在這個文件是更新了一下 github上面的是之前寫的 不影響一點點程序跑起來
拿到過後 npm install 下載依賴包 然後 node server 跑起來

當然也可以部署到線上~
寫好過後 就開始愉快的聊天吧~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章