来源:
博客园
作者:
戴九军
2011-05-27/15:05
其实为了实现这个聊天的功能我也是寻找了很多资料,实现这个聊天功能还是有很多缺陷,例如只能是一对一聊天,不能同时支持一个人对多个人聊天、不支持发送同样的消息,还有不支持的就是发送的第一个信息不能是1。下面我介绍一下我的实现方法,也希望更多的牛人能够给我指点迷津,让我们共同的把这个网页聊天功能实现的更强大,也可以作为开源代码给大家互相学习。
首先介绍一下数据库,数据库有三个表是和这个功能实现有关的,一个是user,主要是存储用户的信息其中包含了用户的姓名、帐号、密码等信息。如下图:
包含的信息只是与接下来讲解的有关的属性。
第二表,这个表有四个属性,分别是id、userId、friendId、friendType。相信大家根据字面意思都能够明白表中的属性意思:下面是表的截图:
第三个表是我们的chating表,这个表就是用户与用户建立聊天的表,有如下属性:
这里我分成两个截图显示,其中的personId就是发起聊天的用户,friendId就是接受聊天的用户,contentToFriend就是person发送给friend的信息,而contentToperson就是friend发送给person的信息,其他的属性就无需讲解了。
至此,如果大家想实现这个聊天功能的话,只需要建立这三个表就行了。下面我们开始讲解主题实现:
首先我们从数据层开始:数据层有三个类分别对应三个表,然后属性对应类中的相应的私有变量,然后有三个对应的数据库操作函数(删除、添加、根据属性获取id等等数据库操作函数)分别可以命名为,userFunction、friendListFunction、chatingFunction。
最后讲解我们的逻辑层实现,这是关键一步:这里会涉及六个文件。
#p#副标题#e#
chating_with_friend.php:
主要是显示出user的所有好友,例如如下代码:
- <ul>
- <li><a href="#" onclick="displayfriend('one')">最近联系人</a></li>
- <ul class="dispalyfriend" id="one">
- <a href="#" onclick="getbacknodisplay('one')">缩放</a>
- <?php
- foreach($friendList as $friend ){
- $friendType = $friend->get_friendType();
- $friendId = $friend->get_friendId();
- $user = get_user($friendId);
- $userName = $user->get_userName();
- if($friendType == 0){
- ?>
- <li><a href="#" onclick="connectFriend(<?php echo $friendId;?>,<?php echo $userId;?>,<?php echo $user->get_headPicture();?>)"><img style="width:20px" src="../imgs/headPicture/<?php echo $user->get_headPicture();?>.jpg"><?php echo $userName;?></a></li>
- <?php
- }
- }
- ?>
- </ul>
复制代码
这里只是显示所有的user的最近联系人的列表,关键就是遍历数据库查找所有为最近联系人的好友id,然后根据id得到user类,就可以显示所有信息。
其中
这段代码,显示用户,如果点击用户头像或者用户昵称,就会触发一个connectFriend函数,而且会传入三个参数分别是connectFriend(friendId,userId,headPicture),下面我们简单看一下这个函数,这个函数在chating.js文件中代码如下:
- function connectFriend(friendId,userId,headPicture){
- deletenode();
- //stopRefresh();
- //clearTimeout(over);
- $("chatingeare").style.display = "block";
- $("friendId").value = friendId;
- $("userId").value = userId;
- $("headPicture").value = headPicture;
- pushdown();
- getmessage();
- deletechating();
- }
复制代码
#p#副标题#e#
第一个deletenode()是一个函数:
- function deletenode(){
- var a = document.getElementById("chatingtext");
- var ul_arr = a.getElementsByTagName("p");
- while(ul_arr.length!=0){
- a.removeChild(ul_arr[0]);
- }
- }
复制代码
这个函数主要作用是清除上个与好友聊天的所有信息,因为我们的聊天主要是通过在id为chatingtext下插入<p></p>实现的,因此要清除之前的聊天记录只需要,使用DOM把他下面的所有子节点全部删除。
这段代码主要是当用户点击另外一个用户的时候会弹出对话框(对话框最初是隐藏的),对话框代码如下:
- <div id="chatingeare" style="display:none;">
- <div id="chatingtext">
- <div id="refresh" class="node"></div>
- </div>
- <div>
- <form>
- <textarea id="textarea" value=""></textarea><br/>
- <input type="button" onclick="sendmessage()" value="发送"/>
- <input id="friendId" type="hidden" value=""/><input id="userId" type="hidden" value=""/> <input id="headPicture" type="hidden" value=""/>
- <input type="button" onclick="nodisplay()" value="关闭"/>
- </form>
- </div>
- </div>
复制代码
这段代码,包含了三个hidden的type的input,主要是为了保存js中的变量值。
这段代码主要为了在js文件中互相传递参数,也就是说connectFriend(friendId,userId,headPicture)函数传入的三个参数,插入到html中input的value中,以后只要js希望得到这个参数就直接可以$(“friendId”).value就可以相应的得到friendId变量。其实这里的话可以设置全局变量,同样可以达到相应的结果。
接下来我们看pushdown函数,这个函数主要是为了,当用户正在和一个人聊天,而另外一个人却在Q用户的时候,用户可以把当前聊天的用户缩放到工具栏下,而切换与另外一个人聊天。代码如下:
- function pushdown(){
- var headPicture = $("headPicture").value;
- var friendId = $("friendId").value;
- var userId = $("userId").value;
- var len = $("newspicture").getElementsByTagName("input").length;
- var count=0;
- for(i=0;i<len;i++){
- if(friendId == $("newspicture").getElementsByTagName("input")[i].value)
- count++;
- }
- if(count==0){
- res = "<li id='"+friendId+"'><a href='#' onclick=connectFriend("+friendId+","+userId+","+headPicture+")>"+"<img style='width:20px' src =../imgs/headPicture/"+headPicture+".jpg />"+"</a> "+"<input name=headpicture value='"+friendId+"'type='hidden'></li>"
- var newNode = document.createElement("span");
- newNode.innerHTML = res;
- $("newspicture").appendChild(newNode);
- }
- }
复制代码
#p#副标题#e#
其中的前三行就是获取前面的三个变量,然后len是获取当前工具栏下的所有用户,主要是为了避免一个用户多次被缩放到工具栏下面,这里实现了一个判断,就是如果工具栏存在改用户,则不会插入用户头像,如果该工具栏下没有改用户则执行插入用户头像。
然后就是getmessage()函数:
- function getmessage(){
- var friendId = $("friendId").value;
- var userId = $("userId").value;
- var url = "../ajax/getchating.php";
- var myAjax = new Ajax.Request(
- url,
- {
- method:"post",
- parameters: {
- friendId : friendId,
- userId : userId
- },
- onError: function (request){
- alert("请求方法发生错误!"+request.statusText);
- },
- onComplete: function (request){
- var res = request.responseText;
- if(friendContext != res){
- var newNode = document.createElement("p");
- newNode.innerHTML = res;
- newNode.className = "node";
- $("chatingtext").appendChild(newNode);
- }
- friendContext = res;
- },
- asynchronous:true
- });
- t = setTimeout(getmessage,2000);
- //addnewnode();
- }
复制代码
代码主要是通过ajax实现的,前面两行代码同样是获取userId、friendId变量。url主要是链接到相应的PHP处理文件,然后就是我们熟悉的ajax。接下来我们去查看一个getchating.php看一下主要是如何处理获取聊天信息功能的。
- $friendId = $_POST['friendId'];
- $userId = $_POST['userId'];
-
- if (isset($friendId) && $friendId != 0 && isset($userId) && $userId != 0){
- if(exist_chating($userId, $friendId)){
- $id = exist_chating($userId, $friendId);
- $user = get_user($friendId);
- $userName = $user->get_userName();
- $chating = get_chating($id);
- $contentToPerson = $chating->get_contentToPerson();
- if($contentToPerson != 1){
- echo "<span style='color:blue''>$userName:</span> $contentToPerson";
- }
- else
- echo " ";
- }
- if(exist_chating($friendId,$userId)){
- $id = exist_chating($friendId,$userId);
- $user = get_user($friendId);
- $userName = $user->get_userName();
- $chating = get_chating($id);
- $contentToPerson = $chating->get_contentToFriend();
- if($contentToPerson != 1){
- echo "<span style='color:blue''>$userName:</span> $contentToPerson";
- }
- else
- echo " ";
- }
- else{
- echo "";
- }
- }
复制代码
#p#副标题#e#
前面两行代码是,获取ajax传入的两个变量,if条件主要是判断改id是否有效,如果就是主题代码:第一个条件判断该聊天是否已经建立,如果建立了,则直接返回用户输入的信息。第二个同样是判断是否已经建立。建立以后从数据库读取信息content,然后返回信息的html内容。Ajax得到返回的html代码,然后判断该代码是否和之前读取的代码相同,如果代码相同表示好友没有发送新消息给用户,那么我们在对话框中就不需要插入新的信息,如果不存在则插入本条返回的html信息,直接显示在对话框中。
- onComplete: function (request){
- var res = request.responseText;
- if(friendContext != res){
- var newNode = document.createElement("p");
- newNode.innerHTML = res;
- newNode.className = "node";
- $("chatingtext").appendChild(newNode);
- }
- friendContext = res;
- },
复制代码
这段就是处理返回的结果代码,friendContext就是前一次获取的数据库中的好友信息。res就是获取的最新信息,如果两者不相同,则执行插入操作。如果两者相同则不需要做任何操作。
- t = setTimeout(getmessage,2000);
复制代码
最后一段代码就是,每隔2秒钟获取数据库中的好友发给user的信息。
到这里为止我们就讲解了如何每隔2秒钟,获取是否有好友发送信息给自己。如果有就会插入在聊天对话框中,这样就可以实现,friend发送的消息,在本地可以实时的查看,而不需要刷新。
接下来,我们讲解如何发送信息给好友:
- <form>
- <textarea id="textarea" value=""></textarea><br/>
- <input type="button" onclick="sendmessage()" value="发送"/>
- <input id="friendId" type="hidden" value=""/><input id="userId" type="hidden" value=""/> <input id="headPicture" type="hidden" value=""/>
- <input type="button" onclick="nodisplay()" value="关闭"/>
- </form>
复制代码
代码里面有一个发送的content和发送的用户,以及发送给谁的用户的value值,并且出了content其他的都是隐藏的,这个在前面的connectFriend函数里面已经讲解过,这里不在累赘。代码中的一个value值为“发送”的button,当用户点击发送的时候会触发sendmessage函数,下面我们来简单的看一下这个函数:
- function sendmessage(){
- var friendId = $("friendId").value;
- var userId = $("userId").value;
- var content = $("textarea").value;
- var url = "../ajax/chating.php";
- var myAjax = new Ajax.Request(
- url,
- {
- method:"post",
- parameters: {
- friendId : friendId,
- userId : userId,
- content : content
- },
- onError: function (request){
- alert("请求方法发生错误!"+request.statusText);
- },
- onComplete: function (request){
- var res = request.responseText;
- var newNode = document.createElement("p");
- newNode.innerHTML = res;
- newNode.className = "node";
- $("chatingtext").appendChild(newNode);
- },
- asynchronous:true
- });
- //t = setTimeout(getmessage, 5);
- //refresh(friendId,userId);
- //getmessage(friendId,userId);
- }
复制代码
前三行代码主要是获取三个变量值。url主要是链接处理文件PHP。接下来是Ajax,我们看一下chating.php处理的功能:
- $friendId = $_POST['friendId'];
- $userId = $_POST['userId'];
- $content = $_POST['content'];
- $content = iconv('UTF-8','gb2312',$content);
-
- if (isset($friendId) && $friendId != 0 && isset($userId) && $userId != 0){
- if (exist_chating($userId, $friendId)) {
- $id =exist_chating($userId, $friendId);
- $user = get_user($userId);
- $userName = $user->get_userName();
- update_contentToFriend($id, $content);
- $chating = get_chating($id);
- $contentToFriend = $chating->get_contentToFriend();
- echo "<span style='color:red'>$userName:</span> $contentToFriend";
- }
- else if(exist_chating($friendId,$userId )){
- $id =exist_chating($friendId,$userId );
- $user = get_user($userId);
- $userName = $user->get_userName();
- update_contentToPerson($id, $content);
- $chating = get_chating($id);
- $contentToPerson= $chating->get_contentToPerson();
- echo "<span style='color:red'>$userName:</span> $contentToPerson";
- }
- else{
- $id = save_chating($userId, $friendId, $content, "1");
- $user = get_user($userId);
- $userName = $user->get_userName();
- $chating = get_chating($id);
- $contentToFriend = $chating->get_contentToFriend();
- echo "<div><span style='color:red''>$userName:</span> $contentToFriend</div>";
- }
复制代码
#p#副标题#e#
前四行是获取Ajax传入的三个变量,然后判断两个id是否合法。
接下来三个if判断函数,第一个判断当前是否已经在数据库建立了两者的聊天记录,第二个判断和第一个一样,主要是为了防止以下这种情况的发生:
其实这两者的关系是一样的,因此只需要存储一
种,也就是先发起对话的人为user,回复信息的
人为Friend。
如果数据库没有建立二者的聊天记录,在在数据库插入一段新的记录,并返回聊天信息。
- var newNode = document.createElement("p");
- newNode.innerHTML = res;
- newNode.className = "node";
- $("chatingtext").appendChild(newNode);
复制代码
Ajax得到返回结果直接插入在html中,从而就可以实现,自己发送的消息自己可以查看。
- function bindUI(){
- getothermessage();
- }
-
- function getothermessage(){
- var userId = $("userId").value;
- var url = "../ajax/getothermessage.php"
- var myAjax = new Ajax.Request(
- url,
- {
- method:"post",
- parameters: {
- userId:userId
- },
- onError: function (request){
- alert("请求方法发生错误!"+request.statusText);
- },
- onComplete: function (request){
- var res = request.responseText;
- if(res.indexOf("newmessage") != -1){
- play_click("../imgs/msg.wav");
- }
- },
- asynchronous:true
- });
- }
-
- function play_click(url){
- var div = $('music');
- div.innerHTML = '<embed src="'+url+'" loop="0" autostart="true" hidden="true"></embed>';
- var emb = document.getElementsByTagName('EMBED')[0];
- if (emb) {
- setTimeout(function(){div.innerHTML='';},1000);
- }
- }
-
- document.observe('dom:loaded', bindUI);
复制代码
还有就是一些辅助的信息功能,比如说getothermessage(),就是获取当前正在和好友聊天,是否还有其他用户发送消息给我。Play_click()主要是声音提示,当有新的消息时候会有声音提示用户您有新的消息。
最后就是用户聊天结束以后,建立的聊天要从数据库删除,处理函数主要是:
deletechating.php同样的是PHP处理文件,主要是在数据库删除用户聊天记录。