Web IM 远程及时聊天通信程序

开发 前端 项目管理
这篇文章主要介绍用JavaScript和jQuery、HTML、CSS以及用第三方聊天JavaScript(jsjac)框架构建一个BS Web的聊天应用程序。此程序可以和所有连接到Openfire服务器的应用进行通信、发送消息。

这篇文章主要介绍用JavaScript和jQuery、HTML、CSS以及用第三方聊天JavaScript(jsjac)框架构建一个BS Web的聊天应用程序。此程序可以和所有连接到Openfire服务器的应用进行通信、发送消息。如果要运行本程序还需要一个聊天服务器Openfire,

以及需要用到Http方式和Openfire通信的第三方库(JabberHTTPBind)。

JabberHTTPBind是jabber提供的XMPP协议通信的Http bind发送的形式,它可以完成WebBrowser和Openfire建立长连接通信。

主要通信流程如下图所示:

image

用户A通过JavaScript jsjac.js库发送一条消息到JabberHTTPBind这个Servlet容器,然后JabberHTTPBind的Servlet容器会向Openfire发送XMPP协议的XML报文。Openfire Server接收到报文后解析,然后发送给指定的用户B。JabberHTTPBind获取到Openfire Server发送的数据后,解析报文向当前Servlet容器中的链接的Session中找到指定的用户再发送数据给用户B。

WebBrowser端用的是jsjac和JabberHTTPBind建立的连接,所有数据都要经过JabberHTTPBind解析/转换发送给Openfire。

先上张图看看效果,呵呵~这里是用户hoojo和girl的聊天画面,双方在进行互聊……

image

可以发送表情、改变字体样式(对方界面也可以看到你的字体样式),同时右侧是显示/收缩详情的信息

image

收缩详情

image

聊天界面部分截图

用户登录、注册,sendTo表示你登录后向谁发送聊天消息、并且建立一个聊天窗口

image

登录成功后,你可以在日志控制台看到你的登陆状态、或是在firebug控制台中看到你的连接请求状态

image

image

登陆失败

image

只有connecting,就没有下文了

image

登陆成功后,你就可以给指定用户发送消息,且设置你想发送消息的新用户点击new Chat按钮创建新会话

image

如果你来了新消息,在浏览器的标题栏会有新消息提示

image

如果你当前聊天界面的窗口都是关闭状态,那么在右下角会有消息提示的闪动图标

#p#

导读

如果你对openfire还不是很了解或是不知道安装,建议你看看这2篇文章

http://www.cnblogs.com/hoojo/archive/2012/05/17/2506769.html

http://www.cnblogs.com/hoojo/archive/2012/05/13/2498151.html

因为这里还用到了JabberHTTPBind 以及在使用它或是运行示例的时候会遇到些问题,那么你可以看看这篇文章

http://www.cnblogs.com/hoojo/archive/2012/05/17/2506845.html

开发环境

System:Windows

JavaEE Server:Tomcat 5.0.28+/Tomcat 6

WebBrowser:IE6+、Firefox3.5+、Chrome 已经兼容浏览器

JavaSDK:JDK 1.6+

Openfire 3.7.1

IDE:eclipse 3.2、MyEclipse 6.5

开发依赖库

image

jdk1.4+

serializer.jar

xalan.jar

jhb-1.0.jar

log4j-1.2.16.jar

jhb-1.0.jar 这个就是JabberHTTPBind,我把编译的class打成jar包了

JavaScript lib

image

jquery.easydrag.js 窗口拖拽JavaScript lib

jquery-1.7.1.min.js jquery lib

jsjac.js 通信核心库

local.chat-2.0.js 本地会话窗口发送消息JavaScript库

remote.jsjac.chat-2.0.js 远程会话消息JavaScript库

send.message.editor-1.0.js 窗口编辑器JavaScript库

一、准备工作

jsjac JavaScript lib下载:https://github.com/sstrigler/JSJaC/

如果你不喜欢用jsjac JavaScript lib和Openfire通信,那么有一款jQuery的plugin可以供你使用,下载地址

jQuery-XMPP-plugin https://github.com/maxpowel/jQuery-XMPP-plugin

这里有所以能支持Openfire通信的第三方库,有兴趣的可以研究下 http://xmpp.org/xmpp-software/libraries/

jquery.easydrag 下载:http://fromvega.com/code/easydrag/jquery.easydrag.js

jquery 下载:http://code.jquery.com/jquery-1.7.1.min.js

JabberHTTPBind jhb.jar 下载:http://download.csdn.net/detail/ibm_hoojo/4489188

images 图片素材:http://download.csdn.net/detail/ibm_hoojo/4489439

工程目录结构

image

#p#

二、核心代码演示

1、主界面(登陆、消息提示、日志、建立新聊天窗口)代码 index.jsp

  1. <%@ page language="java" pageEncoding="UTF-8" %> 
  2. <%  
  3. String path = request.getContextPath();  
  4. String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";  
  5. %> 
  6.    
  7. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
  8. <html> 
  9.   <head> 
  10.     <base href="<%=basePath%>"> 
  11.       
  12.     <title>WebIM Chat</title> 
  13.     <meta http-equiv="pragma" content="no-cache"> 
  14.     <meta http-equiv="cache-control" content="no-cache"> 
  15.     <meta http-equiv="expires" content="0">      
  16.     <meta http-equiv="author" content="hoojo"> 
  17.     <meta http-equiv="email" content="hoojo_@126.com"> 
  18.     <meta http-equiv="blog" content="http://blog.csdn.net/IBM_hoojo"> 
  19.     <meta http-equiv="blog" content="http://hoojo.cnblogs.com"> 
  20.     <link rel="stylesheet" type="text/css" href="css/chat-2.0.css" /> 
  21.     <script type="text/javascript"> 
  22.         window.contextPath = "<%=path%>";  
  23.         window["serverDomin"] = "192.168.8.22";  
  24.     </script> 
  25.     <script type="text/javascript" src="jslib/jquery-1.7.1.min.js"></script> 
  26.     <script type="text/javascript" src="jslib/jsjac.js"></script> 
  27.     <!-- script type="text/javascript" src="debugger/Debugger.js"></script--> 
  28.     <script type="text/javascript" src="jslib/send.message.editor-1.0.js"></script> 
  29.     <script type="text/javascript" src="jslib/jquery.easydrag.js"></script> 
  30.     <script type="text/javascript" src="jslib/remote.jsjac.chat-2.0.js"></script> 
  31.     <script type="text/javascript" src="jslib/local.chat-2.0.js"></script> 
  32.     <script type="text/javascript"> 
  33.         $(function () {  
  34.               
  35.             $("#login").click(function () {  
  36.                 var userName = $(":text[name='userName']").val();  
  37.                 var receiver = $("*[name='to']").val();  
  38.                 // 建立一个聊天窗口应用,并设置发送者和消息接收者  
  39.                 $.WebIM({  
  40.                     sender: userName,  
  41.                     receiver: receiver  
  42.                 });  
  43.                 // 登陆到openfire服务器  
  44.                  remote.jsjac.chat.login(document.userForm);  
  45.                  $("label").text(userName);  
  46.                  $("form").hide();  
  47.                  $("#newConn").show();  
  48.             });  
  49.               
  50.             $("#logout").click(function () {  
  51.                  // 退出openfire登陆,断开链接  
  52.                  remote.jsjac.chat.logout();  
  53.                  $("form").show();  
  54.                  $("#newConn").hide();  
  55.                  $("#chat").hide(800);  
  56.             });  
  57.               
  58.             $("#newSession").click(function () {  
  59.                 var receiver = $("#sendTo").val();  
  60.                 // 建立一个新聊天窗口,并设置消息接收者(发送给谁?)  
  61.                 $.WebIM.newWebIM({  
  62.                     receiver: receiver  
  63.                 });  
  64.             });  
  65.         });  
  66.     </script> 
  67.   </head> 
  68.     
  69.   <body> 
  70.     <!-- 登陆表单 --> 
  71.     <form name="userForm" style="background-color: #fcfcfc; width: 100%;"> 
  72.         userName:<input type="text" name="userName" value="boy"/> 
  73.         password:<input type="password" name="password" value="boy"/> 
  74.           
  75.         register: <input type="checkbox" name="register"/> 
  76.         sendTo: <input type="text" id="to" name="to" value="hoojo" width="10"/> 
  77.         <input type="button" value="Login" id="login"/>   
  78.     </form> 
  79.     <!-- 新窗口聊天 --> 
  80.     <div id="newConn" style="display: none; background-color: #fcfcfc; width: 100%;"> 
  81.            User:<label></label> 
  82.            sendTo: <input type="text" id="sendTo" value="hoojo" width="10"/> 
  83.            <input type="button" value="new Chat" id="newSession"/>   
  84.            <input type="button" value="Logout" id="logout"/> 
  85.     </div> 
  86.     <!-- 日志信息 --> 
  87.     <div id="error" style="display: ; background-color: red;"></div> 
  88.     <div id="info" style="display: ; background-color: #999999;"></div> 
  89.     <!-- 聊天来消息提示 --> 
  90.     <div class="chat-message"> 
  91.         <img src="images/write_icon.png" class="no-msg"/> 
  92.         <img src="images/write_icon.gif" class="have-msg" style="display: none;"/> 
  93.     </div> 
  94.   </body> 
  95. </html> 

下面这段代码尤为重要,它是设置你链接openfire的地址。这个地址一段错误你将无法进行通信!

  1. <script type="text/javascript">  
  2.     window.contextPath = "<%=path%>";  
  3.     window["serverDomin"] = "192.168.8.22";  
  4. </script>  

$.WebIM方法是主函数,用它可以覆盖local.chat中的基本配置,它可以完成聊天窗口的创建。$.WebIM.newWebIM方法是新创建一个窗口,只是消息的接收者是一个新用户。

  1. $.WebIM({  
  2.     sender: userName,  
  3.     receiver: receiver  
  4. });  
  5.    
  6. $.WebIM.newWebIM({  
  7.     receiver: receiver  
  8. }); 

remote.jsjac.chat.login(document.userForm);方法是用户登录到Openfire服务器

参数如下:

  1. httpbase: window.contextPath + "/JHB/"//请求后台http-bind服务器url  
  2. domain: window["serverDomin"], //"192.168.5.231", // 192.168.5.231 当前有效域名  
  3. username: ""// 登录用户名  
  4. pass: ""// 密码  
  5. timerval: 2000// 设置请求超时  
  6. resource: "WebIM"// 链接资源标识  
  7. register: true // 是否注册 

remote.jsjac.chat.logout();是退出、断开openfire的链接

#p#

2、本地聊天应用核心代码 local.chat-2.0.js

  1. /***  
  2.  * jquery local chat  
  3.  * @version v2.0   
  4.  * @createDate -- 2012-5-28  
  5.  * @author hoojo  
  6.  * @email hoojo_@126.com  
  7.  * @blog http://hoojo.cnblogs.com & http://blog.csdn.net/IBM_hoojo  
  8.  * @requires jQuery v1.2.3 or later, send.message.editor-1.0.js  
  9.  * Copyright (c) 2012 M. hoo  
  10.  **/ 
  11.    
  12. ;(function ($) {  
  13.    
  14.     if (/1\.(0|1|2)\.(0|1|2)/.test($.fn.jquery) || /^1.1/.test($.fn.jquery)) {  
  15.         alert('WebIM requires jQuery v1.2.3 or later!  You are using v' + $.fn.jquery);  
  16.         return;  
  17.     }  
  18.       
  19.     var faceTimed, count = 0;  
  20.       
  21.     var _opts = defaultOptions = {  
  22.         version: 2.0,  
  23.         chat: "#chat",  
  24.         chatEl: function () {  
  25.             var $chat = _opts.chat;  
  26.             if ((typeof _opts.chat) == "string") {  
  27.                 $chat = $(_opts.chat);  
  28.             } else if ((typeof _opts.chat) == "object") {  
  29.                 if (!$chat.get(0)) {  
  30.                     $chat = $($chat);  
  31.                 }  
  32.             }   
  33.             return $chat;  
  34.         },  
  35.         sendMessageIFrame: function (receiverId) {  
  36.             return $("iframe[name='sendMessage" + receiverId + "']").get(0).contentWindow;  
  37.         },  
  38.         receiveMessageDoc: function (receiverId) {  
  39.             receiverId = receiverId || "";  
  40.             var docs = [];  
  41.             $.each($("iframe[name^='receiveMessage" + receiverId + "']"), function () {  
  42.                 docs.push($(this.contentWindow.document));  
  43.             });  
  44.             return docs;  
  45.             //return $($("iframe[name^='receiveMessage" + receiverId + "']").get(0).contentWindow.document);  
  46.         },  
  47.         sender: ""// 发送者  
  48.         receiver: ""// 接收者  
  49.         setTitle: function (chatEl) {  
  50.             var receiver = this.getReceiver(chatEl);  
  51.             chatEl.find(".title").html("和" + receiver + "聊天对话中");  
  52.         },  
  53.         getReceiver: function (chatEl) {  
  54.             var receiver = chatEl.attr("receiver");  
  55.             if (~receiver.indexOf("@")) {  
  56.                 receiver = receiver.split("@")[0];  
  57.             }  
  58.             return receiver;  
  59.         },  
  60.           
  61.         // 接收消息iframe样式  
  62.         receiveStyle: [  
  63.             '<html>',  
  64.                 '<head><style type="text/css">',  
  65.                 'body{border:0;margin:0;padding:3px;height:98%;cursor:text;background-color:white;font-size:12px;font-family:Courier,serif,monospace;}',  
  66.                 '.msg{margin-left: 1em;}p{margin:0;padding:0;}.me{color: blue;}.you{color:green;}',  
  67.                 '</style></head>',  
  68.                 '<body></body>',  
  69.             '</html>' 
  70.         ].join(""),  
  71.         writeReceiveStyle: function (receiverId) {  
  72.             this.receiveMessageDoc(receiverId)[0].get(0).write(this.receiveStyle);  
  73.         },  
  74.           
  75.         datetimeFormat: function (v) {  
  76.             if (~~v < 10) {  
  77.                 return "0" + v;  
  78.             }  
  79.             return v;  
  80.         },  
  81.         getDatetime: function () {  
  82.             // 设置当前发送日前  
  83.             var date = new Date();  
  84.             var datetime = date.getFullYear() + "-" + date.getMonth() + "-" + date.getDate();  
  85.             datetime = " " + _opts.datetimeFormat(date.getHours())   
  86.                         + ":" + _opts.datetimeFormat(date.getMinutes())   
  87.                         + ":" + _opts.datetimeFormat(date.getSeconds());  
  88.             return datetime;  
  89.         },  
  90.           
  91.         /***  
  92.          * 发送消息的格式模板                      
  93.          * flag = true 表示当前user是自己,否则就是对方  
  94.          **/   
  95.         receiveMessageTpl: function (userName, styleTpl, content, flag) {  
  96.             var userCls = flag ? "me" : "you";  
  97.             if (styleTpl && flag) {  
  98.                 content = [ "<span style='", styleTpl, "'>", content, "</span>" ].join("");  
  99.             }  
  100.             return [  
  101.                 '<p class="', userCls, '">', _opts.getDatetime(), '  ', userName, ':</p>',  
  102.                 '<p class="msg">', content, '</p>' 
  103.             ].join("");  
  104.         },  
  105.           
  106.         // 工具类按钮触发事件返回html模板  
  107.         sendMessageStyle: {  
  108.              cssStyle: {  
  109.                  bold: "font-weight: bold;",  
  110.                  underline: "text-decoration: underline;",  
  111.                  italic: "font-style: oblique;" 
  112.              },  
  113.              setStyle: function (style, val) {  
  114.                  if (val) {  
  115.                      _opts.sendMessageStyle[style] = val;  
  116.                  } else {  
  117.                      var styleVal = _opts.sendMessageStyle[style];  
  118.                      if (styleVal === undefined || !styleVal) {  
  119.                          _opts.sendMessageStyle[style] = true;  
  120.                      } else {  
  121.                          _opts.sendMessageStyle[style] = false;  
  122.                      }  
  123.                  }  
  124.              },  
  125.              getStyleTpl: function () {  
  126.                  var tpl = "";  
  127.                  $.each(_opts.sendMessageStyle, function (style, item) {  
  128.                      //alert(style + "#" + item + "#" + (typeof item));  
  129.                      if (item === true) {  
  130.                          tpl += _opts.sendMessageStyle.cssStyle[style];  
  131.                      } else if ((typeof item) === "string") {  
  132.                          //alert(style + "-------------" + sendMessageStyle[style]);  
  133.                          tpl += style + ":" + item + ";";  
  134.                      }  
  135.                  });  
  136.                  return tpl;  
  137.              }  
  138.         },  
  139.         // 向接收消息iframe区域写消息  
  140.         writeReceiveMessage: function (receiverId, userName, content, flag) {  
  141.             if (content) {  
  142.                 // 发送消息的样式  
  143.                 var styleTpl = _opts.sendMessageStyle.getStyleTpl();  
  144.                 var receiveMessageDoc = _opts.receiveMessageDoc(receiverId);  
  145.                 $.each(receiveMessageDoc, function () {  
  146.                     var $body = this.find("body");  
  147.                     // 向接收信息区域写入发送的数据  
  148.                     $body.append(_opts.receiveMessageTpl(userName, styleTpl, content, flag));  
  149.                     // 滚动条滚到底部  
  150.                     this.scrollTop(this.height());  
  151.                 });  
  152.             }  
  153.         },  
  154.         // 发送消息  
  155.         sendHandler: function ($chatMain) {  
  156.             var doc = $chatMain.find("iframe[name^='sendMessage']").get(0).contentWindow.document;  
  157.               
  158.             var content = doc.body.innerHTML;  
  159.             content = $.trim(content);  
  160.             content = content.replace(new RegExp("<br>""gm"), "");  
  161.             // 获取即将发送的内容  
  162.             if (content) {  
  163.                 var sender = $chatMain.attr("sender");  
  164.                 var receiverId = $chatMain.attr("id");  
  165.                 // 接收区域写消息  
  166.                 _opts.writeReceiveMessage(receiverId, sender, content, true);  
  167.                   
  168.                 //############# XXX  
  169.                 var receiver = $chatMain.find("#to").val();  
  170.                 //var receiver = $chatMain.attr("receiver");  
  171.                 // 判断是否是手机端会话,如果是就发送纯text,否则就发送html代码  
  172.                 var flag = _opts.isMobileClient(receiver);  
  173.                 if (flag) {  
  174.                     var text = $(doc.body).text();  
  175.                     text = $.trim(text);  
  176.                     if (text) {  
  177.                         // 远程发送消息  
  178.                         remote.jsjac.chat.sendMessage(text, receiver);  
  179.                     }  
  180.                 } else { // 非手机端通信 可以发送html代码  
  181.                     var styleTpl = _opts.sendMessageStyle.getStyleTpl();  
  182.                     content = [ "<span style='", styleTpl, "'>", content, "</span>" ].join("");  
  183.                     remote.jsjac.chat.sendMessage(content, receiver);  
  184.                 }  
  185.                   
  186.                 // 清空发送区域  
  187.                 $(doc).find("body").html("");  
  188.             }  
  189.         },   
  190.           
  191.         faceImagePath: "images/emotions/",  
  192.         faceElTpl: function (i) {  
  193.             return [  
  194.                 "<img src='",  
  195.                 this.faceImagePath,  
  196.                 (i - 1),  
  197.                 "fixed.bmp' gif='",  
  198.                 this.faceImagePath,  
  199.                 (i - 1),  
  200.                 ".gif'/>" 
  201.             ].join("");  
  202.         },  
  203.         // 创建表情html elements  
  204.         createFaceElement: function ($chat) {  
  205.             var faces = [];  
  206.             for (var i = 1; i < 100; i++) {  
  207.                  faces.push(this.faceElTpl(i));  
  208.                  if (i % 11 == 0) {  
  209.                      faces.push("<br/>");  
  210.                  }   
  211.             }  
  212.             $chat.find("#face").html(faces.join(""));  
  213.             this.faceHandler($chat);  
  214.         },  
  215.         // 插入表情  
  216.         faceHandler: function ($chat) {  
  217.             $chat.find("#face img").click(function () {  
  218.                  $chat.find("#face").hide(150);  
  219.                  var imgEL = "<img src='" + $(this).attr("gif") + "'/>";  
  220.                  var $chatMain = $(this).parents(".chat-main");  
  221.                  var win = $chatMain.find("iframe[name^='sendMessage']").get(0).contentWindow;  
  222.                  var doc = win.document;  
  223.                  sendMessageEditor.insertAtCursor(imgEL, doc, win);  
  224.             });  
  225.             // 表情隐藏  
  226.             $chat.find("#face, #face img").mouseover(function () {  
  227.                 window.clearTimeout(faceTimed);  
  228.             }).mouseout(function () {  
  229.                 window.clearTimeout(faceTimed);  
  230.                 faceTimed = window.setTimeout(function () {  
  231.                     $chat.find("#face").hide(150);  
  232.                 }, 700);  
  233.             });  
  234.         },  
  235.         /***  
  236.          * 发送消息工具栏按钮事件方法  
  237.          **/ 
  238.         toolBarHandler: function () {  
  239.             var $chat = $(this).parents(".chat-main");  
  240.             var targetCls = $(this).attr("class");  
  241.             if (targetCls == "face") {  
  242.                 $chat.find("#face").show(150);  
  243.                 window.clearTimeout(faceTimed);  
  244.                 faceTimed = window.setTimeout(function () {  
  245.                     $chat.find("#face").hide(150);  
  246.                 }, 1000);  
  247.             } else if (this.tagName == "DIV") {  
  248.                 _opts.sendMessageStyle.setStyle(targetCls);  
  249.             } else if (this.tagName == "SELECT") {  
  250.                 _opts.sendMessageStyle.setStyle($(this).attr("name"), $(this).val());  
  251.                 if ($(this).attr("name") == "color") {  
  252.                     $(this).css("background-color", $(this).val());  
  253.                 }  
  254.             }  
  255.               
  256.             // 设置sendMessage iframe的style css  
  257.             _opts.writeSendStyle();  
  258.         },  
  259.         // 设置sendMessage iframe的style css  
  260.         writeSendStyle: function () {  
  261.             var styleTpl = _opts.sendMessageStyle.getStyleTpl();  
  262.             var styleEL = ['<style type="text/css">body{', styleTpl,'}</style>'].join("");  
  263.               
  264.             $("body").find("iframe[name^='sendMessage']").each(function () {  
  265.                 var $head = $(this.contentWindow.document).find("head");  
  266.                 if ($head.find("style").size() > 1) {  
  267.                     $head.find("style:gt(0)").remove();  
  268.                 }  
  269.                 if (styleTpl) {  
  270.                     $head.append(styleEL);  
  271.                 }  
  272.             });  
  273.         },                  
  274.           
  275.         isMobileClient: function (receiver) {  
  276.             var moblieClients = ["iphone""ipad""ipod""wp7""android""blackberry""Spark""warning""symbian"];  
  277.             var flag = false;  
  278.             for (var i in moblieClients) {  
  279.                 if (~receiver.indexOf(moblieClients[i])) {  
  280.                     return true;  
  281.                 }  
  282.             }  
  283.             return false;  
  284.         },  
  285.    
  286.         // 聊天界面html元素  
  287.         chatLayoutTemplate: function (userJID, sender, receiver, product, flag) {  
  288.             var display = "";  
  289.             if (flag) {  
  290.                 display = "style='display: none;'";  
  291.             }  
  292.             return [  
  293.             '<div class="chat-main" id="', userJID,  
  294.                 '" sender="', sender, '" receiver="', receiver, '">',  
  295.                       
  296.                 '<div id="chat"><div class="radius">',  
  297.                     '<table>',  
  298.                         '<tr>',  
  299.                             '<td colspan="3" class="title"></td>',  
  300.                         '</tr>',  
  301.                         '<tr>',  
  302.                             '<td class="receive-message">',  
  303.                                 '<iframe name="receiveMessage', userJID,'" frameborder="0" width="100%" height="100%"></iframe>',  
  304.                             '</td>',  
  305.                             '<td rowspan="4" class="split" ', display, '></td>',  
  306.                             '<td rowspan="4" class="product-info" ', display, '>',  
  307.                                 '<ul>',  
  308.                                     '<div class="header">商品详情</div>',  
  309.                                     '<li class="pic">',  
  310.                                     '<img src="', product.pic, '"/></li>',  
  311.                                     '<li class="product-name">', product.name, '</li>',  
  312.                                     '<li class="price">团购价:<span>', product.price, '</span>元</li>',  
  313.                                     '<li class="market-price">市场价:<s><i>', product.marketPrice, '</i></s>元</li>',  
  314.                                     '<li>快递公司:', product.deliverOrgs, '</li>',  
  315.                                     '<li>仓库:', product.wareHouses, '</li>',  
  316.                                     product.skuAttrs,  
  317.                                 '</ul>',  
  318.                             '</td>',  
  319.                         '</tr>',  
  320.                         '<tr class="tool-bar">',  
  321.                             '<td>',  
  322.                                 '<select name="font-family" class="family">',  
  323.                                     '<option>宋体</option>',  
  324.                                     '<option>黑体</option>',  
  325.                                     '<option>幼圆</option>',  
  326.                                     '<option>华文行楷</option>',  
  327.                                     '<option>华文楷体</option>',  
  328.                                     '<option>华文楷体</option>',  
  329.                                     '<option>华文彩云</option>',  
  330.                                     '<option>华文隶书</option>',  
  331.                                     '<option>微软雅黑</option>',  
  332.                                     '<option>Fixedsys</option>',  
  333.                                 '</select>',  
  334.                                   
  335.                                 '<select name="font-size">',  
  336.                                     '<option value="12px">大小</option>',  
  337.                                     '<option value="10px">10</option>',  
  338.                                     '<option value="12px">12</option>',  
  339.                                     '<option value="14px">14</option>',  
  340.                                     '<option value="16px">16</option>',  
  341.                                     '<option value="18px">18</option>',  
  342.                                     '<option value="20px">20</option>',  
  343.                                     '<option value="24px">24</option>',  
  344.                                     '<option value="28px">28</option>',  
  345.                                     '<option value="36px">36</option>',  
  346.                                     '<option value="42px">42</option>',  
  347.                                     '<option value="52px">52</option>',  
  348.                                 '</select>',  
  349.                                 '<select name="color">',  
  350.                                     '<option value="" selected="selected">颜色</option>',  
  351.                                     '<option value="#000000" style="background-color:#000000"></option>',  
  352.                                     '<option value="#FFFFFF" style="background-color:#FFFFFF"></option>',  
  353.                                     '<option value="#008000" style="background-color:#008000"></option>',  
  354.                                     '<option value="#800000" style="background-color:#800000"></option>',  
  355.                                     '<option value="#808000" style="background-color:#808000"></option>',  
  356.                                     '<option value="#000080" style="background-color:#000080"></option>',  
  357.                                     '<option value="#800080" style="background-color:#800080"></option>',  
  358.                                     '<option value="#808080" style="background-color:#808080"></option>',  
  359.                                     '<option value="#FFFF00" style="background-color:#FFFF00"></option>',  
  360.                                     '<option value="#00FF00" style="background-color:#00FF00"></option>',  
  361.                                     '<option value="#00FFFF" style="background-color:#00FFFF"></option>',  
  362.                                     '<option value="#FF00FF" style="background-color:#FF00FF"></option>',  
  363.                                     '<option value="#FF0000" style="background-color:#FF0000"></option>',  
  364.                                     '<option value="#0000FF" style="background-color:#0000FF"></option>',  
  365.                                     '<option value="#008080" style="background-color:#008080"></option>',  
  366.                                 '</select>',  
  367.                                 '<div class="bold"></div>',  
  368.                                 '<div class="underline"></div>',  
  369.                                 '<div class="italic"></div>',  
  370.                                 '<div class="face"></div>',  
  371.                                 '<div class="history">消息记录</div>',  
  372.                             '</td>',  
  373.                         '</tr>',  
  374.                         '<tr class="send-message">',  
  375.                             '<td>',  
  376.                                 '<iframe name="sendMessage', userJID,'" width="100%" height="80px" frameborder="0"></iframe>',  
  377.                             '</td>',  
  378.                         '</tr>',  
  379.                         '<tr class="bottom-bar">',  
  380.                             '<td><input type="text" id="to" name="to" value="hoojo" style="width: 100px; display: none;"/><input type="button" value="关闭" id="close"/>',  
  381.                             '<input type="button" value="发送(Enter)" id="send"/> </td>',  
  382.                         '</tr>',  
  383.                     '</table></div>',  
  384.                     '<div id="face"></div>',  
  385.                 '</div>',  
  386.             '</div>' 
  387.             ].join("");  
  388.         },  
  389.           
  390.         initWebIM: function (userJID, receiver) {  
  391.             var product = {  
  392.                 name: "小玩熊",  
  393.                 pic: "http://avatar.csdn.net/9/7/A/2_ibm_hoojo.jpg",  
  394.                 price: "198.00",  
  395.                 marketPrice: "899.90",  
  396.                 deliverOrgs: "EMS",  
  397.                 wareHouses: "A库",  
  398.                 skuAttrs: "" 
  399.             };  
  400.             var chatEl = $(_opts.chatLayoutTemplate(userJID, _opts.sender, receiver, product));  
  401.             $("body").append(chatEl);                          
  402.               
  403.             // 拖拽  
  404.             $("#" + userJID).easydrag();  
  405.             // 初始化sendMessageEditor相关信息  
  406.             sendMessageEditor.iframe = this.sendMessageIFrame(userJID);  
  407.             sendMessageEditor.init(userJID);      
  408.               
  409.             _opts.setTitle(chatEl);  
  410.             _opts.writeReceiveStyle(userJID);  
  411.             _opts.writeSendStyle();  
  412.             _opts.createFaceElement(chatEl);  
  413.               
  414.             // 查看更多详情  
  415.             chatEl.find(".more").click(function () {  
  416.                 var $ul = $(this).parents("ul");  
  417.                 $ul.find(".more").toggle();  
  418.                 $ul.find(".info").toggle();  
  419.                 $ul.find(".pic").toggle();  
  420.             });  
  421.               
  422.             // 收缩详情  
  423.             chatEl.find(".split").toggle(function () {  
  424.                 $(".product-info").hide();  
  425.                 $(this).parents(".radius").css("border-right-width""0");  
  426.             }, function () {  
  427.                 $(".product-info").show();  
  428.                 $(this).parents(".radius").css("border-right-width""8px");  
  429.             });  
  430.               
  431.             // 工具类绑定事件 settings.toolBarHandler  
  432.             chatEl.find(".tool-bar td").children().click(this.toolBarHandler);  
  433.              chatEl.find("#send").click(function () {  
  434.                  var $chatMain = $(this).parents(".chat-main");  
  435.                 _opts.sendHandler($chatMain);  
  436.              });  
  437.              chatEl.find("#close").click(function () {  
  438.                  var $chatMain = $(this).parents(".chat-main");  
  439.                 $chatMain.hide(500);  
  440.              });  
  441.                
  442.              // 首先取消事件绑定,当一次性发多条消息的情况下会同时绑定多个相同事件  
  443.             $(".have-msg, .no-msg, .chat-main").unbind("click");  
  444.              $(".have-msg").bind("click"function () {  
  445.                 $(this).hide();  
  446.                 $(".no-msg").show();  
  447.                 $(".chat-main:hidden").show(150);  
  448.             });  
  449.               
  450.             $(".no-msg").click(function () {  
  451.                 $(".chat-main:hidden").each(function (i, item) {  
  452.                     var top = i * 10 + 50;  
  453.                     var left = i * 20 + 50;  
  454.                     $(this).show(500).css({top: top, left: left});  
  455.                 });  
  456.             });  
  457.               
  458.             $(".chat-main").click(function () {  
  459.                 $(".chat-main").css("z-index", 9999);  
  460.                 $(this).css({"z-index": 10000});  
  461.             });  
  462.                
  463.              $(this.sendMessageIFrame(userJID).document).keyup(function (event) {  
  464.                  var e = event || window.event;  
  465.                  var keyCode = e.which || e.keyCode;  
  466.                  if (keyCode == 13) {  
  467.                      var $chatMain = $("#" + $(this).find("body").attr("jid"));  
  468.                      _opts.sendHandler($chatMain);  
  469.                  }  
  470.              });  
  471.         },  
  472.           
  473.         // 建立新聊天窗口  
  474.         newWebIM: function (settings) {  
  475.             var chatUser = remote.userAddress(settings.receiver);  
  476.             var userJID = "u" + hex_md5(chatUser);  
  477.             _opts.initWebIM(userJID, chatUser);  
  478.               
  479.             $("#" + userJID).find(remote.receiver).val(chatUser);  
  480.             $("#" + userJID).show(220);  
  481.         },  
  482.           
  483.         // 远程发送消息时执行函数  
  484.         messageHandler: function (user, content) {  
  485.             var userName = user.split("@")[0];  
  486.             var tempUser = user;  
  487.             if (~tempUser.indexOf("/")) {  
  488.                 tempUser = tempUser.substr(0, tempUser.indexOf("/"));  
  489.             }  
  490.             var userJID = "u" + hex_md5(tempUser);  
  491.               
  492.             // ***初始webIM  
  493.             if (!$("#" + userJID).get(0)) {  
  494.                 // 初始IM面板;  
  495.                 _opts.initWebIM(userJID, user);  
  496.             }   
  497.             // 设置消息接受者的名称  
  498.             $("#" + userJID).find(remote.receiver).val(user);  
  499.               
  500.             if ($("#" + userJID).get(0)) {  
  501.                 // 消息提示  
  502.                 if ($("div[id='" + userJID + "']:hidden").get(0)) {  
  503.                     var haveMessage = $(".have-msg");  
  504.                     haveMessage.show();  
  505.                     $(".no-msg").hide();  
  506.                 }  
  507.                   
  508.                 _opts.messageTip("闪聊有了新消息,请查收!");  
  509.                 // 向chat接收信息区域写消息  
  510.                 remote.jsjac.chat.writeMessage(userJID, userName, content);  
  511.             }   
  512.         },  
  513.           
  514.         // 消息提示  
  515.         messageTip: function () {  
  516.             if (count % 2 == 0) {  
  517.                 window.focus();  
  518.                 document.title = "你来了新消息,请查收!";  
  519.             } else {  
  520.                 document.title = "";                  
  521.             }  
  522.             if (count > 4) {  
  523.                 document.title = "";      
  524.                 count = 0;              
  525.             } else {  
  526.                 window.setTimeout(_opts.messageTip, 1000);  
  527.                 count ++;  
  528.             }  
  529.         }  
  530.     };  
  531.       
  532.     // 初始化远程聊天程序相关方法  
  533.     var initRemoteIM = function (settings) {  
  534.           
  535.         // 初始化远程消息  
  536.         remote.jsjac.chat.init();  
  537.           
  538.         // 设置客户端写入信息方法  
  539.         remote.jsjac.chat.writeReceiveMessage = settings.writeReceiveMessage;  
  540.           
  541.         // 注册事件  
  542.         $(window).bind({  
  543.              unload: remote.jsjac.chat.unloadHandler,  
  544.              error: remote.jsjac.chat.errorHandler,  
  545.              beforeunload: remote.jsjac.chat.logout  
  546.         });  
  547.     }  
  548.       
  549.     $.extend({  
  550.         WebIM: function (opts) {  
  551.             opts = opts || {};  
  552.             // 覆盖默认配置  
  553.             defaultOptions = $.extend(defaultOptions, defaultOptions, opts);  
  554.             var settings = $.extend({}, defaultOptions, opts);      
  555.             initRemoteIM(settings);  
  556.               
  557.             settings.newWebIM(settings);  
  558.               
  559.             $.WebIM.settings = settings;  
  560.         }  
  561.     });  
  562.       
  563.     $.WebIM.settings = $.WebIM.settings || _opts;  
  564.     $.WebIM.initWebIM = _opts.initWebIM;  
  565.     $.WebIM.newWebIM = _opts.newWebIM;  
  566.     $.WebIM.messageHandler = _opts.messageHandler;  
  567.       
  568. })(jQuery);  

这里的方法基本上是聊天窗口上的应用,主要是本地聊天程序的js、HTML元素的操作。如字体、字体大小、颜色、表情、消息的发送等,不涉及到聊天消息发送的核心代码,其中有用到发送远程消息的方法。

remote.jsjac.chat.sendMessage(text, receiver); 这个是发送远程消息的方法,参数1是消息内容、参数2是消息的接收者

如果你有看到这篇文章http://www.cnblogs.com/hoojo/archive/2012/06/18/2553886.html 它是一个单纯的WebIM本地的聊天界面。

#p#

3、远程聊天JavaScript核心代码,它是和jsjac库关联的。

remote.jsjac.chat-2.0.js

  1. /**  
  2.  * IM chat jsjac remote message  
  3.  * @author: hoojo  
  4.  * @email: hoojo_@126.com  
  5.  * @blog http://hoojo.cnblogs.com & http://blog.csdn.net/IBM_hoojo  
  6.  * @createDate: 2012-5-24  
  7.  * @version 2.0  
  8.  * @requires jQuery v1.2.3 or later  
  9.  * Copyright (c) 2012 M. hoo  
  10.  **/ 
  11.    
  12. var remote = {  
  13.     debug: "info, error",  
  14.     chat: "body",  
  15.     receiver: "#to"// 接受者jquery expression  
  16.     console: {  
  17.         errorEL: function () {  
  18.             if ($(remote.chat).get(0)) {  
  19.                 return $(remote.chat).find("#error");  
  20.             } else {  
  21.                 return $("body").find("#error");  
  22.             }  
  23.         },  
  24.         infoEL: function () {  
  25.             if ($(remote.chat).get(0)) {  
  26.                 return $(remote.chat).find("#info");  
  27.             } else {  
  28.                 return $("body").find("#info");  
  29.             }  
  30.         },  
  31.         // debug info  
  32.         info: function (html) {  
  33.             if (~remote.debug.indexOf("info")) {  
  34.                 remote.console.infoEL().append(html);  
  35.                 remote.console.infoEL().get(0).lastChild.scrollIntoView();  
  36.             }  
  37.         },  
  38.         // debug error  
  39.         error: function (html) {  
  40.             if (~remote.debug.indexOf("error")) {  
  41.                 remote.console.errorEL().append(html);   
  42.             }  
  43.         },  
  44.         // clear info/debug console  
  45.         clear: function (s) {  
  46.             if ("debug" == s) {  
  47.                 remote.console.errorEL().html("");  
  48.             } else {  
  49.                 remote.console.infoEL().html("");  
  50.             }  
  51.         }  
  52.     },  
  53.       
  54.     userAddress: function (user) {  
  55.         if (user) {  
  56.             if (!~user.indexOf("@")) {  
  57.                 user += "@" + remote.jsjac.domain;// + "/" + remote.jsjac.resource;  
  58.             } else if (~user.indexOf("/")) {  
  59.                 user = user.substr(0, user.indexOf("/"));  
  60.             }  
  61.         }  
  62.         return user;  
  63.     },  
  64.     jsjac: {  
  65.         httpbase: window.contextPath + "/JHB/"//请求后台http-bind服务器url  
  66.         domain: window["serverDomin"], //"192.168.5.231", // 192.168.5.231 当前有效域名  
  67.         username: "",  
  68.         pass: "",  
  69.         timerval: 2000, // 设置请求超时  
  70.         resource: "WebIM"// 链接资源标识  
  71.         register: true // 是否注册  
  72.     }  
  73. };  
  74. remote.jsjac.chat = {  
  75.     writeReceiveMessage: function () {  
  76.     },  
  77.     setState: function () {  
  78.         var onlineStatus = new Object();  
  79.         onlineStatus["available"] = "在线";  
  80.         onlineStatus["chat"] = "欢迎聊天";  
  81.         onlineStatus["away"] = "离开";  
  82.         onlineStatus["xa"] = "不可用";  
  83.         onlineStatus["dnd"] = "请勿打扰";  
  84.         onlineStatus["invisible"] = "隐身";  
  85.         onlineStatus["unavailable"] = "离线";  
  86.         remote.jsjac.chat.state = onlineStatus;  
  87.         return onlineStatus;  
  88.     },  
  89.     state: null,  
  90.     init: function () {  
  91.         // Debugger plugin  
  92.         if (typeof (Debugger) == "function") {  
  93.             remote.dbger = new Debugger(2, remote.jsjac.resource);  
  94.             remote.dbger.start();  
  95.         } else {  
  96.             // if you're using firebug or safari, use this for debugging  
  97.             // oDbg = new JSJaCConsoleLogger(2);  
  98.             // comment in above and remove comments below if you don't need debugging  
  99.             remote.dbger = function () {  
  100.             };  
  101.             remote.dbger.log = function () {  
  102.             };  
  103.         }  
  104.           
  105.         try {   
  106.             // try to resume a session  
  107.             if (JSJaCCookie.read("btype").getValue() == "binding") {  
  108.                 remote.connection = new JSJaCHttpBindingConnection({ "oDbg": remote.dbger});  
  109.                 rdbgerjac.chat.setupEvent(remote.connection);  
  110.                 if (remote.connection.resume()) {  
  111.                     remote.console.clear("debug");  
  112.                 }  
  113.             }   
  114.         } catch (e) {  
  115.             remote.console.errorEL().html(e.name + ":" + e.message);  
  116.         } // reading cookie failed - never mind  
  117.           
  118.         remote.jsjac.chat.setState();  
  119.     },  
  120.     login: function (loginForm) {  
  121.         remote.console.clear("debug"); // reset  
  122.         try {  
  123.             // 链接参数  
  124.             var connectionConfig = remote.jsjac;  
  125.               
  126.             // Debugger console  
  127.             if (typeof (oDbg) != "undefined") {  
  128.                 connectionConfig.oDbg = oDbg;  
  129.             }  
  130.             var connection = new JSJaCHttpBindingConnection(connectionConfig);  
  131.             remote.connection = connection;  
  132.             // 安装(注册)Connection事件模型  
  133.             remote.jsjac.chat.setupEvent(connection);  
  134.       
  135.             // setup args for connect method  
  136.             if (loginForm) {  
  137.                 //connectionConfig = new Object();  
  138.                 //connectionConfig.domain = loginForm.domain.value;  
  139.                 connectionConfig.username = loginForm.userName.value;  
  140.                 connectionConfig.pass = loginForm.password.value;  
  141.                 connectionConfig.register = loginForm.register.checked;  
  142.             }  
  143.             // 连接服务器  
  144.             connection.connect(connectionConfig);  
  145.               
  146.             //remote.jsjac.chat.changeStatus("available", "online", 1, "chat");  
  147.         } catch (e) {  
  148.             remote.console.errorEL().html(e.toString());  
  149.         } finally {  
  150.             return false;  
  151.         }  
  152.     },  
  153.     // 改变用户状态  
  154.     changeStatus: function (type, status, priority, show) {  
  155.         type = type || "unavailable";  
  156.         status = status || "online";  
  157.         priority = priority || "1";  
  158.         show = show || "chat";  
  159.         var presence = new JSJaCPresence();  
  160.         presence.setType(type); // unavailable invisible  
  161.         if (remote.connection) {  
  162.             //remote.connection.send(presence);  
  163.         }  
  164.           
  165.         //presence = new JSJaCPresence();  
  166.         presence.setStatus(status); // online  
  167.         presence.setPriority(priority); // 1  
  168.         presence.setShow(show); // chat  
  169.         if (remote.connection) {  
  170.             remote.connection.send(presence);  
  171.         }  
  172.     },  
  173.       
  174.     // 为Connection注册事件  
  175.     setupEvent: function (con) {  
  176.         var remoteChat = remote.jsjac.chat;  
  177.         con.registerHandler('message', remoteChat.handleMessage);  
  178.         con.registerHandler('presence', remoteChat.handlePresence);  
  179.         con.registerHandler('iq', remoteChat.handleIQ);  
  180.         con.registerHandler('onconnect', remoteChat.handleConnected);  
  181.         con.registerHandler('onerror', remoteChat.handleError);  
  182.         con.registerHandler('status_changed', remoteChat.handleStatusChanged);  
  183.         con.registerHandler('ondisconnect', remoteChat.handleDisconnected);  
  184.       
  185.         con.registerIQGet('query', NS_VERSION, remoteChat.handleIqVersion);  
  186.         con.registerIQGet('query', NS_TIME, remoteChat.handleIqTime);  
  187.     },  
  188.     // 发送远程消息  
  189.     sendMessage: function (msg, to) {  
  190.         try {  
  191.             if (msg == "") {  
  192.                 return false;  
  193.             }  
  194.             var user = "";  
  195.             if (to) {  
  196.                 if (!~to.indexOf("@")) {  
  197.                     user += "@" + remote.jsjac.domain;  
  198.                     to += "/" + remote.jsjac.resource;  
  199.                 } else if (~to.indexOf("/")) {  
  200.                     user = to.substr(0, to.indexOf("/"));  
  201.                 }  
  202.             } else {  
  203.                 // 向chat接收信息区域写消息  
  204.                 if (remote.jsjac.chat.writeReceiveMessage) {  
  205.                     var html = "你没有指定发送者的名称";  
  206.                     alert(html);  
  207.                     //remote.jsjac.chat.writeReceiveMessage(receiverId, "server", html, false);  
  208.                 }  
  209.                 return false;  
  210.             }  
  211.             var userJID = "u" + hex_md5(user);  
  212.             $("#" + userJID).find(remote.receiver).val(to);  
  213.             // 构建jsjac的message对象  
  214.             var message = new JSJaCMessage();  
  215.             message.setTo(new JSJaCJID(to));  
  216.             message.setType("chat"); // 单独聊天,默认为广播模式  
  217.             message.setBody(msg);  
  218.             // 发送消息  
  219.             remote.connection.send(message);  
  220.             return false;  
  221.         } catch (e) {  
  222.             var html = "<div class='msg error''>Error: " + e.message + "</div>";  
  223.             remote.console.info(html);  
  224.             return false;  
  225.         }  
  226.     },  
  227.     // 退出、断开链接  
  228.     logout: function () {  
  229.         var presence = new JSJaCPresence();  
  230.         presence.setType("unavailable");  
  231.         if (remote.connection) {  
  232.             remote.connection.send(presence);  
  233.             remote.connection.disconnect();  
  234.         }  
  235.     },  
  236.     errorHandler: function (event) {  
  237.         var e = event || window.event;  
  238.         remote.console.errorEL().html(e);  
  239.         if (remote.connection && remote.connection.connected()) {  
  240.             remote.connection.disconnect();  
  241.         }  
  242.         return false;  
  243.     },  
  244.     unloadHandler: function () {  
  245.         var con = remote.connection;  
  246.         if (typeof con != "undefined" && con && con.connected()) {  
  247.               // save backend type  
  248.             if (con._hold) { // must be binding  
  249.                 (new JSJaCCookie("btype""binding")).write();  
  250.             }   
  251.             if (con.suspend) {  
  252.                 con.suspend();  
  253.             }  
  254.         }  
  255.     },  
  256.     writeMessage: function (userJID, userName, content) {  
  257.         // 向chat接收信息区域写消息  
  258.         if (remote.jsjac.chat.writeReceiveMessage && !!content) {  
  259.             remote.jsjac.chat.writeReceiveMessage(userJID, userName, content, false);  
  260.         }  
  261.     },  
  262.     // 重新连接服务器  
  263.     reconnection: function () {  
  264.         remote.jsjac.register = false;  
  265.         if (remote.connection.connected()) {  
  266.             remote.connection.disconnect();  
  267.         }  
  268.         remote.jsjac.chat.login();  
  269.     },  
  270.     /* ########################### Handler Event ############################# */ 
  271.       
  272.     handleIQ: function (aIQ) {  
  273.         var html = "<div class='msg'>IN (raw): " + aIQ.xml().htmlEnc() + "</div>";  
  274.         remote.console.info(html);  
  275.         remote.connection.send(aIQ.errorReply(ERR_FEATURE_NOT_IMPLEMENTED));  
  276.     },  
  277.     handleMessage: function (aJSJaCPacket) {  
  278.         var user = aJSJaCPacket.getFromJID().toString();  
  279.         //var userName = user.split("@")[0];  
  280.         //var userJID = "u" + hex_md5(user);  
  281.         var content = aJSJaCPacket.getBody();  
  282.         var html = "";  
  283.         html += "<div class=\"msg\"><b>消息来自 " + user + ":</b><br/>";  
  284.         html += content.htmlEnc() + "</div>";  
  285.         remote.console.info(html);  
  286.           
  287.         $.WebIM.messageHandler(user, content);  
  288.     },  
  289.     handlePresence: function (aJSJaCPacket) {  
  290.         var user = aJSJaCPacket.getFromJID();  
  291.         var userName = user.toString().split("@")[0];  
  292.         var html = "<div class=\"msg\">";  
  293.         if (!aJSJaCPacket.getType() && !aJSJaCPacket.getShow()) {  
  294.             html += "<b>" + userName + " 上线了.</b>";  
  295.         } else {  
  296.             html += "<b>" + userName + " 设置 presence 为: ";  
  297.             if (aJSJaCPacket.getType()) {  
  298.                 html += aJSJaCPacket.getType() + ".</b>";  
  299.             } else {  
  300.                 html += aJSJaCPacket.getShow() + ".</b>";  
  301.             }  
  302.             if (aJSJaCPacket.getStatus()) {  
  303.                 html += " (" + aJSJaCPacket.getStatus().htmlEnc() + ")";  
  304.             }  
  305.         }  
  306.         html += "</div>";  
  307.         remote.console.info(html);  
  308.           
  309.         // 向chat接收信息区域写消息  
  310.         remote.jsjac.chat.writeMessage("", userName, html);  
  311.     },  
  312.     handleError: function (event) {  
  313.         var e = event || window.event;  
  314.         var html = "An error occured:<br />"   
  315.             + ("Code: " + e.getAttribute("code")   
  316.             + "\nType: " + e.getAttribute("type")   
  317.             + "\nCondition: " + e.firstChild.nodeName).htmlEnc();  
  318.         remote.error(html);  
  319.           
  320.         var content = "";  
  321.         switch (e.getAttribute("code")) {  
  322.             case "401":  
  323.                 content = "登陆验证失败!";  
  324.                 break;  
  325.             // 当注册发现重复,表明该用户已经注册,那么直接进行登陆操作              
  326.             case "409":  
  327.                 //content = "注册失败!\n\n请换一个用户名!";  
  328.                 remote.jsjac.chat.reconnection();  
  329.                 break;  
  330.             case "503":  
  331.                 content = "无法连接到IM服务器,请检查相关配置!";  
  332.                 break;  
  333.             case "500":  
  334.                 var contents = "服务器内部错误!\n\n连接断开!<br/><a href='javascript: self.parent.remote.jsjac.chat.reconnection();'>重新连接</a>";  
  335.                 remote.jsjac.chat.writeMessage("""系统", contents);  
  336.                 break;  
  337.             default:  
  338.                 break;  
  339.         }  
  340.         if (content) {  
  341.             alert("WeIM: " + content);  
  342.         }  
  343.         if (remote.connection.connected()) {  
  344.             remote.connection.disconnect();  
  345.         }  
  346.     },  
  347.     // 状态变化触发事件  
  348.     handleStatusChanged: function (status) {  
  349.         remote.console.info("<div>当前用户状态: " + status + "</div>");  
  350.         remote.dbger.log("当前用户状态: " + status);  
  351.         if (status == "disconnecting") {  
  352.             var html = "<b style='color:red;'>你离线了!</b>";  
  353.             // 向chat接收信息区域写消息  
  354.             remote.jsjac.chat.writeMessage("""系统", html);  
  355.         }  
  356.     },  
  357.     // 建立链接触发事件方法  
  358.     handleConnected: function () {  
  359.         remote.console.clear("debug"); // reset  
  360.         remote.connection.send(new JSJaCPresence());  
  361.     },  
  362.     // 断开链接触发事件方法  
  363.     handleDisconnected: function () {  
  364.           
  365.     },  
  366.     handleIqVersion: function (iq) {  
  367.         remote.connection.send(iq.reply([  
  368.             iq.buildNode("name", remote.jsjac.resource),   
  369.             iq.buildNode("version", JSJaC.Version),   
  370.             iq.buildNode("os", navigator.userAgent)  
  371.         ]));  
  372.         return true;  
  373.     },  
  374.     handleIqTime: function (iq) {  
  375.         var now = new Date();  
  376.         remote.connection.send(iq.reply([  
  377.             iq.buildNode("display", now.toLocaleString()),   
  378.             iq.buildNode("utc", now.jabberDate()),   
  379.             iq.buildNode("tz", now.toLocaleString().substring(now.toLocaleString().lastIndexOf(" ") + 1))  
  380.         ]));  
  381.         return true;  
  382.     }  
  383. };  

个文件的代码就是用jsjac库和openfire建立通信的核心代码,代码中已经有注释,这里我就不再赘述。如果有什么不懂的可以给我留言。

#p#

4、消息区域、编辑器代码 send.message.editor-1.0.js

  1. /**  
  2.  * IM chat Send Message iframe editor  
  3.  * @author: hoojo  
  4.  * @email: hoojo_@126.com  
  5.  * @blog: http://blog.csdn.net/IBM_hoojo   
  6.  * @createDate: 2012-5-24  
  7.  * @version 1.0  
  8.  **/ 
  9. var agent = window.navigator.userAgent.toLowerCase();  
  10. var sendMessageEditor = {  
  11.    
  12.      // 获取iframe的window对象  
  13.     getWin: function () {  
  14.         return /*!/firefox/.test(agent)*/false ? sendMessageEditor.iframe.contentWindow : window.frames[sendMessageEditor.iframe.name];  
  15.     },  
  16.    
  17.     //获取iframe的document对象  
  18.     getDoc: function () {  
  19.         return !/firefox/.test(agent) ? sendMessageEditor.getWin().document : (sendMessageEditor.iframe.contentDocument || sendMessageEditor.getWin().document);  
  20.     },  
  21.    
  22.     init: function (userJID) {  
  23.         //打开document对象,向其写入初始化内容,以兼容FireFox  
  24.         var doc = sendMessageEditor.getDoc();  
  25.         doc.open();  
  26.         var html = [  
  27.             '<html>',   
  28.             '<head><style type="text/css">body{border:0;margin:0;padding:3px;height:98%;cursor:text;background-color:white;font-size:12px;font-family:Courier,serif,monospace;}</style></head>',  
  29.             '<body jid="', userJID, '"></body>',   
  30.             '</html>'].join("");  
  31.         doc.write(html);  
  32.         //打开document对象编辑模式  
  33.         doc.designMode = "on";  
  34.         doc.close();  
  35.     },  
  36.    
  37.      getContent: function () {  
  38.          var doc = sendMessageEditor.getDoc();  
  39.          //获取编辑器的body对象  
  40.         var body = doc.body || doc.documentElement;  
  41.         //获取编辑器的内容  
  42.         var content = body.innerHTML;  
  43.         //对内容进行处理,例如替换其中的某些特殊字符等等  
  44.         //Some code  
  45.           
  46.         //返回内容  
  47.         return content;  
  48.      },  
  49.        
  50.       //统一的执行命令方法  
  51.     execCmd: function (cmd, value, d){  
  52.         var doc = d || sendMessageEditor.getDoc();  
  53.         //doc对象的获取参照上面的代码  
  54.         //调用execCommand方法执行命令  
  55.         doc.execCommand(cmd, false, value === undefined ? null : value);  
  56.     },  
  57.       
  58.     getStyleState: function (cmd) {  
  59.         var doc = sendMessageEditor.getDoc();  
  60.         //doc对象的获取参考上面的对面  
  61.         //光标处是否是粗体  
  62.         var state = doc.queryCommandState(cmd);  
  63.         if(state){  
  64.           //改变按钮的样式  
  65.         }  
  66.         return state;  
  67.     },  
  68.     insertAtCursor: function (text, d, w){  
  69.         var doc = d || sendMessageEditor.getDoc();  
  70.         var win = w || sendMessageEditor.getWin();  
  71.         //win对象的获取参考上面的代码  
  72.         if (/msie/.test(agent)) {  
  73.             win.focus();  
  74.             var r = doc.selection.createRange();  
  75.             if (r) {  
  76.                 r.collapse(true);  
  77.                 r.pasteHTML(text);        
  78.             }  
  79.         } else if (/gecko/.test(agent) || /opera/.test(agent)) {  
  80.             win.focus();  
  81.             sendMessageEditor.execCmd('InsertHTML', text, doc);  
  82.         } else if (/safari/.test(agent)) {  
  83.             sendMessageEditor.execCmd('InsertText', text, doc);  
  84.         }  
  85.     }  
  86. };  
  87.    
  88.  

#p#

5、css样式 chat-2.0.css

  1. /**  
  2.  * function: im web chat css  
  3.  * author: hoojo  
  4.  * createDate: 2012-5-26 上午11:42:10  
  5.  */ 
  6. @CHARSET "UTF-8";  
  7.    
  8. *, body {  
  9.     font-family: Courier,serif,monospace;  
  10.     font-size12px;  
  11.     padding0;  
  12.     margin0;      
  13. }  
  14.    
  15. .chat-main {  
  16.     positionabsolute;  
  17.     /*right: 80px;*/ 
  18.     left: 50px;  
  19.     top: 20px;  
  20.     z-index999;  
  21.     displaynone;  
  22. }  
  23.    
  24. .chat-main .radius {  
  25.     background-colorwhite;  
  26.     border8px solid #94CADF;  
  27.     border-radius: 1em;  
  28. }  
  29.    
  30. #chat {  
  31.     positionrelative;  
  32.     /*left: 150px;*/ 
  33.     padding0;  
  34.     margin0;  
  35. }  
  36. #chat table {  
  37.     border-collapsecollapse;  
  38.     width435px;  
  39.     *width460px;  
  40.     /*width: 410px;*/ 
  41.     /*width: 320px;*/ 
  42. }  
  43.    
  44. #chat table .title {  
  45.     font-weightbold;  
  46.     colorgreen;  
  47.     padding3px;  
  48.     background-color#94CADF;  
  49. }  
  50.    
  51. /* 收缩条 */ 
  52. #chat table .split {  
  53.     background-color#94CADF;  
  54.     cursorpointer;  
  55. }  
  56.    
  57. /* ################## product info #################### */ 
  58. #chat table .product-info {  
  59.     width30%;  
  60.     /*display: none;*/ 
  61.     padding0;  
  62.     margin0;  
  63.     vertical-aligntop;  
  64. }  
  65.    
  66. #chat table .product-info ul {  
  67.     margin0;  
  68.     padding0;  
  69. }  
  70.    
  71. #chat table .product-info ul div.header {  
  72.     background-color#EBEFFE;  
  73.     line-height22px;  
  74.     font-size12px;  
  75.     colorblack;  
  76. }  
  77.    
  78. #chat table .product-info ul li {  
  79.     list-stylenone outside none;  
  80.     background-colorwhite;  
  81.     text-overflow: ellipsis;  
  82.     white-spacenowrap;  
  83.     overflowhidden;  
  84.     padding-left5px;  
  85.     line-height22px;  
  86.     font-size11px;  
  87.     color#6F6F6F;  
  88.     width140px;  
  89. }  
  90.    
  91. #chat table .product-info ul li.pic {  
  92.     height200px;  
  93.     padding0 5px 0 5px;  
  94.     border1px dashed #ccc;  
  95.     text-aligncenter;  
  96. }  
  97.    
  98. #chat table .product-info ul li.pic img {  
  99. }  
  100.    
  101. #chat table .product-info ul li.product-name {  
  102.     font-weightbold;  
  103.     colorblack;  
  104. }  
  105.    
  106. #chat table .product-info ul li.price span {  
  107.     font-family: Courier;  
  108.     font-size16px;  
  109.     font-weightbold;  
  110.     color#ED4E08;  
  111. }  
  112.    
  113. #chat table .product-info ul li.market-price s {  
  114.     colorblack;  
  115. }  
  116.    
  117. #chat table .product-info ul li a {  
  118.     floatright;  
  119. }  
  120.    
  121. #chat table .product-info ul li.info {  
  122.     displaynone;  
  123. }  
  124.    
  125. /*########### 接收消息区域 ############ */ 
  126. #chat table .receive-message {  
  127.     height250px;  
  128. }  
  129.    
  130. #chat table .send-message {  
  131.     width100%;  
  132.     /*height: auto;*/ 
  133. }  
  134.    
  135. #chat table td {  
  136.     /*border: 1px solid white;*/ 
  137. }  
  138.    
  139. #chat table .bottom-bar {  
  140.     background-color#94CADF;  
  141.     text-alignright;  
  142. }  
  143.    
  144. /* ############## 工具条 ################# start */ 
  145. #chat table .tool-bar {  
  146.     height25px;  
  147.     background-color#94CADF;  
  148. }  
  149.    
  150. #chat table .tool-bar select {  
  151.     floatleft;  
  152. }  
  153.    
  154. #chat table .tool-bar select.family {  
  155.     width45px;  
  156.     *width55px;  
  157. }  
  158.    
  159. #chat table .tool-bar div {  
  160.     width17px;  
  161.     height16px;  
  162.     floatleft;  
  163.     cursorpointer;  
  164.     margin-right2px;  
  165.     margin-top1px;  
  166.     *margin-top2px;  
  167.     backgroundtransparent url("../images/tb-sprite.gif"no-repeat scroll 0 0;  
  168. }  
  169.    
  170. #chat table .tool-bar .color {  
  171.     margin-left2px;  
  172.     background-position-159px 0;  
  173. }  
  174. #chat table .tool-bar .bold {  
  175.     /*background-position: 0 0;*/ 
  176. }  
  177. #chat table .tool-bar .italic {  
  178.     background-position-18px 0;  
  179. }  
  180. #chat table .tool-bar .underline {  
  181.     background-position-32px 0;  
  182. }  
  183. #chat table .tool-bar .face {  
  184.     margin2px 0 0 3px;  
  185.     background-imageurl("../images/facehappy.gif");  
  186. }  
  187. #chat table .tool-bar .history {  
  188.     background-imagenone;  
  189.     width60px;  
  190.     floatright;  
  191.     margin-top3px;  
  192.     font-size12px;  
  193.     displaynone;  
  194. }  
  195. /* ###### 表情 ###### */ 
  196. #chat #face {  
  197.     border1px solid black;  
  198.     width275px;  
  199.     *width277px;  
  200.     positionrelative;  
  201.     left: 8px;  
  202.     top: -370px;  
  203.     _top: -359px;  
  204.     z-index3;  
  205.     displaynone;  
  206. }  
  207.    
  208. #chat #face img {  
  209.     border1px solid #ccc;  
  210.     border-rightnone;  
  211.     border-bottomnone;   
  212.     cursorpointer;  
  213. }  
  214.    
  215. #send {  
  216.     width90px;  
  217.     height25px;  
  218. }  
  219. #close {  
  220.     width40px;  
  221.     height25px;  
  222. }  
  223.    
  224. .chat-message {  
  225.     positionabsolute;   
  226.     bottom: 0;   
  227.     left: 0;   
  228.     width100%;   
  229.     height25px;   
  230.     background-color#fcfcfc;  
  231. }  
  232.    
  233. .no-msg, .have-msg {  
  234.     cursorpointer;   
  235.     floatright;   
  236.     margin5px 5px 0 0;  
  237. }  

#p#

6、web.xml配置

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" 
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  4.     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   
  5. >  
  6.     <servlet>  
  7.         <servlet-name>Jabber HTTP Binding Servlet</servlet-name>  
  8.         <servlet-class>org.jabber.JabberHTTPBind.JHBServlet</servlet-class>  
  9.         <!--   
  10.         <init-param>  
  11.             <param-name>debug</param-name>  
  12.             <param-value>1</param-value>  
  13.         </init-param>  
  14.          -->  
  15.     </servlet>  
  16.    
  17.     <servlet-mapping>  
  18.         <servlet-name>Jabber HTTP Binding Servlet</servlet-name>  
  19.         <url-pattern>/JHB/</url-pattern>  
  20.     </servlet-mapping>  
  21.    
  22.     <welcome-file-list>  
  23.         <welcome-file>index.jsp</welcome-file>  
  24.     </welcome-file-list>  
  25. </web-app>  

至此,这个应用的全部代码已经贴出来,如果你按照我这边的结构形式应该是可以完成这个聊天应用的。如果你有什么问题或想法,欢迎你给我留言或评论!

原文链接:http://www.blogjava.net/hoojo/archive/2012/08/13/385360.html

作者博客:http://hoojo.cnblogs.com/

【编辑推荐】

责任编辑:张伟 来源: hoojo的博客
相关推荐

2023-12-07 19:48:42

2009-03-25 08:52:01

MySpaceWebIM

2014-04-01 11:02:00

Node.jsWeb Socket聊天程序

2023-11-28 08:49:01

短轮询WebSocket长轮询

2020-12-14 15:59:10

PythonWechaty机器人

2023-10-30 17:48:30

架构设计通信

2015-11-05 18:30:38

腾讯云

2009-12-07 11:19:39

WCF聊天

2020-09-30 18:00:48

JavaSpring BootIM

2010-03-19 14:42:29

Java Socket

2011-08-03 17:08:43

iPhone Sqlite 时间

2010-07-19 14:08:15

2023-01-05 09:17:58

2023-01-13 00:02:41

2010-01-22 21:10:54

光纤USB远程通信

2010-11-23 09:26:57

2011-02-25 10:43:45

2009-06-22 10:59:00

J2EE web se

2010-03-17 08:27:58

HTML 5 Web Web通信
点赞
收藏

51CTO技术栈公众号