基于Ajax的即时聊天实现(客户端)

本文介绍了一种基于AJAX实现的即时聊天系统的客户端部分,包括消息发送与接收的实现方式,采用定时轮询的方式从服务器获取新消息,并通过JSON格式进行数据交换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

     腾讯的网页即时聊天出现了一段时日了,开始以为腾讯是使用flash xmlsocket来建立服务器“推”消息到客户端的,但是通过对客户端代码的分析,以及使用httpwatch监视,发现也是使用按刷新率来“拉”消息。为什么不使用flash做接口呢?参考了许多网上的例子,以及各方面的反应,估计有以下几点
个人观点,欢迎指证)。我不是flash程序员
  1. flash与浏览器JS脚本交互效率不高,经常出现无响应的假死状态.
  2. flash xmlsocket使用socket协议来通信,这需要服务器端socket监听程序来支持。
    flash的安全性要求连接的主机必须在同域或配置安全性许可文件(security.xml)?,种种实现起来还是较复杂的。我不是不推行这种方式,但是对于我们这些一直没有真正包含AS脚本编程经验的同志,实现起来有点难度。
什么是ajax?大家可以去百度或Google查询下怎么定义的。总结一下就几个关键词语: 异步回调 ,后台请求
现在网上到处都是ajax技术的文章。其实说的再多,反而让你觉得神秘莫测。
一,原理分析 
目前的即时聊天技术实现,使用按设定的时间来刷新获取服务器的新消息,通常使用反复 查询数据库来实现。但是这种效率和服务器资源消耗率都不是很理想。
  如果我们在服务器内存,设定某种消息标识机制。用来标识某个客户端是否有新消息,这比反复查询数据库的效率要高的多。但是消息格式是怎样的呢?我们一步一  步来分析和实现一下。和各位朋友来一同探讨。
  这是我目前的项目所包含的一个聊天模块:
 
  聊天窗口很简单,上面是内容显示区,下面是消息发送区。客户端使用javascript(jquery框架)来处理消息的发送和接收。
  如果构建这样的窗口只需要一些css布局方面的知识就足够了。我们只讲核心的实现方式
  提示:jquery框架封装了很多ajax相关的方法以及方便对DOM操作的一系列函数。
  客户端聊天代码: 
ContractedBlock.gif ExpandedBlockStart.gif chatplugin.js
  1var emotes=['微笑','撇嘴','','发呆','得意','流泪','害羞','','大哭','尴尬','发怒','调皮','呲牙','惊讶',
  2'难过','','冷汗','抓狂','','偷笑','可笑','傲慢','饥饿','','惊恐','流汗','憨笑','大兵',
  3'奋斗','咒骂','疑问','','','折磨','','敲打','再见','擦汗','扣鼻','鼓掌','糗大了','坏笑',
  4'左哼哼','右哼哼','哈欠','鄙视','委屈','快哭了','阴险','','可怜','菜刀','西瓜','脾酒','篮球','乒乓',
  5'咖啡','','','玫瑰','凋谢','示爱','爱心','蛋糕','闪电','炸弹','','足球','瓢虫','便便',
  6'月亮','太阳','礼物','拥抱','','','握手','抱拳','勾引','拳头','差劲','爱你','NO','OK'];
  7var __messageThread=null;
  8var __targetid=0;
  9var __lastMessageTime='';
 10var __constTime=5*1000;
 11var __closed=false;
 12var __loading=true;
 13ExpandedBlockStart.gifContractedBlock.gif$(document).ready(function(){
 14ExpandedSubBlockStart.gifContractedSubBlock.gif    $("#loading").bind("contextmenu",function(){return false;});
 15ExpandedSubBlockStart.gifContractedSubBlock.gif    $(window).load(function(){
 16        openeditor();
 17        __targetid=1;
 18        startchat();
 19    }
);
 20    $('#sendbutton').hover(
 21ExpandedSubBlockStart.gifContractedSubBlock.gif        function(){$(this).removeClass('normalsend').addClass('activesend')},
 22ExpandedSubBlockStart.gifContractedSubBlock.gif        function(){$(this).removeClass('activesend').addClass('normalsend')}
 23        )
 24ExpandedSubBlockStart.gifContractedSubBlock.gif    .click(function(){
 25        var mc=getsafehtml();
 26        mc=replaceunsafe(mc);
 27ExpandedSubBlockStart.gifContractedSubBlock.gif        if($.trim(mc)!=""){
 28ExpandedSubBlockStart.gifContractedSubBlock.gif            $(this).css({disabled:true});
 29            sendMessage(__targetid,mc);
 30        }

 31ExpandedSubBlockStart.gifContractedSubBlock.gif        else{
 32            showError('发送的信息不能为空');
 33            Editor.focus();
 34        }

 35    }
);
 36ExpandedSubBlockStart.gifContractedSubBlock.gif    $('#pagec').find('a').each(function(i){
 37ExpandedSubBlockStart.gifContractedSubBlock.gif        $(this).click(function(e){
 38            $(this).blur();
 39            var epageindex=parseInt($("#emote-layer").attr('class').replace(/[^\d]/gi,''));
 40            var npageindex=i==0?(epageindex-1):(epageindex+1);
 41ExpandedSubBlockStart.gifContractedSubBlock.gif            if(npageindex<1||npageindex>4){e.stopPropagation();return false;}
 42ExpandedSubBlockStart.gifContractedSubBlock.gif            $("#emote-layer").fadeOut(100,function(){
 43ExpandedSubBlockStart.gifContractedSubBlock.gif                $(this).fadeIn(100,function(){
 44                    $("#emote-layer").attr('class',"emote-p"+npageindex);
 45                }
)
 46            }
)
 47            
 48            $('#pagec > span').text(npageindex+" / 4");
 49            checkEmotepages(npageindex);
 50            e.stopPropagation();//防止上升到document.click
 51        }
);
 52    }
);
 53ExpandedSubBlockStart.gifContractedSubBlock.gif    $("#funclist").find("a").each(function(i){
 54ExpandedSubBlockStart.gifContractedSubBlock.gif        $(this).click(function(){
 55ExpandedSubBlockStart.gifContractedSubBlock.gif            if(i==0){//打开表情
 56ExpandedSubBlockStart.gifContractedSubBlock.gif                if($("#emp").is(':hidden')){
 57ExpandedSubBlockStart.gifContractedSubBlock.gif                    $(document).bind('click',function(event){
 58ExpandedSubBlockStart.gifContractedSubBlock.gif                        if($(event.target).attr('class')!='a1'){
 59                            $("#emp").hide();
 60                        }

 61                    }
);
 62                    $("#emp").show();
 63                }

 64            }

 65ExpandedSubBlockStart.gifContractedSubBlock.gif            else if(i==1){//清除屏幕
 66                    $("#chatwin").empty();
 67            }

 68        }
);
 69    }
);
 70ExpandedSubBlockStart.gifContractedSubBlock.gif    $("#emp").click(function(e){
 71        e.stopPropagation();
 72    }
);
 73ExpandedSubBlockStart.gifContractedSubBlock.gif    $("a.closeby").click(function(){
 74ExpandedSubBlockStart.gifContractedSubBlock.gif        try{top.existchat();}catch(e){}
 75    }
)
 76ExpandedSubBlockStart.gifContractedSubBlock.gif       .focus(function(){$(this).blur()});
 77    $("#emote-layer")
 78ExpandedSubBlockStart.gifContractedSubBlock.gif        .hover(function(){
 79                $(this).find('.maskbox').show();
 80ExpandedSubBlockStart.gifContractedSubBlock.gif        }
,function(){
 81            $(this).find('.maskbox').hide();$("#epageinfo").text("");
 82            $('#previewbox').hide();
 83        }
)
 84ExpandedSubBlockStart.gifContractedSubBlock.gif        .mousemove(function(event){
 85            var lfpos=event.pageX-$(this).offset().left;
 86            var tppos=event.pageY-$(this).offset().top;
 87            var lindex=lfpos/30+"";
 88            var tindex=tppos/30+"";
 89            var row=tindex.replace(/\.\d+/gi,'');
 90            var coll= lindex.replace(/\.\d+/gi,'');
 91            var r_c=row+","+coll;
 92ExpandedSubBlockStart.gifContractedSubBlock.gif            if($(this).find('.maskbox').data('r_c')){
 93                if($(this).find('.maskbox').data('r_c').r==r_c) 
 94                return false;
 95            }

 96            //-----
 97            var pageindex=parseInt($.trim($('#pagec > span').text().split('/')[0]));
 98            var pcurPostion=$(this).find('#previewbox').attr('class');
 99            var startIndex=pageindex<3?((pageindex-1)*7+parseInt(row)*14):42+(pageindex-3)*7+parseInt(row)*14;
100            var imageindex=startIndex+parseInt(coll)+1;
101            var imagedesc="/"+emotes[imageindex-1];
102            var imagesrc = "images/emote/"+imageindex+".gif";
103            $("#epageinfo").text(imagedesc);
104            $(this).attr('title',imagedesc);
105ExpandedSubBlockStart.gifContractedSubBlock.gif            $('#previewbox').find('img').attr({src:imagesrc}).data('em',{desc:imagedesc,index:imageindex});
106ExpandedSubBlockStart.gifContractedSubBlock.gif            if($('#previewbox').is(":hidden")){$('#previewbox').show()}
107            ////============
108            var prepostion=coll<4?'inleft':'inright';
109ExpandedSubBlockStart.gifContractedSubBlock.gif            if(prepostion==pcurPostion){//发现遮盖
110                $('#previewbox').removeClass(prepostion).addClass(prepostion=='inleft'?'inright':'inleft');
111            }

112            var top_ = row*30-tindex+1;
113            var left_ = coll*30-(lindex-1);
114ExpandedSubBlockStart.gifContractedSubBlock.gif            $(this).find('.maskbox').css({top:top_,left:left_}).data('r_c',r_c);
115        }
)
116ExpandedSubBlockStart.gifContractedSubBlock.gif        .click(function(e){
117            var imgubb = $("#previewbox").find("img").data('em').desc;
118            insert("<img class=gif border='0' src='"+ $("#previewbox").find("img").attr('src'+ "'/>");
119            $("#emp").hide();
120            $(document).unbind('click');
121            e.stopPropagation();
122        }
);
123}
);
124ExpandedBlockStart.gifContractedBlock.giffunction changecaption(m){
125    $("#chattitle").text(m);
126}

127ExpandedBlockStart.gifContractedBlock.giffunction startchat(){
128    __closed=false;
129    $("#lstxt").text("正在加载聊天信息.");
130    scrolltoend();
131    getMessage(User.id,__targetid,__lastMessageTime);
132}

133ExpandedBlockStart.gifContractedBlock.giffunction flashMessage(){
134    var maxt=16;
135    var flag=$(".ctr2").find(".lo2").data("flag");
136    if(!flag) flag =0;
137    if(flag%2==0)
138        $(".ctr2").find(".lo2").addClass("noico");
139    else 
140        $(".ctr2").find(".lo2").removeClass("noico");
141    flag++;
142    $(".ctr2").find(".lo2").data("flag",flag);
143ExpandedSubBlockStart.gifContractedSubBlock.gif    if(flag<maxt){
144        setTimeout(flashMessage,400);
145    }

146ExpandedSubBlockStart.gifContractedSubBlock.gif    else{
147        $(".ctr2").find(".lo2").removeClass("noico");
148        $(".ctr2").find(".lo2").data("flag",0);
149    }

150}

151ExpandedBlockStart.gifContractedBlock.giffunction checkEmotepages(epageindex){
152ExpandedSubBlockStart.gifContractedSubBlock.gif    $('#pagec').find('a:eq(0)').attr({disabled:epageindex==1});
153ExpandedSubBlockStart.gifContractedSubBlock.gif    $('#pagec').find('a:eq(1)').attr({disabled:epageindex==4});
154}

155ExpandedBlockStart.gifContractedBlock.giffunction ubbTag(txa, markup)
156    txa.focus(); 
157    var strEnd=markup.replace(/\[/ig,'[/'); 
158ExpandedSubBlockStart.gifContractedSubBlock.gif    if (strEnd.indexOf('=')>-1)
159        strEnd=strEnd.replace(/(.*?)\=.*?\]/,'$1]'); 
160    }
 
161ExpandedSubBlockStart.gifContractedSubBlock.gif    if(document.selection&&document.selection.type== "Text")
162    // IE, Opera 
163            var oStr=document.selection.createRange(); 
164            oStr.text=markup+oStr.text+strEnd; 
165ExpandedSubBlockStart.gifContractedSubBlock.gif    }
 else if(window.getSelection&&txa.selectionStart>-1
166    // Netscape 
167        var st=txa.selectionStart; 
168        var ed=txa.selectionEnd; 
169           txa.value=txa.value.substring(0,st)+markup+ 
170           txa.value.substring(st,ed)+strEnd+ 
171           txa.value.slice(ed); 
172ExpandedSubBlockStart.gifContractedSubBlock.gif    }
 else 
173        txa.value+=markup+strEnd; 
174    }
 
175}
 
176ExpandedBlockStart.gifContractedBlock.giffunction sendMessage(targetid,content){
177    var eco=encode64(content);
178ExpandedSubBlockStart.gifContractedSubBlock.gif    Async('chat/send/',{
179         target:targetid,
180         uid:User.id,
181         m:eco
182ExpandedSubBlockStart.gifContractedSubBlock.gif        }
,function(r){
183            var t=date2str(new Date());
184ExpandedSubBlockStart.gifContractedSubBlock.gif            if(!r){showError('与服务器通讯发生错误。',t);return false;}
185ExpandedSubBlockStart.gifContractedSubBlock.gif            if(!r.st){showError(r.err,t);return false;}
186            addMessage(User.nick,User.id,content,t,r.dbid,true);
187            clearhtml();
188ExpandedSubBlockStart.gifContractedSubBlock.gif            $("#sendbutton").css({disabled:false});
189        }
,'json','POST');
190}

191ExpandedBlockStart.gifContractedBlock.giffunction getMessage(userid,targetid){
192    //changecaption(__lastMessageTime);
193ExpandedSubBlockStart.gifContractedSubBlock.gif    if(__closed){
194        $("#loading").show();
195         return false;
196     }

197ExpandedSubBlockStart.gifContractedSubBlock.gif    Async('chat/get/',{
198        uid:userid,
199        target:targetid,
200        last:(typeof __lastMessageTime=='undefined')?'':__lastMessageTime
201ExpandedSubBlockStart.gifContractedSubBlock.gif        }
,function(r){
202            var t=date2str(new Date());
203ExpandedSubBlockStart.gifContractedSubBlock.gif            if(!r){showError('网络错误或数据传输失败。',t);return false;}
204ExpandedSubBlockStart.gifContractedSubBlock.gif            if(!r.st){showError(r.err,t);return false;}
205            var mtime='';
206ExpandedSubBlockStart.gifContractedSubBlock.gif            if(r.datas.length>0){
207                //按messageid顺序排序
208ExpandedSubBlockStart.gifContractedSubBlock.gif                r.datas=r.datas.sort(function(a,b){
209                    return a.mid-b.mid;
210                }
);
211ExpandedSubBlockStart.gifContractedSubBlock.gif                $.each(r.datas,function(i,n){
212                    var b=true;
213ExpandedSubBlockStart.gifContractedSubBlock.gif                    if(__lastMessageTime==''){
214ExpandedSubBlockStart.gifContractedSubBlock.gif                        if($("#msg"+n.mid).length!=0){
215                            b=false;
216                        }

217                    }

218                    if(b)addMessage(n.uname,n.uid,decode64(n.m),n.t,n.mid,n.uid==User.id);
219                    mtime=n.t;
220                }
);
221                if(mtime!='')
222                 __lastMessageTime=mtime;
223                flashMessage();
224            }

225            //清除LOADING
226ExpandedSubBlockStart.gifContractedSubBlock.gif            if(!$("#loading").is(":hidden")){ __loading=false;$("#loading").hide();}
227ExpandedSubBlockStart.gifContractedSubBlock.gif            setTimeout(function(){getMessage(User.id,__targetid);},__constTime)
228        }
,'json','GET');
229}

230ExpandedBlockStart.gifContractedBlock.giffunction scrolltoend(){
231    $("#chatwin").get(0).scrollTop=$("#chatwin").get(0).scrollHeight;
232}

233var errtimer=null;
234ExpandedBlockStart.gifContractedBlock.giffunction showError(errmess,t){
235    //$("#chatwin").find(".merr:last").fadeOut(100);
236    if(!t) t="";
237ExpandedSubBlockStart.gifContractedSubBlock.gif    if(__loading){
238        $("#lstxt").html("<font color=red>"+errmess+"</font>");
239    }

240ExpandedSubBlockStart.gifContractedSubBlock.gif    if($("#chatwin > .msgitem:last").find('.err').length>0){//错误消息已经存在
241        $("#chatwin > .msgitem:last").find('.err > span').html(errmess);
242        $("#chatwin > .msgitem:last").find('.err > font').html(t);
243    }

244ExpandedSubBlockStart.gifContractedSubBlock.gif    else{
245        $("#chatwin").find(".merr").remove();
246        $("#chatwin").append(String.format("<div class=\"msgitem merr\"><div class='err'><b disabled='disabled'>[{2}]</b> <span>{0}</span> <font>{1}</font></div></div>",errmess,t,"提示"));
247    }

248    $("#chatwin").find(".merr:last").fadeIn(100);
249    scrolltoend();
250    if(errtimer) clearTimeout(errtimer);
251ExpandedSubBlockStart.gifContractedSubBlock.gif    errtimer = setTimeout(function(){
252        $("#chatwin").find(".merr:last").fadeOut(200);
253        errtimer=null;
254    }
,3000)
255}

256ExpandedBlockStart.gifContractedBlock.giffunction addMessage(username,userid,msghtml,msgtime,dbid,bMyMessage){
257    var sb = new StringBuilder();
258    sb.append("<div class=\"msgitem\" id='msg{4}'>");
259    sb.append("<h2{3}>{0} {1}</h2>");
260    sb.append("<div class=\"p\">");
261    sb.append("{2}");
262    sb.append("</div>");
263    sb.append("</div>");
264    var c=String.format(sb.toString(),username,msgtime,msghtml,bMyMessage?" class='me'":"",dbid);
265    $("#chatwin").append(c);
266    scrolltoend();
267    sb=null;
268}


 二。消息结构

上面的客户端代码,重点在于包装消息请求,以及对服务器端响应的JSON数据进行处理。

Async函数是封装的AJAX请求函数

Async(请求地址,请求参数json结构,响应函数,内容响应格式,发送方式)

如果你对jquery有了解,其实这和JQUERYajax发送请求方式非常相似,这里进一步封装只是稍微方便一些。

1.发送消息(请求):

 1  function  sendMessage(targetid,content){
 2 
 3       var  eco = encode64(content);
 4 
 5      Async( ' chat/send/ ' ,{
 6 
 7              target:targetid,
 8 
 9              uid:User.id,
10 
11              m:eco
12 
13             }, function (r){
14 
15                     var  t = date2str( new  Date());
16 
17                     if ( ! r){showError( ' 与服务器通讯发生错误。 ' ,t); return   false ;}
18 
19                     if ( ! r.st){showError(r.err,t); return   false ;}
20 
21                    addMessage(User.nick,User.id,content,t,r.dbid, true ); // 添加消息到聊天窗口
22 
23                    clearhtml(); // 清空发送消息框的内容
24 
25                    $( " #sendbutton " ).css({disabled: false });
26 
27             }, ' json ' , ' POST ' );
28 
29  }

解释:

实际请求url /chat/send.aspx         上面的url使用urlrewrite

sendMessage(targetid,content) 函数

targetid:目标ID(可以是用户,聊天室ID) 在服务器端代码里会解释这个ID

uid:用户ID

m:使用BASE64客户端加密的消息内容

function(r){//json响应回调

       ….//这个AJAX请求发送后服务器的响应处理

}

服务器JSON消息响应:

{

st:true,

dbid:123,

err:”…..”

}

解释:

st:消息发送是否成功(true/false),dbid:消息所存储在数据库中的IDerr: 如果出现错误,服务器返回的错误信息。如果成功则留空字符串。

 

2.服务器消息的获取:

对于消息的获取,我们使用setTimeout函数启动一个“线程”隔5s去服务器端请求一次。然后处理服务器响应的内容。这里的内容可能是有新消息,或者没有任何新内容。ExpandedBlockStart.gif

 1  function  getMessage(userid,targetid){
 2       // changecaption(__lastMessageTime);
 3       if (__closed){
 4          $( " #loading " ).show();
 5            return   false ;
 6       }
 7      Async( ' chat/get/ ' ,{
 8          uid:userid,
 9          target:targetid,
10          last:( typeof  __lastMessageTime == ' undefined ' ) ? '' :__lastMessageTime
11          }, function (r){
12               var  t = date2str( new  Date());
13               if ( ! r){showError( ' 网络错误或数据传输失败。 ' ,t); return   false ;}
14               if ( ! r.st){showError(r.err,t); return   false ;}
15               var  mtime = '' ;
16               if (r.datas.length > 0 ){
17                   // 按messageid顺序排序
18                  r.datas = r.datas.sort( function (a,b){
19                       return  a.mid - b.mid;
20                  });
21                  $.each(r.datas, function (i,n){
22                       var  b = true ;
23                       if (__lastMessageTime == '' ){
24                           if ($( " #msg " + n.mid).length != 0 ){
25                              b = false ;
26                          }
27                      }
28                       if (b)addMessage(n.uname,n.uid,decode64(n.m),n.t,n.mid,n.uid == User.id);
29                      mtime = n.t;
30                  });
31                   if (mtime != '' )
32                   __lastMessageTime = mtime;
33                  flashMessage();
34              }
35               // 清除LOADING
36               if ( ! $( " #loading " ).is( " :hidden " )){ __loading = false ;$( " #loading " ).hide();}
37              setTimeout( function (){getMessage(User.id,__targetid);},__constTime)
38          }, ' json ' , ' GET ' );
39  }

上面的getMessage(userid,targetid)函数 参数userid:用户IDtargetid:目标ID

请求服务器地址:chat/get.aspx

发送到服务器端的参数:

uid:userid, //用户id

target:targetid,//目标ID

last:(typeof __lastMessageTime=='undefined')?'':__lastMessageTime //最后消息接收时间(全局变量)如果第一次请求消息,则为空。

请求发送后服务器返回JSON消息格式数据

 

{

       st: true,

datas:[

{…},

{…},

{…}

]

}

服务器只返回非自身发送的消息,换句话说就是别人给我发送的消息,才返回消息数据。

同样:st表示消息的失败标志位:true表成功,false表失败

Datas:是一个数组。包含一条条的消息对象,里面的元素同样是json对象

{…}的最终结构:

 {

 mid:消息ID,

 uid:发送者用户id,

 uname:发送者用户名,

 tid:目标ID,

 m:’消息内容(使用base64加密,须解码)’,

 t:’消息发送时间

}

一个标准的消息返回示例:

{

 st:true.

datas:[

{

mid:1,uid:2,uname=’用户A’,tid:1,m:”--encode---”,t:’2009-8-7 21:38:20’

},

{

mid:2,uid:3,uname=’用户B’,tid:1,m:”---encode--”,t:’2009-8-7 21:38:22’

},

{

mid:3,uid:2,uname=’用户A’,tid:1,m:”--encode---”,t:’2009-8-7 21:38:33’

}

]

}

对服务器响应的消息,除了排序并添加到聊天内容框,还有一个比较重要的变量t变量

对于成功有效的消息,这个t时间变量表明了我最后一条接收的消息时间是t,然后将它存储在__lastMessageTime=t;全局变量中,在下次获取新消息的时候会加上这个变量作为请求参数,服务器端判断这个请求,检查内存application变量或asp.netHttpApplication静态类变量(也叫服务器全局变量)中有没有大于这个时间的消息,并且发送者不是我自己。

服务器端处理代码将在下一节提供。

在消息处理后继续隔__constTime所设定的时间,继续请求服务器端获取新内容,达到一个循环。

setTimeout(function(){getMessage(User.id,__targetid);},__constTime)

如果获取消息失败会自动停止再次请求(这里可以修改成,失败继续模式)

 

当然,安全性方面我们需要过滤客户端的一些非法代码或攻击脚本,提高服务器安全性。这里可以使用正则表达式进行过滤。具体代码在稍候提供的压缩包中。

 

客户端的消息发送格式和服务器的响应格式大体就这样子,下一篇日志中,我会给大家提供服务器端的实现,以及数据库方面的内容。

《基于AJAX的即时聊天(2)-服务器端》


  1var emotes=['微笑','撇嘴','','发呆','得意','流泪','害羞','','大哭','尴尬','发怒','调皮','呲牙','惊讶',
  2'难过','','冷汗','抓狂','','偷笑','可笑','傲慢','饥饿','','惊恐','流汗','憨笑','大兵',
  3'奋斗','咒骂','疑问','','','折磨','','敲打','再见','擦汗','扣鼻','鼓掌','糗大了','坏笑',
  4'左哼哼','右哼哼','哈欠','鄙视','委屈','快哭了','阴险','','可怜','菜刀','西瓜','脾酒','篮球','乒乓',
  5'咖啡','','','玫瑰','凋谢','示爱','爱心','蛋糕','闪电','炸弹','','足球','瓢虫','便便',
  6'月亮','太阳','礼物','拥抱','','','握手','抱拳','勾引','拳头','差劲','爱你','NO','OK'];
  7var __messageThread=null;
  8var __targetid=0;
  9var __lastMessageTime='';
 10var __constTime=5*1000;
 11var __closed=false;
 12var __loading=true;
 13ExpandedBlockStart.gifContractedBlock.gif$(document).ready(function(){
 14ExpandedSubBlockStart.gifContractedSubBlock.gif    $("#loading").bind("contextmenu",function(){return false;});
 15ExpandedSubBlockStart.gifContractedSubBlock.gif    $(window).load(function(){
 16        openeditor();
 17        __targetid=1;
 18        startchat();
 19    });
 20    $('#sendbutton').hover(
 21ExpandedSubBlockStart.gifContractedSubBlock.gif        function(){$(this).removeClass('normalsend').addClass('activesend')},
 22ExpandedSubBlockStart.gifContractedSubBlock.gif        function(){$(this).removeClass('activesend').addClass('normalsend')}
 23        )
 24ExpandedSubBlockStart.gifContractedSubBlock.gif    .click(function(){
 25        var mc=getsafehtml();
 26        mc=replaceunsafe(mc);
 27ExpandedSubBlockStart.gifContractedSubBlock.gif        if($.trim(mc)!=""){
 28ExpandedSubBlockStart.gifContractedSubBlock.gif            $(this).css({disabled:true});
 29            sendMessage(__targetid,mc);
 30        }
 31ExpandedSubBlockStart.gifContractedSubBlock.gif        else{
 32            showError('发送的信息不能为空');
 33            Editor.focus();
 34        }
 35    });
 36ExpandedSubBlockStart.gifContractedSubBlock.gif    $('#pagec').find('a').each(function(i){
 37ExpandedSubBlockStart.gifContractedSubBlock.gif        $(this).click(function(e){
 38            $(this).blur();
 39            var epageindex=parseInt($("#emote-layer").attr('class').replace(/[^\d]/gi,''));
 40            var npageindex=i==0?(epageindex-1):(epageindex+1);
 41ExpandedSubBlockStart.gifContractedSubBlock.gif            if(npageindex<1||npageindex>4){e.stopPropagation();return false;}
 42ExpandedSubBlockStart.gifContractedSubBlock.gif            $("#emote-layer").fadeOut(100,function(){
 43ExpandedSubBlockStart.gifContractedSubBlock.gif                $(this).fadeIn(100,function(){
 44                    $("#emote-layer").attr('class',"emote-p"+npageindex);
 45                })
 46            })
 47            
 48            $('#pagec > span').text(npageindex+" / 4");
 49            checkEmotepages(npageindex);
 50            e.stopPropagation();//防止上升到document.click
 51        });
 52    });
 53ExpandedSubBlockStart.gifContractedSubBlock.gif    $("#funclist").find("a").each(function(i){
 54ExpandedSubBlockStart.gifContractedSubBlock.gif        $(this).click(function(){
 55ExpandedSubBlockStart.gifContractedSubBlock.gif            if(i==0){//打开表情
 56ExpandedSubBlockStart.gifContractedSubBlock.gif                if($("#emp").is(':hidden')){
 57ExpandedSubBlockStart.gifContractedSubBlock.gif                    $(document).bind('click',function(event){
 58ExpandedSubBlockStart.gifContractedSubBlock.gif                        if($(event.target).attr('class')!='a1'){
 59                            $("#emp").hide();
 60                        }
 61                    });
 62                    $("#emp").show();
 63                }
 64            }
 65ExpandedSubBlockStart.gifContractedSubBlock.gif            else if(i==1){//清除屏幕
 66                    $("#chatwin").empty();
 67            }
 68        });
 69    });
 70ExpandedSubBlockStart.gifContractedSubBlock.gif    $("#emp").click(function(e){
 71        e.stopPropagation();
 72    });
 73ExpandedSubBlockStart.gifContractedSubBlock.gif    $("a.closeby").click(function(){
 74ExpandedSubBlockStart.gifContractedSubBlock.gif        try{top.existchat();}catch(e){}
 75    })
 76ExpandedSubBlockStart.gifContractedSubBlock.gif       .focus(function(){$(this).blur()});
 77    $("#emote-layer")
 78ExpandedSubBlockStart.gifContractedSubBlock.gif        .hover(function(){
 79                $(this).find('.maskbox').show();
 80ExpandedSubBlockStart.gifContractedSubBlock.gif        },function(){
 81            $(this).find('.maskbox').hide();$("#epageinfo").text("");
 82            $('#previewbox').hide();
 83        })
 84ExpandedSubBlockStart.gifContractedSubBlock.gif        .mousemove(function(event){
 85            var lfpos=event.pageX-$(this).offset().left;
 86            var tppos=event.pageY-$(this).offset().top;
 87            var lindex=lfpos/30+"";
 88            var tindex=tppos/30+"";
 89            var row=tindex.replace(/\.\d+/gi,'');
 90            var coll= lindex.replace(/\.\d+/gi,'');
 91            var r_c=row+","+coll;
 92ExpandedSubBlockStart.gifContractedSubBlock.gif            if($(this).find('.maskbox').data('r_c')){
 93                if($(this).find('.maskbox').data('r_c').r==r_c) 
 94                return false;
 95            }
 96            //-----
 97            var pageindex=parseInt($.trim($('#pagec > span').text().split('/')[0]));
 98            var pcurPostion=$(this).find('#previewbox').attr('class');
 99            var startIndex=pageindex<3?((pageindex-1)*7+parseInt(row)*14):42+(pageindex-3)*7+parseInt(row)*14;
100            var imageindex=startIndex+parseInt(coll)+1;
101            var imagedesc="/"+emotes[imageindex-1];
102            var imagesrc = "images/emote/"+imageindex+".gif";
103            $("#epageinfo").text(imagedesc);
104            $(this).attr('title',imagedesc);
105ExpandedSubBlockStart.gifContractedSubBlock.gif            $('#previewbox').find('img').attr({src:imagesrc}).data('em',{desc:imagedesc,index:imageindex});
106ExpandedSubBlockStart.gifContractedSubBlock.gif            if($('#previewbox').is(":hidden")){$('#previewbox').show()}
107            ////============
108            var prepostion=coll<4?'inleft':'inright';
109ExpandedSubBlockStart.gifContractedSubBlock.gif            if(prepostion==pcurPostion){//发现遮盖
110                $('#previewbox').removeClass(prepostion).addClass(prepostion=='inleft'?'inright':'inleft');
111            }
112            var top_ = row*30-tindex+1;
113            var left_ = coll*30-(lindex-1);
114ExpandedSubBlockStart.gifContractedSubBlock.gif            $(this).find('.maskbox').css({top:top_,left:left_}).data('r_c',r_c);
115        })
116ExpandedSubBlockStart.gifContractedSubBlock.gif        .click(function(e){
117            var imgubb = $("#previewbox").find("img").data('em').desc;
118            insert("<img class=gif border='0' src='"+ $("#previewbox").find("img").attr('src'+ "'/>");
119            $("#emp").hide();
120            $(document).unbind('click');
121            e.stopPropagation();
122        });
123});
124ExpandedBlockStart.gifContractedBlock.giffunction changecaption(m){
125    $("#chattitle").text(m);
126}
127ExpandedBlockStart.gifContractedBlock.giffunction startchat(){
128    __closed=false;
129    $("#lstxt").text("正在加载聊天信息.");
130    scrolltoend();
131    getMessage(User.id,__targetid,__lastMessageTime);
132}
133ExpandedBlockStart.gifContractedBlock.giffunction flashMessage(){
134    var maxt=16;
135    var flag=$(".ctr2").find(".lo2").data("flag");
136    if(!flag) flag =0;
137    if(flag%2==0)
138        $(".ctr2").find(".lo2").addClass("noico");
139    else 
140        $(".ctr2").find(".lo2").removeClass("noico");
141    flag++;
142    $(".ctr2").find(".lo2").data("flag",flag);
143ExpandedSubBlockStart.gifContractedSubBlock.gif    if(flag<maxt){
144        setTimeout(flashMessage,400);
145    }
146ExpandedSubBlockStart.gifContractedSubBlock.gif    else{
147        $(".ctr2").find(".lo2").removeClass("noico");
148        $(".ctr2").find(".lo2").data("flag",0);
149    }
150}
151ExpandedBlockStart.gifContractedBlock.giffunction checkEmotepages(epageindex){
152ExpandedSubBlockStart.gifContractedSubBlock.gif    $('#pagec').find('a:eq(0)').attr({disabled:epageindex==1});
153ExpandedSubBlockStart.gifContractedSubBlock.gif    $('#pagec').find('a:eq(1)').attr({disabled:epageindex==4});
154}
155ExpandedBlockStart.gifContractedBlock.giffunction ubbTag(txa, markup)
156    txa.focus(); 
157    var strEnd=markup.replace(/\[/ig,'[/'); 
158ExpandedSubBlockStart.gifContractedSubBlock.gif    if (strEnd.indexOf('=')>-1)
159        strEnd=strEnd.replace(/(.*?)\=.*?\]/,'$1]'); 
160    } 
161ExpandedSubBlockStart.gifContractedSubBlock.gif    if(document.selection&&document.selection.type== "Text")
162    // IE, Opera 
163            var oStr=document.selection.createRange(); 
164            oStr.text=markup+oStr.text+strEnd; 
165ExpandedSubBlockStart.gifContractedSubBlock.gif    } else if(window.getSelection&&txa.selectionStart>-1
166    // Netscape 
167        var st=txa.selectionStart; 
168        var ed=txa.selectionEnd; 
169           txa.value=txa.value.substring(0,st)+markup+ 
170           txa.value.substring(st,ed)+strEnd+ 
171           txa.value.slice(ed); 
172ExpandedSubBlockStart.gifContractedSubBlock.gif    } else 
173        txa.value+=markup+strEnd; 
174    } 
175} 
176ExpandedBlockStart.gifContractedBlock.giffunction sendMessage(targetid,content){
177    var eco=encode64(content);
178ExpandedSubBlockStart.gifContractedSubBlock.gif    Async('chat/send/',{
179         target:targetid,
180         uid:User.id,
181         m:eco
182ExpandedSubBlockStart.gifContractedSubBlock.gif        },function(r){
183            var t=date2str(new Date());
184ExpandedSubBlockStart.gifContractedSubBlock.gif            if(!r){showError('与服务器通讯发生错误。',t);return false;}
185ExpandedSubBlockStart.gifContractedSubBlock.gif            if(!r.st){showError(r.err,t);return false;}
186            addMessage(User.nick,User.id,content,t,r.dbid,true);
187            clearhtml();
188ExpandedSubBlockStart.gifContractedSubBlock.gif            $("#sendbutton").css({disabled:false});
189        },'json','POST');
190}
191ExpandedBlockStart.gifContractedBlock.giffunction getMessage(userid,targetid){
192    //changecaption(__lastMessageTime);
193ExpandedSubBlockStart.gifContractedSubBlock.gif    if(__closed){
194        $("#loading").show();
195         return false;
196     }
197ExpandedSubBlockStart.gifContractedSubBlock.gif    Async('chat/get/',{
198        uid:userid,
199        target:targetid,
200        last:(typeof __lastMessageTime=='undefined')?'':__lastMessageTime
201ExpandedSubBlockStart.gifContractedSubBlock.gif        },function(r){
202            var t=date2str(new Date());
203ExpandedSubBlockStart.gifContractedSubBlock.gif            if(!r){showError('网络错误或数据传输失败。',t);return false;}
204ExpandedSubBlockStart.gifContractedSubBlock.gif            if(!r.st){showError(r.err,t);return false;}
205            var mtime='';
206ExpandedSubBlockStart.gifContractedSubBlock.gif            if(r.datas.length>0){
207                //按messageid顺序排序
208ExpandedSubBlockStart.gifContractedSubBlock.gif                r.datas=r.datas.sort(function(a,b){
209                    return a.mid-b.mid;
210                });
211ExpandedSubBlockStart.gifContractedSubBlock.gif                $.each(r.datas,function(i,n){
212                    var b=true;
213ExpandedSubBlockStart.gifContractedSubBlock.gif                    if(__lastMessageTime==''){
214ExpandedSubBlockStart.gifContractedSubBlock.gif                        if($("#msg"+n.mid).length!=0){
215                            b=false;
216                        }
217                    }
218                    if(b)addMessage(n.uname,n.uid,decode64(n.m),n.t,n.mid,n.uid==User.id);
219                    mtime=n.t;
220                });
221                if(mtime!='')
222                 __lastMessageTime=mtime;
223                flashMessage();
224            }
225            //清除LOADING
226ExpandedSubBlockStart.gifContractedSubBlock.gif            if(!$("#loading").is(":hidden")){ __loading=false;$("#loading").hide();}
227ExpandedSubBlockStart.gifContractedSubBlock.gif            setTimeout(function(){getMessage(User.id,__targetid);},__constTime)
228        },'json','GET');
229}
230ExpandedBlockStart.gifContractedBlock.giffunction scrolltoend(){
231    $("#chatwin").get(0).scrollTop=$("#chatwin").get(0).scrollHeight;
232}
233var errtimer=null;
234ExpandedBlockStart.gifContractedBlock.giffunction showError(errmess,t){
235    //$("#chatwin").find(".merr:last").fadeOut(100);
236    if(!t) t="";
237ExpandedSubBlockStart.gifContractedSubBlock.gif    if(__loading){
238        $("#lstxt").html("<font color=red>"+errmess+"</font>");
239    }
240ExpandedSubBlockStart.gifContractedSubBlock.gif    if($("#chatwin > .msgitem:last").find('.err').length>0){//错误消息已经存在
241        $("#chatwin > .msgitem:last").find('.err > span').html(errmess);
242        $("#chatwin > .msgitem:last").find('.err > font').html(t);
243    }
244ExpandedSubBlockStart.gifContractedSubBlock.gif    else{
245        $("#chatwin").find(".merr").remove();
246        $("#chatwin").append(String.format("<div class=\"msgitem merr\"><div class='err'><b disabled='disabled'>[{2}]</b> <span>{0}</span> <font>{1}</font></div></div>",errmess,t,"提示"));
247    }
248    $("#chatwin").find(".merr:last").fadeIn(100);
249    scrolltoend();
250    if(errtimer) clearTimeout(errtimer);
251ExpandedSubBlockStart.gifContractedSubBlock.gif    errtimer = setTimeout(function(){
252        $("#chatwin").find(".merr:last").fadeOut(200);
253        errtimer=null;
254    },3000)
255}
256ExpandedBlockStart.gifContractedBlock.giffunction addMessage(username,userid,msghtml,msgtime,dbid,bMyMessage){
257    var sb = new StringBuilder();
258    sb.append("<div class=\"msgitem\" id='msg{4}'>");
259    sb.append("<h2{3}>{0} {1}</h2>");
260    sb.append("<div class=\"p\">");
261    sb.append("{2}");
262    sb.append("</div>");
263    sb.append("</div>");
264    var c=String.format(sb.toString(),username,msgtime,msghtml,bMyMessage?" class='me'":"",dbid);
265    $("#chatwin").append(c);
266    scrolltoend();
267    sb=null;
268}

转载于:https://www.cnblogs.com/zonestudio/archive/2009/08/07/1541119.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值