
使用 Socket.io 的即時 Web Apps
Broadcasting Events
- 刪除 server/server.js 和 public/js/index.js 的 socket.emit
- 在 server/server.js 新增 io.emit
1 | socket.on('createMessage', (message) => { |
git push heroku master
- 在 server/server.js 新增兩種 emit,如果 connect 就傳送歡迎,如果有新用戶進來,就 broadcast 新用戶加入
1 | socket.emit('newMessage', { |
訊息產生器和測試
- 新增 server/utils/message.js
1 | var generateMessage = (from, text) => { |
npm install expect mocha --save-dev
- 修改 package.json
1 | "test": "mocha server/**/*.test.js", |
- 新增 server/utils/message.test.js
npm test
- 修改 server/utils/message.test.js
1 | var expect = require('expect'); |
- 在 server/server.js 引入
const {generateMessage} = require('./utils/message');
- 將 server/server.js 的 object 換成 function
1 | socket.emit('newMessage', generateMessage('Admin', 'Welcome to the chat app')); |
Event Acknowledgements
- 在 public/js/index.js 新增 emit
1 | socket.emit('createMessage', { |
- 在 server/server.js 新增 callback function
1 | socket.on('createMessage', (message, callback) => { |
訊息表單和 jQuery
- 下載最新版的 jQuery
- 放到 public/js/libs/jquery.js
- 在 public/index.html 引入
<script src="/js/libs/jquery-3.2.1.min.js"></script>
- 在 public/index.html 新增 form
1 | <form id="message-form"> |
- 在 public/js/index.js 新增 jQuery 來取得 form 傳出來的訊息
1 | jQuery('#message-form').on('submit', function (e) { |
- 在 public/index.html 新增
<ol id="messages"></ol>
讓傳出得的訊息 console 在頁面上 - 在 public/js/index.js 將取得的文字用 jQuery 創建元素並顯示在前端
1 | socket.on('newMessage', function (message) { |
git push heroku master
Geolocation
- Geolocation 官方文件
- 在 public/index.html 新增 button
<button id="send-location">Send Location</button>
- 在 public/js/index.js 新增 click 事件,當點擊時傳送出 location 的資訊
1 | var locationButton = jQuery('#send-location'); |
- 在 server/server.js 新增 newMessage 把訊息傳到前端頁面
1 | socket.on('createLocationMessage', (coords) => { |
- 在 server/server.js 新增新的 message,讓 locaiton 可以超連結
1 | socket.on('createLocationMessage', (coords) => { |
- 在 server/utils/message.js 新增 generateLocationMessage 並 export
1 | var generateLocationMessage = (from, latitude, longitude) => { |
- 在 public/js/index.js 將取得的 location 傳送到前端頁面
1 | socket.on('newLocationMessage', function (message) { |
- 在 server/utils/message.test.js 測試 generateLocationMessage 可以運作
1 | describe('generateLocationMessage', () => { |
git push heroku master
裝飾聊天頁面
- 樣式
- 新增 public/css/styles.css
1 | button,button:hover{border:none;color:#fff;padding:10px}.chat__messages,.chat__sidebar ul{list-style-type:none}*{box-sizing:border-box;margin:0;padding:0;font-family:HelveticaNeue-Light,"Helvetica Neue Light","Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif;font-weight:300;font-size:.95rem}li,ul{list-style-position:inside}h3{font-weight:600;text-align:center;font-size:1.5rem}button{background:#265f82;cursor:pointer;transition:background .3s ease}button:hover{background:#1F4C69}button:disabled{cursor:default;background:#698ea5}.centered-form{display:flex;align-items:center;height:100vh;width:100vw;justify-content:center;background:-moz-linear-gradient(125deg,rgba(39,107,130,1) 0,rgba(49,84,129,1) 100%);background:-webkit-gradient(linear,left top,right bottom,color-stop(0,rgba(49,84,129,1)),color-stop(100%,rgba(39,107,130,1)));background:-webkit-linear-gradient(125deg,rgba(39,107,130,1) 0,rgba(49,84,129,1) 100%);background:-o-linear-gradient(125deg,rgba(39,107,130,1) 0,rgba(49,84,129,1) 100%);background:-ms-linear-gradient(125deg,rgba(39,107,130,1) 0,rgba(49,84,129,1) 100%);background:linear-gradient(325deg,rgba(39,107,130,1) 0,rgba(49,84,129,1) 100%)}.centered-form__form{background:rgba(250,250,250,.9);border:1px solid #e1e1e1;border-radius:5px;padding:0 20px;margin:20px;width:230px}.form-field{margin:20px 0}.form-field>*{width:100%}.form-field label{display:block;margin-bottom:7px}.form-field input,.form-field select{border:1px solid #e1e1e1;padding:10px}.chat{display:flex}.chat__sidebar{overflow-y:scroll;width:260px;height:100vh;background:-moz-linear-gradient(125deg,rgba(39,107,130,1) 0,rgba(49,84,129,1) 100%);background:-webkit-gradient(linear,left top,right bottom,color-stop(0,rgba(49,84,129,1)),color-stop(100%,rgba(39,107,130,1)));background:-webkit-linear-gradient(125deg,rgba(39,107,130,1) 0,rgba(49,84,129,1) 100%);background:-o-linear-gradient(125deg,rgba(39,107,130,1) 0,rgba(49,84,129,1) 100%);background:-ms-linear-gradient(125deg,rgba(39,107,130,1) 0,rgba(49,84,129,1) 100%);background:linear-gradient(325deg,rgba(39,107,130,1) 0,rgba(49,84,129,1) 100%)}.chat__footer,.chat__sidebar li{background:#e6eaee;padding:10px}.chat__sidebar h3{color:#e6eaee;margin:10px 20px;text-align:left}.chat__sidebar li{border:1px solid #e1e1e1;border-radius:5px;margin:10px}.chat__main{display:flex;flex-direction:column;height:100vh;width:100%}.chat__messages{flex-grow:1;overflow-y:scroll;-webkit-overflow-scrolling:touch;padding:10px}.chat__footer{display:flex;flex-shrink:0}.chat__footer form{flex-grow:1;display:flex}.chat__footer form *{margin-right:10px}.chat__footer input{border:none;padding:10px;flex-grow:1}.message{padding:10px}.message__title{display:flex;margin-bottom:5px}.message__title h4{font-weight:600;margin-right:10px}.message__title span{color:#999}@media (max-width:600px){*{font-size:1rem}.chat__sidebar{display:none}.chat__footer{flex-direction:column}.chat__footer form{margin-bottom:10px}.chat__footer button{margin-right:0}} |
- 在 public/index.html 引入
<link rel="stylesheet" href="/css/styles.css">
- 在 public/index.html 加入樣式
1 | <body class="body"> |
- 在 server/server.js 把 callback 改為空值
1 | socket.on('createMessage', (message, callback) => { |
- 修改 public/js/index.js 用 jQuery 取得值,然後送到 server
1 | jQuery('#message-form').on('submit', function (e) { |
- 修改 public/js/index.js 當送出的時候把按鈕變成無法點擊,完成之後就移除無法點擊的效果
1 | locationButton.on('click', function () { |
Timestamps 和使用 Moment 格式化
npm i moment --save
- Momentjs 官方網站
- 新增 playground/time.js 測試 moment.js
1 | var moment = require('moment'); |
Printing Message Timestamps
- 修改 server/utils/message.js,引入 moment,然後將 createdAt 改為 moment().valueOf();
1 | var moment = require('moment'); |
npm test
,確定測試可以通過- 從 node_modules/moment/moment.js 複製檔案到 public/js/libs/moment.js
- 在 public/index.html 引入
<script src="/js/libs/moment.js"></script>
- 讓訊息送出時,同時顯示時間
1 | var formattedTime = moment(message.createdAt).format('h:mm a'); |