一个简易网页版“聊天室”,主要是ajax的运用。这是一个基于facebook开发的应用的一小块,后台用groovy on grails框架实现,前台页面用了一些FBJS,FBML,所以如果没接触过facebook应用的朋友可能有些陌生,不过逻辑是一致的,很简单,初学者可以参考一下。
view:
<g:render template="/fanStream/inc/header"/>
<script language="javascript">
var cacheListAll = [];
var cacheListFriends=[];
var startId = 0;
var startIdFriends = 0;
var flag1 = 1;
var flag2 = 1;
function clearText(){
$('add_comment_content').setValue('');
}
function displayDiv(isFriend){
if(isFriend=='0'){
$('fan_comments').setStyle('display', 'block');
$('fan_comments_friends').setStyle('display', 'none');
}else{
$('fan_comments').setStyle('display', 'none');
$('fan_comments_friends').setStyle('display', 'block');
}
}
function writeMsg(){
params = {};
params['pageId'] = "${pageId}";
params['facebookId'] = "${facebookId}";
params['message'] = $('add_comment_content').getValue();
var ajax = new Ajax();
ajax.responseType = Ajax.FBML;
ajax.requireLogin = true;
ajax.post("${grailsApplication.config.fanappz.web.base.url}/fanStream/writeChatMessage", params);
ajax.ondone = function(data){
var newDiv1 = document.createElement("div");
newDiv1.setInnerFBML(data);
$('fan_comments_friends').insertBefore(newDiv1,$('fan_comments_friends').getFirstChild());
var newDiv2 = document.createElement("div");
newDiv2.setInnerFBML(data);
$('fan_comments').insertBefore(newDiv2,$('fan_comments').getFirstChild());
$('add_comment_content').setValue('');
};
ajax.onerror = function(){
var dialog = new Dialog();
dialog.showMessage('Error', 'We are experiencing Facebook Platform issues, please try again. ');
}
}
function fetchChatMsg(){
params = {};
params['pageId'] = "${pageId}";
params['facebookId'] = "${facebookId}";
params['startId'] = startId;
var ajax = new Ajax();
ajax.responseType = Ajax.JSON;
ajax.requireLogin = true;
ajax.post("${grailsApplication.config.fanappz.web.base.url}/fanStream/fetchChatMessage", params);
ajax.ondone = function(data)
{
if(data.length>0){
for(var i=0;i<data.length;i++){
cacheListAll[cacheListAll.length]=data[i];
}
startId = data[data.length-1].id;
}
if(cacheListAll.length>0){readCacheList('0');};
};
setTimeout(function() {fetchChatMsg()},15000);
}
function fetchFriendsChatMsg(){
params = {};
params['pageId'] = "${pageId}";
params['facebookId'] = "${facebookId}";
params['startId'] = startIdFriends;
params['friendList'] = "${friendList}";
var ajax = new Ajax();
ajax.responseType = Ajax.JSON;
ajax.requireLogin = true;
ajax.post("${grailsApplication.config.fanappz.web.base.url}/fanStream/fetchFriendsChatMessage", params);
ajax.ondone = function(data)
{
if(data.length>0){
for(var i=0;i<data.length;i++){
cacheListFriends[cacheListFriends.length]=data[i];
}
startIdFriends = data[data.length-1].id;
}
if(cacheListFriends.length>0){readCacheList('1');};
};
setTimeout(function() {fetchFriendsChatMsg()},15000);
}
function displayMsg(pageId,facebookId,message,date,isFriend){
params = {};
params['pageId'] = pageId;
params['facebookId'] = facebookId;
params['message'] = message;
params['date'] = date;
var ajax = new Ajax();
ajax.responseType = Ajax.FBML;
ajax.requireLogin = true;
ajax.post("${grailsApplication.config.fanappz.web.base.url}/fanStream/displayChatMessage", params);
ajax.ondone = function(data){
var newDiv = document.createElement("div");
newDiv.setInnerFBML(data);
if(isFriend=='1'){
$('fan_comments_friends').insertBefore(newDiv,$('fan_comments_friends').getFirstChild());
}else{
$('fan_comments').insertBefore(newDiv,$('fan_comments').getFirstChild());
}
};
}
function readCacheList(isFriend){
var cacheList;
var flag;
if(isFriend=='1'){
cacheList=cacheListFriends;
flag=flag2;
}else{
cacheList=cacheListAll;
flag=flag1;
}
if(cacheList.length>0){
if(flag ==1){
for(var i=0;i<cacheList.length;i++){
displayMsg("${pageId}",cacheList[i].facebookId,cacheList[i].message,cacheList[i].date.toString(),isFriend);
}
cacheList.splice(0,cacheList.length);
flag=0;
}else if(flag ==0){
var i=0;
displayMsg("${pageId}",cacheList[i].facebookId,cacheList[i].message,cacheList[i].date.toString(),isFriend);
cacheList.splice(i,1);
}
setTimeout(function(){readCacheList(isFriend);},1000);
}
}
fetchChatMsg();
fetchFriendsChatMsg();
</script>
<div class="fanStream_index">
<div class="top">
<div class="my_balance">
<div class="my_balance_icon">
<div class="balance_img"><img src="${grailsApplication.config.fanappz.facebook.assets.url}/images/balance_icon.png"/></div>
<div class="balance_title">My Balance</div>
</div>
<div class="my_balance_lifetime lifetime">
<div class="lifetime">Lifetime</div>
<div class="number" id="lifetime">100</div>
</div>
<div class="my_balance_lifetime">
<div class="lifetime">Current</div>
<div class="number" id="current">100</div>
</div>
<div class="my_balance_lifetime">
<div class="lifetime">Rank</div>
<div class="number" id="rank">100</div>
</div>
<div class="my_balance_button1"><a href="${grailsApplication.config.fanappz.facebook.canvas.page.url}/reward/?fb_page_id=" id="my_balance_button_a"><img src="${grailsApplication.config.fanappz.facebook.assets.url}/images/checkin_button.png"/></a></div>
<div class="my_balance_button0"><a href="${grailsApplication.config.fanappz.facebook.canvas.page.url}/reward/?fb_page_id=" id="my_balance_button_b"><img src="${grailsApplication.config.fanappz.facebook.assets.url}/images/myBalance_f.png"/></a></div>
<div class="my_balance_button"><a href="${grailsApplication.config.fanappz.facebook.canvas.page.url}/reward/?fb_page_id=" id="my_balance_button_c"><img src="${grailsApplication.config.fanappz.facebook.assets.url}/images/seeRewards_button.png"/></a></div>
</div>
</div>
<div class="middle">
<div class="left_icon">
<img src="${grailsApplication.config.fanappz.facebook.assets.url}/images/temp/quiz_content_line-img2.jpg"/>
</div>
<div class="right">
<div class="title">Modern Family</div>
<div class="nav">
<div class="list">Wall</div>
<div class="list">Info</div>
<div class="list active">Fan Stream</div>
</div>
</div>
</div>
<div class="description">
Don't miss Wednesday's episode at 9/8c: "Game Changer": The release of a new product Phil wants coincides with his birthday; Mitchell has a newfound desire to toughen up; Cameron gets involved in a neighbor's marital problems.
</div>
<div class="main">
<div class="left">
<div class="title">
<div class="name" id="name">Fan Stream</div>
<div class="everyone active" id="everyone" οnclick="chooseComments('everyone','space11','myFriend','name');displayDiv('0');" >Everyone</div>
<div class="myFriend" id="myFriend" οnclick="chooseComments('myFriend','name','everyone','space11');displayDiv('1');" >Just My Friends</div>
<div class="space11 active" id="space11"></div>
</div>
<div class="comments">
<div class="new_post">
<div class="profile"><img src="${grailsApplication.config.fanappz.facebook.assets.url}/images/temp/quiz_content_line-img2.jpg"/></div>
<div class="add_comment">
<div class="c_content">
<textarea id="add_comment_content" οnclick="clearText()";>Add a comment</textarea>
</div>
<div class="c_oper">
<div class="post" οnclick="save_quiz_comment();return false" id="message_everyone" οnclick="writeMsg();">Post</div>
<div class="check">
<input type="checkbox">
</div>
<div class="content">Post comment to my Facebook profile</div>
</div>
</div>
</div>
<div class="space5"></div>
<div class="fan_comments" id="fan_comments">
<div class="clear"></div>
</div>
<div style="display:none;" class="fan_comments" id="fan_comments_friends">
<div class="clear"></div>
</div>
</div>
</div>
</div>
</div>
<script language="javascript">
function chooseComments(bActive, b1Active, gActive, g1Active ) {
$(gActive).setClassName(gActive);
$(g1Active).setClassName(g1Active);
$(bActive).setClassName(bActive+" active");
$(b1Active).setClassName(b1Active+" active");
}
</script>
<g:render template="/inc/footer"/>
controller:
package com.webgiftr
class FanStreamController extends BaseController {
def beforeInterceptor = [action: this.&authInFrame, only: ['index']]
ChatService chatService
def index = {
def pageId = params.fb_page_id
//println jsonArray.length()
//println jsonArray.getJSONObject(0).getString('message')
render(view: 'index', model: [facebookId: userId, pageId: pageId, friendList:params.fb_sig_friends])
}
def fetchChatMessage = {
def startId = params.startId as Long
def pageId = params.pageId
def facebookId = params.facebookId
def msgList
msgList = chatService.fetchChatMessage(pageId, facebookId, startId)
render msgList
}
def fetchFriendsChatMessage = {
def startId = params.startId as Long
def pageId = params.pageId
def facebookId = params.facebookId
String[] friendList = [""]
if (params.friendList) {
friendList = params.friendList.split(",")
} else {
friendList = [""]
}
def msgList
msgList = chatService.getFriendsChatMessage(pageId, facebookId, startId, friendList)
render msgList
}
def writeChatMessage = {
def pageId = params.pageId
def facebookId = params.facebookId
def message = params.message
def date = new Date().toString()
chatService.writeChatMessage(pageId,facebookId,message)
render (template:"/fanStream/inc/commentsList",model:[pageId:pageId,facebookId:facebookId,message:message,date:date])
}
def displayChatMessage = {
def pageId = params.pageId
def facebookId = params.facebookId
def message = params.message
def date = params.date
render (template:"/fanStream/inc/commentsList",model:[pageId:pageId,facebookId:facebookId,message:message,date:date])
}
}
service:
package com.webgiftr
import org.json.JSONArray
import org.json.JSONObject
import net.spy.memcached.MemcachedClient
class ChatService {
boolean transactional = true
static MemcachedClient memCachedClient = null;
def init() {
if(!memCachedClient) {
memCachedClient = new MemcachedClient(new InetSocketAddress("127.0.0.1", 11211))
}
}
def writeChatMessage(String pageId, String facebookId, String message) {
init()
def pageChatMessageList = memCachedClient.get(pageId);
def replaceFlag = true
if(!pageChatMessageList) {
pageChatMessageList = []
pageChatMessageList << [id: 1L, facebookId: facebookId, message: message, date: new Date()]
replaceFlag = false
}
else {
def currentMessageSize = pageChatMessageList.size()
// writeChatMessage is invoked for every single message, so currentMessageSize's max value is 500 in theory.
// TODO: make the max list size configurable
if(currentMessageSize >= 500) {
pageChatMessageList.remove(0)
}
def id = pageChatMessageList[pageChatMessageList.size() - 1].id + 1
pageChatMessageList << [id: id, facebookId: facebookId, message: message, date: new Date()]
}
def ret
if (replaceFlag) {
ret = memCachedClient.replace(pageId, 0, pageChatMessageList)
}
else {
ret = memCachedClient.set(pageId, 0, pageChatMessageList)
}
return ret.get().booleanValue()
}
def fetchChatMessage(String pageId, String userFacebookId, Long startId) {
init()
def batchSize = 50
List pageChatMessageList = memCachedClient.get(pageId)
if(!pageChatMessageList) {
return new JSONArray()
}
def resultList = []
if(startId == 0) {
def lastIndex = pageChatMessageList.size() - 1
def startIndex = Math.max((lastIndex - batchSize + 1), 0)
resultList = pageChatMessageList.getAt(startIndex..lastIndex)
}
else {
resultList = pageChatMessageList.findAll {it.id > startId && it.facebookId != userFacebookId}
}
return makeChatMessageJson(resultList)
}
private makeChatMessageJson (chatMessageList) {
def jsonArray = new JSONArray()
chatMessageList.each {
def jsonObject = new JSONObject()
jsonObject.put('id', it.id)
jsonObject.put('facebookId', it.facebookId)
jsonObject.put('message', it.message)
jsonObject.put('date', it.date)
jsonArray.put(jsonObject)
}
return jsonArray
}
def getFriendsChatMessage(String pageId, String userFacebookId, Long startId, String[] friendsFacebookIdList) {
init()
List pageChatMessageList = memCachedClient.get(pageId)
if(!pageChatMessageList) {
return new JSONArray()
}
def batchSize = 50
def resultList = []
List friendsAllMessageList
if (startId == 0) {
friendsAllMessageList = pageChatMessageList.findAll { (friendsFacebookIdList as List).contains(it.facebookId) || it.facebookId == userFacebookId }.toList()
if (!friendsAllMessageList) {
return new JSONArray()
}
def lastIndex = friendsAllMessageList.size() - 1
def startIndex = Math.max((lastIndex - batchSize + 1), 0)
resultList = friendsAllMessageList.getAt(startIndex..lastIndex)
}
else {
friendsAllMessageList = pageChatMessageList.findAll { (friendsFacebookIdList as List).contains(it.facebookId) }.toList()
if (!friendsAllMessageList) {
return new JSONArray()
}
resultList = friendsAllMessageList.findAll {it.id > startId && it.facebookId != userFacebookId}
}
return makeChatMessageJson(resultList)
}
}