Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

v0.9.2b

* 新增線上湯友功能
* 新增進度BAR 主持人可調整
  • Loading branch information...
commit acb8576712d70432b794408491cc0ef515a3bc65 1 parent fa39726
@tpai authored
View
45 app.js
@@ -4,10 +4,11 @@ var soup = [
"id": "1",
"title": "歡樂聊天區",
"hostman": "Han-lin Pai",
- "previous": "今天也要好好喝湯喔 (啾咪",
+ "previous": "******** 新功能亮相 *********\n* 新增線上湯友功能\n* 新增過濾連結與圖片功能\n* 新增進度BAR 主持人可調整\n* 新增留言歷史功能 ( 在對話框中按方向鍵上下可顯示之前留言 )\n* 新增TAG姓名功能 ( 輸入 [username] 或點行頭的玩家姓名 )\n* 新增TAG行高亮功能 ( 輸入 :14 第十四行會以粉紅色底標亮 )",
"host_inf": "",
"guest_inf": "",
"answer": "",
+ "progress": 0,
"online": "0"
}
]
@@ -15,6 +16,9 @@ var soup = [
//聊天紀錄
var chatroom = []
+//在線玩家
+var online_user = []
+
var express = require("express"),
app = express(),
http = require("http"),
@@ -45,15 +49,44 @@ app.configure(function () {
})
io.sockets.on("connection", function (socket) {
- socket.on("disconnect", function () {
- // console.log("Client disconnected!")
+ //使用者離線
+ socket.on('disconnect', function () {
+ for(var i=0;i<online_user.length;i++) {
+ var val = online_user[i]
+ if(val.socket_id == socket.id)online_user.splice(i, 1)
+ }
})
-
+ //使用者登入
socket.on("user_login", function (data) {
- console.log("User "+data.username+" login!")
+ online_user.push({
+ socket_id: socket.id,
+ username: data.username,
+ where: data.where,
+ soup_id: data.soup_id
+ })
+ // console.log(online_user)
+ console.log("Online User ---")
+ for(var i=0;i<online_user.length;i++) {
+ var user = online_user[i]
+ console.log(user.username+"@"+user.where+"#"+user.soup_id)
+ }
+ //送出湯列表
socket.emit("res_soup_list", { list: soup })
- // console.log("Emit soup list to client!")
+ })
+
+ //當前網頁有哪些使用者
+ socket.on("visitor", function (data) {
+ var visitor = []
+ for(var i=0;i<online_user.length;i++) {
+ var val = online_user[i]
+ if(val.where == data.where && val.soup_id == data.soup_id) {
+ visitor.push(val.username)
+ }
+ if(i == online_user.length - 1) {
+ socket.emit("visitor", { visitor: visitor })
+ }
+ }
})
//將談話加入陣列
View
2  package.json
@@ -1,6 +1,6 @@
{
"name": "turtlesoup",
- "version": "0.9.1b",
+ "version": "0.9.2b",
"description": "喝海龜湯有助於增進聯想、邏輯與推理能力,海龜湯網頁版讓你輕鬆喝隨處喝!",
"main": "app.js",
"scripts": {
View
15 www/css/main.css
@@ -19,4 +19,19 @@ img {
}
.gray {
color: gray;
+}
+.highlight {
+ position: absolute;
+ background-color: pink;
+ z-index: -1;
+ display: none;
+}
+.tag_name {
+ background-color: #D2DFF6;
+ border:#bdc7d8 1px solid;
+ padding: 2px;
+}
+.label_style {
+ font-size: 14px;
+ font-weight: bold;
}
View
46 www/index.html
@@ -12,71 +12,85 @@
<div class="row">
<div id="list" class="span12">
<center>
- <h4>
+ <h5>
<a href="http://forum.gamer.com.tw/C.php?bsn=60219&snA=1265&tnum=7" target="_blank">《海龜湯是什麼》</a>
/
<a href="http://forum.gamer.com.tw/C.php?bsn=60219&snA=1756&tnum=9" target="_blank">《怎麼出題呢》</a>
- </h4>
- <input type="button" id="create" class="btn btn-large btn-primary" value="煮一碗好喝的海龜湯" onclick="javascript:location.href='/create';" />
- <h5>
+ /
+ <a href="http://sdrv.ms/14QHVoG" target="_blank">《遊玩記錄截圖》</a>
+ </h5>
+ </center>
+ <input type="button" id="create" class="btn btn-medium btn-primary" value="煮一碗好喝的海龜湯" onclick="javascript:location.href='/create';" />
+ <h5>
+ <div id="lobby_visitor"></div>
+ <center>
<span class="green">●</span>
燉煮 (進行)
<span class="red">●</span>
保溫 (暫停)
<span class="gray">●</span>
完食 (結束)
- </h5>
- </center>
+ </center>
+ </h5>
<table id="soup_list" class="table"></table>
</div>
<div id="main" class="span12">
- <table class="">
+ <table>
<tr>
<td>
<input type="button" class="btn" value="返回列表" onclick="javascript:location.href='/'">
</td>
</tr>
<tr>
+ <td><div id="soup_visitor"></div></td>
+ </tr>
+ <tr>
<td><input type="button" class="btn btn-info" id="show_inf_table" value="資訊面板" /></td>
</tr>
<tr class="inf_table">
- <th>本湯主題</th>
+ <td class="label_style">本湯主題</td>
</tr>
<tr class="inf_table">
<td id="title"></td>
</tr>
<tr class="inf_table">
- <th>本湯狀態</th>
+ <td class="label_style">本湯進度</td>
+ </tr>
+ <tr class="inf_table">
+ <td id="progress"></td>
+ </tr>
+ <tr class="inf_table">
+ <td class="label_style">本湯狀態</td>
</tr>
<tr class="inf_table">
<td id="online"></td>
</tr>
<tr class="inf_table">
- <th>主持人</th>
+ <td class="label_style">主持人</td>
</tr>
<tr class="inf_table">
<td id="who"></td>
</tr>
<tr class="inf_table">
- <th>前情提要</th>
+ <td class="label_style">前情提要</td>
</tr>
<tr class="inf_table">
<td id="previous"></td>
</tr>
<tr class="inf_table">
- <th>湯主提示</th>
+ <td class="label_style">湯主提示</td>
</tr>
<tr class="inf_table">
<td id="host_inf"></td>
</tr>
<tr class="inf_table">
- <th>玩家情報</th>
+ <td class="label_style">玩家情報</td>
</tr>
<tr class="inf_table">
<td id="guest_inf"></td>
</tr>
<tr class="inf_table">
- <th>湯底結局</th>
+ <td class="label_style">湯底結局</td>
</tr>
<tr class="inf_table">
<td id="answer"></td>
@@ -104,7 +118,7 @@
</div>
</div>
</div>
- <div id="highlight" style="position: absolute; background-color: pink; z-index: -1; display: none;">&nbsp;</div>
+ <div id="highlight" class="highlight">&nbsp;</div>
<div id="fb-root"></div>
</body>
<script src="/js/jquery-1.10.1.min.js"></script>
@@ -131,7 +145,7 @@
FB.Event.subscribe('auth.statusChange', function(response) {
if(response.status === "connected") {
FB.api("/me", function (res) {
- socket.emit("user_login", { username: res.name })
+ socket.emit("user_login", { username: res.name, where: where, soup_id: soup_id })
$("#username").text(res.name) //初始化姓名
localStorage["says_history"] = JSON.stringify([]) //留言歷史
console.log(res.name)
View
18 www/js/button.handler.js
@@ -2,22 +2,24 @@
$("#save").click(function() {
$(this).prop("disabled", "disabled")
- var soup_id = (id === undefined)?-1:id
+ var id = (soup_id === undefined)?-1:soup_id
var title = $("#title input").prop("value")
+ var online = $("input[name='trigger']:checked").val()
+ var progress = $("#progress input").prop("value")
var prev = $("#previous textarea").val()
var h_inf = $("#host_inf textarea").val()
var g_inf = $("#guest_inf textarea").val()
var ans = $("#answer textarea").val()
- var online = $("input[name='trigger']:checked").val()
var data = {
- id: soup_id,
+ id: id,
title: title,
+ online: online,
+ progress: progress,
previous: prev,
host_inf: h_inf,
guest_inf: g_inf,
- answer: ans,
- online: online
+ answer: ans
}
// console.log(data)
console.log("Save soup data.")
@@ -26,7 +28,7 @@ $("#save").click(function() {
data["hostman"] = res.name
socket.emit("sav_soup_data", { soup: data })
- if(soup_id == -1) {
+ if(id == -1) {
location.href = "/"
}
else {
@@ -57,7 +59,7 @@ var add_to_commu_table = function() {
var user = $("#username").text()
socket.emit("user_chat", {
- id: id,
+ id: soup_id,
user: user,
says: says
})
@@ -67,7 +69,7 @@ var add_to_commu_table = function() {
$("#says").prop("value", "")
- // console.log("["+id+"] "+user+" says '"+says+"'.")
+ // console.log("["+soup_id+"] "+user+" says '"+says+"'.")
}
};
View
78 www/js/library.js
@@ -25,50 +25,50 @@ function sortJsonArrayByProp(objArray, prop){
}
function strip_tags (input, allowed) {
- // http://kevin.vanzonneveld.net
- // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
- // + improved by: Luke Godfrey
- // + input by: Pul
- // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
- // + bugfixed by: Onno Marsman
- // + input by: Alex
- // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
- // + input by: Marc Palau
- // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
- // + input by: Brett Zamir (http://brett-zamir.me)
- // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
- // + bugfixed by: Eric Nagel
- // + input by: Bobby Drake
- // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
- // + bugfixed by: Tomasz Wesolowski
- // + input by: Evertjan Garretsen
- // + revised by: Rafał Kukawski (http://blog.kukawski.pl/)
- // * example 1: strip_tags('<p>Kevin</p> <br /><b>van</b> <i>Zonneveld</i>', '<i><b>');
- // * returns 1: 'Kevin <b>van</b> <i>Zonneveld</i>'
- // * example 2: strip_tags('<p>Kevin <img src="someimage.png" onmouseover="someFunction()">van <i>Zonneveld</i></p>', '<p>');
- // * returns 2: '<p>Kevin van Zonneveld</p>'
- // * example 3: strip_tags("<a href='http://kevin.vanzonneveld.net'>Kevin van Zonneveld</a>", "<a>");
- // * returns 3: '<a href='http://kevin.vanzonneveld.net'>Kevin van Zonneveld</a>'
- // * example 4: strip_tags('1 < 5 5 > 1');
- // * returns 4: '1 < 5 5 > 1'
- // * example 5: strip_tags('1 <br/> 1');
- // * returns 5: '1 1'
- // * example 6: strip_tags('1 <br/> 1', '<br>');
- // * returns 6: '1 1'
- // * example 7: strip_tags('1 <br/> 1', '<br><br/>');
- // * returns 7: '1 <br/> 1'
- allowed = (((allowed || "") + "").toLowerCase().match(/<[a-z][a-z0-9]*>/g) || []).join(''); // making sure the allowed arg is a string containing only tags in lowercase (<a><b><c>)
- var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi,
- commentsAndPhpTags = /<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi;
- return input.replace(commentsAndPhpTags, '').replace(tags, function ($0, $1) {
- return allowed.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : '';
- });
+ // http://kevin.vanzonneveld.net
+ // + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+ // + improved by: Luke Godfrey
+ // + input by: Pul
+ // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+ // + bugfixed by: Onno Marsman
+ // + input by: Alex
+ // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+ // + input by: Marc Palau
+ // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+ // + input by: Brett Zamir (http://brett-zamir.me)
+ // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+ // + bugfixed by: Eric Nagel
+ // + input by: Bobby Drake
+ // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+ // + bugfixed by: Tomasz Wesolowski
+ // + input by: Evertjan Garretsen
+ // + revised by: Rafał Kukawski (http://blog.kukawski.pl/)
+ // * example 1: strip_tags('<p>Kevin</p> <br /><b>van</b> <i>Zonneveld</i>', '<i><b>');
+ // * returns 1: 'Kevin <b>van</b> <i>Zonneveld</i>'
+ // * example 2: strip_tags('<p>Kevin <img src="someimage.png" onmouseover="someFunction()">van <i>Zonneveld</i></p>', '<p>');
+ // * returns 2: '<p>Kevin van Zonneveld</p>'
+ // * example 3: strip_tags("<a href='http://kevin.vanzonneveld.net'>Kevin van Zonneveld</a>", "<a>");
+ // * returns 3: '<a href='http://kevin.vanzonneveld.net'>Kevin van Zonneveld</a>'
+ // * example 4: strip_tags('1 < 5 5 > 1');
+ // * returns 4: '1 < 5 5 > 1'
+ // * example 5: strip_tags('1 <br/> 1');
+ // * returns 5: '1 1'
+ // * example 6: strip_tags('1 <br/> 1', '<br>');
+ // * returns 6: '1 1'
+ // * example 7: strip_tags('1 <br/> 1', '<br><br/>');
+ // * returns 7: '1 <br/> 1'
+ allowed = (((allowed || "") + "").toLowerCase().match(/<[a-z][a-z0-9]*>/g) || []).join(''); // making sure the allowed arg is a string containing only tags in lowercase (<a><b><c>)
+ var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi,
+ commentsAndPhpTags = /<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi;
+ return input.replace(commentsAndPhpTags, '').replace(tags, function ($0, $1) {
+ return allowed.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : '';
+ });
}
//濾出圖片與連結
var content_parser = function(str) {
str = str.replace(/:(\d{1,})/, "<a href='#$1' class='anchor'>:$1</a>")
- str = str.replace(/\[([^\]]*)\]/ig, "<span style='background-color: #D2DFF6; padding: 2px; border:#bdc7d8 1px solid;'>$1</span>")
+ str = str.replace(/\[([^\]]*)\]/ig, "<span class='tag_name'>$1</span>")
if(str.match(/(jpg|png|gif|jpeg|bmp)/) === null)
return str.replace(/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig,"<a href='$1' target='_blank'>$1</a>");
else
View
42 www/js/socket.handler.js
@@ -1,7 +1,7 @@
var hostname = "tonypai.twbbs.org:500"
var path = location.pathname.split("/")
-var where = path[1]
-var id = path[2]
+var where = (path[1]=="")?"lobby":path[1]
+var soup_id = (path[2]==undefined)?-1:path[2]
var socket = io.connect("http://" + hostname, {
"force new connection": true
@@ -12,15 +12,16 @@ socket.on("connect", function () {
})
socket.on("disconnect", function () {
- console.log("Lost connection!")
+ console.log("Lost connection!")
})
//將湯資料寫入表格
var write_soup_data = function(row, stage) { //0:煮湯 1:主持 2:玩家
if(stage == 0) {
$("#title").html("<input type='text' value='' />")
- $("#who").html("<input type='hidden' id='hostman' value='"+row.hostman+"' />"+row.hostman)
$("#online").html("<input type='radio' name='trigger' value='0' checked='true'> 燉煮 <input type='radio' name='trigger' value='1'> 保溫 <input type='radio' name='trigger' value='2'> 完食")
+ $("#progress").html("<input type='text' value='"+row.progress+"' style='width: 50px;' /> %")
+ $("#who").html("<input type='hidden' id='hostman' value='"+row.hostman+"' />"+row.hostman)
$("#previous").html("<textarea></textarea>")
$("#host_inf").html("<textarea></textarea>")
$("#guest_inf").html("<textarea></textarea>")
@@ -28,8 +29,9 @@ var write_soup_data = function(row, stage) { //0:煮湯 1:主持 2:玩家
}
else if(stage == 1) {
$("#title").html("<input type='text' value='"+row.title+"' />")
- $("#who").html("<input type='hidden' id='hostman' value='"+row.hostman+"' />"+row.hostman)
$("#online").html("<input type='radio' name='trigger' value='0'> 燉煮 <input type='radio' name='trigger' value='1'> 保溫 <input type='radio' name='trigger' value='2'> 完食")
+ $("#progress").html("<input type='text' value='"+row.progress+"' style='width: 50px;' /> %")
+ $("#who").html("<input type='hidden' id='hostman' value='"+row.hostman+"' />"+row.hostman)
$("input[name='trigger'][value='"+row.online+"']").prop("checked", "true")
$("#previous").html("<textarea>"+row.previous+"</textarea>")
$("#host_inf").html("<textarea>"+row.host_inf+"</textarea>")
@@ -38,8 +40,9 @@ var write_soup_data = function(row, stage) { //0:煮湯 1:主持 2:玩家
}
else if(stage == 2) {
$("#title").text(row.title)
- $("#who").text(row.hostman)
$("#online").text((row.online == "0")?"燉煮":(row.online == "1")?"保溫":(row.online == "2")?"完食":"Error")
+ $("#progress").html("<div class='progress'><div class='bar bar-warning' style='width: "+row.progress+"%;'></div></div>")
+ $("#who").text(row.hostman)
$("#previous").html(nl2br(row.previous))
$("#host_inf").html(nl2br(row.host_inf))
$("#guest_inf").html(nl2br(row.guest_inf))
@@ -54,7 +57,7 @@ socket.on("res_soup_list", function (data) {
sortJsonArrayByProp(data.list, "online")
//湯表標頭
- var html = "<tr><th>湯題</th><th>主持人</th></tr>"
+ var html = "<tr><td class='label_style'>湯題</td><td class='label_style'>主持人</td><td class='label_style'>進度</td></tr>"
$.each(data.list, function(index, row) {
//煲湯頁
@@ -71,7 +74,7 @@ socket.on("res_soup_list", function (data) {
//喝湯頁
else if(where.search("soup") != -1) {
- if(id == row.id) {
+ if(soup_id == row.id) {
FB.api("/me", function (res) {
//主持人
@@ -86,9 +89,10 @@ socket.on("res_soup_list", function (data) {
socket.emit("req_soup_data", { id: row.id })
}, 1000)
}
- //定時請求聊天紀錄
+ //定時請求聊天紀錄與在線使用者
setInterval(function() {
socket.emit("req_chat_history", { id: row.id })
+ socket.emit("visitor", { where: where, soup_id: soup_id })
}, 1000)
})
@@ -105,15 +109,16 @@ socket.on("res_soup_list", function (data) {
else if(row.online == "1")online = "red"
else if(row.online == "2")online = "gray"
- html += "<tr><td class='soup'><a href='/soup/"+row.id+"' style='color: "+online+"'>"+row.title+"</a></td><td class='hostman'>"+row.hostman+"</td></tr>"
+ html += "<tr><td class='soup'><a href='/soup/"+row.id+"' style='color: "+online+"'>"+row.title+"</a></td><td class='hostman'>"+row.hostman+"</td><td><div class='progress'><div class='bar bar-warning' style='width: "+row.progress+"%;'></div></div></td></tr>"
if(index == data.list.length - 1) {
//寫入湯表
$("#soup_list").html(html)
$("#list").show()
- //定時請求新湯表
+ //定時請求新湯表與在線使用者
setTimeout(function() {
socket.emit("req_soup_list", {})
+ socket.emit("visitor", { where: where, soup_id: soup_id })
}, 3000)
}
}
@@ -122,9 +127,9 @@ socket.on("res_soup_list", function (data) {
var intv_id //for highlight
//更新交談紀錄
-socket.on("res_chat_history", function(data) {
+socket.on("res_chat_history", function (data) {
var html = ""
- $.each(data.commu, function(key, val) {
+ $.each(data.commu, function (key, val) {
html = "<tr><td><span name='"+val.user+"' class='quick_name'>"+val.user+"</span>:"+val.says+"</td><td style='text-align: right; vertical-align: top;'><a name='"+key+"'>"+key+"</a></td></tr>" + html
if(key == data.commu.length - 1) {
//更新至表格
@@ -153,7 +158,7 @@ socket.on("res_chat_history", function(data) {
})
})
//更新湯資料
-socket.on("res_soup_data", function(data) {
+socket.on("res_soup_data", function (data) {
FB.api("/me", function (res) {
if(res.name == data.soup.hostman) {
write_soup_data(data.soup, 1)
@@ -162,4 +167,13 @@ socket.on("res_soup_data", function(data) {
write_soup_data(data.soup, 2)
}
})
+})
+//更新在線使用者
+socket.on("visitor", function (data) {
+ var visitor = data.visitor
+ var html = "<span class='label_style'>線上湯友:</span>"
+ $.each(visitor, function(key, val) {
+ html += "<span class='tag_name'>"+val+"</span> "
+ })
+ $("#"+where+"_visitor").html(html)
})
Please sign in to comment.
Something went wrong with that request. Please try again.