JavaScript/jQuery、HTML、CSS 构建 Web IM 远程及时聊天通信程序

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

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

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

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


用户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的聊天画面,双方在进行互聊……


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


收缩详情


聊天界面部分截图

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



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


登陆失败


只有connecting,就没有下文了


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


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


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

         

这里已经贴出了所有的源代码了,如果你非常的需要源代码(但我希望你能自己创建一个工程去复制源代码,这是我希望看到的),那么你可以通过以下方式联系我

Email:hoojo_@126.com

Blog:http://blog.csdn.net/IBM_hoojo

http://hoojo.cnblogs.com/

http://hoojo.blogjava.net

注:我不会保证在第一时间给你代码,但我会在空闲的时间给你发送源码

 

导读

如果你对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

 

开发依赖库


jdk1.4+

serializer.jar
xalan.jar
jhb-1.0.jar

log4j-1.2.16.jar

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

 

JavaScript lib


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

 

工程目录结构


 

二、核心代码演示

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

<%@ page language="java" pageEncoding="UTF-8" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>WebIM Chat</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="author" content="hoojo">
    <meta http-equiv="email" content="hoojo_@126.com">
    <meta http-equiv="blog" content="http://blog.csdn.net/IBM_hoojo">
    <meta http-equiv="blog" content="http://hoojo.cnblogs.com">
    <link rel="stylesheet" type="text/css" href="css/chat-2.0.css" />
    <script type="text/javascript">
        window.contextPath = "<%=path%>";
        window["serverDomin"] = "192.168.8.22";
    </script>
    <script type="text/javascript" src="jslib/jquery-1.7.1.min.js"></script>
    <script type="text/javascript" src="jslib/jsjac.js"></script>
    <!-- script type="text/javascript" src="debugger/Debugger.js"></script-->
    <script type="text/javascript" src="jslib/send.message.editor-1.0.js"></script>
    <script type="text/javascript" src="jslib/jquery.easydrag.js"></script>
    <script type="text/javascript" src="jslib/remote.jsjac.chat-2.0.js"></script>
    <script type="text/javascript" src="jslib/local.chat-2.0.js"></script>
    <script type="text/javascript">
        $(function () {
            
            $("#login").click(function () {
                var userName = $(":text[name='userName']").val();
                var receiver = $("*[name='to']").val();
                // 建立一个聊天窗口应用,并设置发送者和消息接收者
                $.WebIM({
                    sender: userName,
                    receiver: receiver
                });
                // 登陆到openfire服务器
                 remote.jsjac.chat.login(document.userForm);
                 $("label").text(userName);
                 $("form").hide();
                 $("#newConn").show();
            });
            
            $("#logout").click(function () {
                 // 退出openfire登陆,断开链接
                 remote.jsjac.chat.logout();
                 $("form").show();
                 $("#newConn").hide();
                 $("#chat").hide(800);
            });
            
            $("#newSession").click(function () {
                var receiver = $("#sendTo").val();
                // 建立一个新聊天窗口,并设置消息接收者(发送给谁?)
                $.WebIM.newWebIM({
                    receiver: receiver
                });
            });
        });
    </script>
  </head>
  
  <body>
    <!-- 登陆表单 -->
    <form name="userForm" style="background-color: #fcfcfc; width: 100%;">
        userName:<input type="text" name="userName" value="boy"/>
        password:<input type="password" name="password" value="boy"/>
        
        register: <input type="checkbox" name="register"/>
        sendTo: <input type="text" id="to" name="to" value="hoojo" width="10"/>
        <input type="button" value="Login" id="login"/> 
    </form>
    <!-- 新窗口聊天 -->
    <div id="newConn" style="display: none; background-color: #fcfcfc; width: 100%;">
           User:<label></label>
           sendTo: <input type="text" id="sendTo" value="hoojo" width="10"/>
           <input type="button" value="new Chat" id="newSession"/> 
           <input type="button" value="Logout" id="logout"/>
    </div>
    <!-- 日志信息 -->
    <div id="error" style="display: ; background-color: red;"></div>
    <div id="info" style="display: ; background-color: #999999;"></div>
    <!-- 聊天来消息提示 -->
    <div class="chat-message">
        <img src="images/write_icon.png" class="no-msg"/>
        <img src="images/write_icon.gif" class="have-msg" style="display: none;"/>
    </div>
  </body>
</html>

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

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

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

$.WebIM({
    sender: userName,
    receiver: receiver
});
 
$.WebIM.newWebIM({
    receiver: receiver
});

 

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

参数如下:

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

 

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

 

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

/***
 * jquery local chat
 * @version v2.0 
 * @createDate -- 2012-5-28
 * @author hoojo
 * @email hoojo_@126.com
 * @blog http://hoojo.cnblogs.com & http://blog.csdn.net/IBM_hoojo
 * @requires jQuery v1.2.3 or later, send.message.editor-1.0.js
 * Copyright (c) 2012 M. hoo
 **/
 
;(function ($) {

	if (/1\.(0|1|2)\.(0|1|2)/.test($.fn.jquery) || /^1.1/.test($.fn.jquery)) {
		alert('WebIM requires jQuery v1.2.3 or later!  You are using v' + $.fn.jquery);
		return;
	}
	
	var faceTimed, count = 0;
	
	var _opts = defaultOptions = {
		version: 2.0,
		chat: "#chat",
		chatEl: function () {
			var $chat = _opts.chat;
			if ((typeof _opts.chat) == "string") {
				$chat = $(_opts.chat);
			} else if ((typeof _opts.chat) == "object") {
				if (!$chat.get(0)) {
					$chat = $($chat);
				}
			} 
			return $chat;
		},
		sendMessageIFrame: function (receiverId) {
			return $("iframe[name='sendMessage" + receiverId + "']").get(0).contentWindow;
		},
		receiveMessageDoc: function (receiverId) {
			receiverId = receiverId || "";
			var docs = [];
			$.each($("iframe[name^='receiveMessage" + receiverId + "']"), function () {
				docs.push($(this.contentWindow.document));
			});
			return docs;
			//return $($("iframe[name^='receiveMessage" + receiverId + "']").get(0).contentWindow.document);
		},
		sender: "", // 发送者
		receiver: "", // 接收者
		setTitle: function (chatEl) {
			var receiver = this.getReceiver(chatEl);
			chatEl.find(".title").html("和" + receiver + "聊天对话中");
		},
		getReceiver: function (chatEl) {
			var receiver = chatEl.attr("receiver");
			if (~receiver.indexOf("@")) {
				receiver = receiver.split("@")[0];
			}
			return receiver;
		},
		
		// 接收消息iframe样式
		receiveStyle: [
			'<html>',
				'<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;}',
				'.msg{margin-left: 1em;}p{margin:0;padding:0;}.me{color: blue;}.you{color:green;}',
				'</style></head>',
				'<body></body>',
			'</html>'
		].join(""),
		writeReceiveStyle: function (receiverId) {
			this.receiveMessageDoc(receiverId)[0].get(0).write(this.receiveStyle);
		},
		
		datetimeFormat: function (v) {
			if (~~v < 10) {
				return "0" + v;
			}
			return v;
		},
		getDatetime: function () {
			// 设置当前发送日前
			var date = new Date();
			var datetime = date.getFullYear() + "-" + date.getMonth() + "-" + date.getDate();
			datetime = " " + _opts.datetimeFormat(date.getHours()) 
						+ ":" + _opts.datetimeFormat(date.getMinutes()) 
						+ ":" + _opts.datetimeFormat(date.getSeconds());
			return datetime;
		},
		
		/***
		 * 发送消息的格式模板					
		 * flag = true 表示当前user是自己,否则就是对方
		 **/ 
		receiveMessageTpl: function (userName, styleTpl, content, flag) {
			var userCls = flag ? "me" : "you";
			if (styleTpl && flag) {
				content = [ "<span style='", styleTpl, "'>", content, "</span>" ].join("");
			}
			return [
				'<p class="', userCls, '">', _opts.getDatetime(), '  ', userName, ':</p>',
				'<p class="msg">', content, '</p>'
			].join("");
		},
		
		// 工具类按钮触发事件返回html模板
		sendMessageStyle: {
		 	cssStyle: {
		 		bold: "font-weight: bold;",
		 		underline: "text-decoration: underline;",
		 		italic: "font-style: oblique;"
		 	},
		 	setStyle: function (style, val) {
		 		if (val) {
		 			_opts.sendMessageStyle[style] = val;
		 		} else {
			 		var styleVal = _opts.sendMessageStyle[style];
			 		if (styleVal === undefined || !styleVal) {
			 			_opts.sendMessageStyle[style] = true;
			 		} else {
			 			_opts.sendMessageStyle[style] = false;
			 		}
		 		}
		 	},
		 	getStyleTpl: function () {
		 		var tpl = "";
		 		$.each(_opts.sendMessageStyle, function (style, item) {
		 			//alert(style + "#" + item + "#" + (typeof item));
		 			if (item === true) {
	 					tpl += _opts.sendMessageStyle.cssStyle[style];
		 			} else if ((typeof item) === "string") {
		 				//alert(style + "-------------" + sendMessageStyle[style]);
	 					tpl += style + ":" + item + ";";
		 			}
		 		});
		 		return tpl;
		 	}
		},
		// 向接收消息iframe区域写消息
		writeReceiveMessage: function (receiverId, userName, content, flag) {
			if (content) {
				// 发送消息的样式
				var styleTpl = _opts.sendMessageStyle.getStyleTpl();
				var receiveMessageDoc = _opts.receiveMessageDoc(receiverId);
				$.each(receiveMessageDoc, function () {
					var $body = this.find("body");
					// 向接收信息区域写入发送的数据
					$body.append(_opts.receiveMessageTpl(userName, styleTpl, content, flag));
					// 滚动条滚到底部
					this.scrollTop(this.height());
				});
			}
		},
		// 发送消息
		sendHandler: function ($chatMain) {
			var doc = $chatMain.find("iframe[name^='sendMessage']").get(0).contentWindow.document;
			
			var content = doc.body.innerHTML;
			content = $.trim(content);
			content = content.replace(new RegExp("<br>", "gm"), "");
			// 获取即将发送的内容
			if (content) {
				var sender = $chatMain.attr("sender");
				var receiverId = $chatMain.attr("id");
				// 接收区域写消息
				_opts.writeReceiveMessage(receiverId, sender, content, true);
				
				//############# XXX
				var receiver = $chatMain.find("#to").val();
				//var receiver = $chatMain.attr("receiver");
				// 判断是否是手机端会话,如果是就发送纯text,否则就发送html代码
				var flag = _opts.isMobileClient(receiver);
				if (flag) {
					var text = $(doc.body).text();
					text = $.trim(text);
					if (text) {
						// 远程发送消息
						remote.jsjac.chat.sendMessage(text, receiver);
					}
				} else { // 非手机端通信 可以发送html代码
					var styleTpl = _opts.sendMessageStyle.getStyleTpl();
					content = [ "<span style='", styleTpl, "'>", content, "</span>" ].join("");
					remote.jsjac.chat.sendMessage(content, receiver);
				}
				
				// 清空发送区域
				$(doc).find("body").html("");
			}
		}, 
		
		faceImagePath: "images/emotions/",
		faceElTpl: function (i) {
			return [
				"<img src='",
				this.faceImagePath,
				(i - 1),
				"fixed.bmp' gif='",
				this.faceImagePath,
				(i - 1),
				".gif'/>"
			].join("");
		},
		// 创建表情html elements
		createFaceElement: function ($chat) {
			var faces = [];
			for (var i = 1; i < 100; i++) {
		 		faces.push(this.faceElTpl(i));
			 	if (i % 11 == 0) {
			 		faces.push("<br/>");
			 	} 
			}
			$chat.find("#face").html(faces.join(""));
			this.faceHandler($chat);
		},
		// 插入表情
		faceHandler: function ($chat) {
			$chat.find("#face img").click(function () {
			 	$chat.find("#face").hide(150);
			 	var imgEL = "<img src='" + $(this).attr("gif") + "'/>";
			 	var $chatMain = $(this).parents(".chat-main");
			 	var win = $chatMain.find("iframe[name^='sendMessage']").get(0).contentWindow;
			 	var doc = win.document;
			 	sendMessageEditor.insertAtCursor(imgEL, doc, win);
			});
			// 表情隐藏
			$chat.find("#face, #face img").mouseover(function () {
				window.clearTimeout(faceTimed);
			}).mouseout(function () {
				window.clearTimeout(faceTimed);
				faceTimed = window.setTimeout(function () {
					$chat.find("#face").hide(150);
				}, 700);
			});
		},
		/***
		 * 发送消息工具栏按钮事件方法
		 **/
		toolBarHandler: function () {
			var $chat = $(this).parents(".chat-main");
			var targetCls = $(this).attr("class");
			if (targetCls == "face") {
				$chat.find("#face").show(150);
				window.clearTimeout(faceTimed);
				faceTimed = window.setTimeout(function () {
					$chat.find("#face").hide(150);
				}, 1000);
			} else if (this.tagName == "DIV") {
				_opts.sendMessageStyle.setStyle(targetCls);
			} else if (this.tagName == "SELECT") {
				_opts.sendMessageStyle.setStyle($(this).attr("name"), $(this).val());
				if ($(this).attr("name") == "color") {
					$(this).css("background-color", $(this).val());
				}
			}
			
			// 设置sendMessage iframe的style css
			_opts.writeSendStyle();
		},
		// 设置sendMessage iframe的style css
		writeSendStyle: function () {
			var styleTpl = _opts.sendMessageStyle.getStyleTpl();
			var styleEL = ['<style type="text/css">body{', styleTpl,'}</style>'].join("");
			
			$("body").find("iframe[name^='sendMessage']").each(function () {
				var $head = $(this.contentWindow.document).find("head");
				if ($head.find("style").size() > 1) {
					$head.find("style:gt(0)").remove();
				}
				if (styleTpl) {
					$head.append(styleEL);
				}
			});
		},				
		
		isMobileClient: function (receiver) {
			var moblieClients = ["iphone", "ipad", "ipod", "wp7", "android", "blackberry", "Spark", "warning", "symbian"];
			var flag = false;
			for (var i in moblieClients) {
				if (~receiver.indexOf(moblieClients[i])) {
					return true;
				}
			}
			return false;
		},

		// 聊天界面html元素
		chatLayoutTemplate: function (userJID, sender, receiver, product, flag) {
			var display = "";
			if (flag) {
				display = "style='display: none;'";
			}
			return [
			'<div class="chat-main" id="', userJID,
				'" sender="', sender, '" receiver="', receiver, '">',
				    
			    '<div id="chat"><div class="radius">',
				    '<table>',
				    	'<tr>',
				    		'<td colspan="3" class="title"></td>',
				    	'</tr>',
				    	'<tr>',
				    		'<td class="receive-message">',
				    			'<iframe name="receiveMessage', userJID,'" frameborder="0" width="100%" height="100%"></iframe>',
				    		'</td>',
				    		'<td rowspan="4" class="split" ', display, '> </td>',
				    		'<td rowspan="4" class="product-info" ', display, '>',
				    			'<ul>',
				    				'<div class="header"> 商品详情</div>',
				    				'<li class="pic">',
				    				'<img src="', product.pic, '"/></li>',
				    				'<li class="product-name">', product.name, '</li>',
				    				'<li class="price">团购价:<span>', product.price, '</span>元</li>',
				    				'<li class="market-price">市场价:<s><i>', product.marketPrice, '</i></s>元</li>',
				    				'<li>快递公司:', product.deliverOrgs, '</li>',
				    				'<li>仓库:', product.wareHouses, '</li>',
				    				product.skuAttrs,
				    			'</ul>',
				    		'</td>',
				    	'</tr>',
				    	'<tr class="tool-bar">',
				    		'<td>',
				    			'<select name="font-family" class="family">',
				    				'<option>宋体</option>',
				    				'<option>黑体</option>',
				    				'<option>幼圆</option>',
				    				'<option>华文行楷</option>',
				    				'<option>华文楷体</option>',
				    				'<option>华文楷体</option>',
				    				'<option>华文彩云</option>',
				    				'<option>华文隶书</option>',
				    				'<option>微软雅黑</option>',
				    				'<option>Fixedsys</option>',
				    			'</select>',
				    			
				    			'<select name="font-size">',
				    				'<option value="12px">大小</option>',
				    				'<option value="10px">10</option>',
				    				'<option value="12px">12</option>',
				    				'<option value="14px">14</option>',
				    				'<option value="16px">16</option>',
				    				'<option value="18px">18</option>',
				    				'<option value="20px">20</option>',
				    				'<option value="24px">24</option>',
				    				'<option value="28px">28</option>',
				    				'<option value="36px">36</option>',
				    				'<option value="42px">42</option>',
				    				'<option value="52px">52</option>',
				    			'</select>',
				    			'<select name="color">',
									'<option value="" selected="selected">颜色</option>',
									'<option value="#000000" style="background-color:#000000"></option>',
									'<option value="#FFFFFF" style="background-color:#FFFFFF"></option>',
									'<option value="#008000" style="background-color:#008000"></option>',
									'<option value="#800000" style="background-color:#800000"></option>',
									'<option value="#808000" style="background-color:#808000"></option>',
									'<option value="#000080" style="background-color:#000080"></option>',
									'<option value="#800080" style="background-color:#800080"></option>',
									'<option value="#808080" style="background-color:#808080"></option>',
									'<option value="#FFFF00" style="background-color:#FFFF00"></option>',
									'<option value="#00FF00" style="background-color:#00FF00"></option>',
									'<option value="#00FFFF" style="background-color:#00FFFF"></option>',
									'<option value="#FF00FF" style="background-color:#FF00FF"></option>',
									'<option value="#FF0000" style="background-color:#FF0000"></option>',
									'<option value="#0000FF" style="background-color:#0000FF"></option>',
									'<option value="#008080" style="background-color:#008080"></option>',
								'</select>',
				    			'<div class="bold"></div>',
				    			'<div class="underline"></div>',
				    			'<div class="italic"></div>',
				    			'<div class="face"></div>',
				    			'<div class="history">消息记录</div>',
							'</td>',
				    	'</tr>',
				    	'<tr class="send-message">',
				    		'<td>',
				    			'<iframe name="sendMessage', userJID,'" width="100%" height="80px" frameborder="0"></iframe>',
							'</td>',
				    	'</tr>',
				    	'<tr class="bottom-bar">',
				    		'<td><input type="text" id="to" name="to" value="hoojo" style="width: 100px;"/><input type="button" value="关闭" id="close"/> ',
				    		'<input type="button" value="发送(Enter)" id="send"/> </td>',
				    	'</tr>',
				    '</table></div>',
				    '<div id="face"></div>',
			    '</div>',
			'</div>'
			].join("");
		},
		
		initWebIM: function (userJID, receiver) {
			var product = {
				name: "小玩熊",
				pic: "http://avatar.csdn.net/9/7/A/2_ibm_hoojo.jpg",
				price: "198.00",
				marketPrice: "899.90",
				deliverOrgs: "EMS",
				wareHouses: "A库",
				skuAttrs: ""
			};
			var chatEl = $(_opts.chatLayoutTemplate(userJID, _opts.sender, receiver, product));
			$("body").append(chatEl);						
			
			// 拖拽
			$("#" + userJID).easydrag();
			// 初始化sendMessageEditor相关信息
			sendMessageEditor.iframe = this.sendMessageIFrame(userJID);
			sendMessageEditor.init(userJID);	
			
			_opts.setTitle(chatEl);
			_opts.writeReceiveStyle(userJID);
			_opts.writeSendStyle();
			_opts.createFaceElement(chatEl);
			
			// 查看更多详情
			chatEl.find(".more").click(function () {
				var $ul = $(this).parents("ul");
				$ul.find(".more").toggle();
				$ul.find(".info").toggle();
				$ul.find(".pic").toggle();
			});
			
			// 收缩详情
			chatEl.find(".split").toggle(function () {
				$(".product-info").hide();
				$(this).parents(".radius").css("border-right-width", "0");
			}, function () {
				$(".product-info").show();
				$(this).parents(".radius").css("border-right-width", "8px");
			});
			
			// 工具类绑定事件 settings.toolBarHandler
			chatEl.find(".tool-bar td").children().click(this.toolBarHandler);
		 	chatEl.find("#send").click(function () {
		 		var $chatMain = $(this).parents(".chat-main");
				_opts.sendHandler($chatMain);
		 	});
		 	chatEl.find("#close").click(function () {
		 		var $chatMain = $(this).parents(".chat-main");
				$chatMain.hide(500);
		 	});
		 	
		 	// 首先取消事件绑定,当一次性发多条消息的情况下会同时绑定多个相同事件
			$(".have-msg, .no-msg, .chat-main").unbind("click");
		 	$(".have-msg").bind("click", function () {
				$(this).hide();
				$(".no-msg").show();
				$(".chat-main:hidden").show(150);
			});
			
			$(".no-msg").click(function () {
				$(".chat-main:hidden").each(function (i, item) {
					var top = i * 10 + 50;
					var left = i * 20 + 50;
					$(this).show(500).css({top: top, left: left});
				});
			});
			
			$(".chat-main").click(function () {
				$(".chat-main").css("z-index", 9999);
				$(this).css({"z-index": 10000});
			});
		 	
		 	$(this.sendMessageIFrame(userJID).document).keyup(function (event) {
		 		var e = event || window.event;
		 		var keyCode = e.which || e.keyCode;
		 		if (keyCode == 13) {
		 			var $chatMain = $("#" + $(this).find("body").attr("jid"));
		 			_opts.sendHandler($chatMain);
		 		}
		 	});
		},
		
		// 建立新聊天窗口
		newWebIM: function (settings) {
			var chatUser = remote.userAddress(settings.receiver);
			var userJID = "u" + hex_md5(chatUser);
			_opts.initWebIM(userJID, chatUser);
			
			$("#" + userJID).find(remote.receiver).val(chatUser);
			$("#" + userJID).show(220);
		},
		
		// 远程发送消息时执行函数
		messageHandler: function (user, content) {
			var userName = user.split("@")[0];
			var tempUser = user;
			if (~tempUser.indexOf("/")) {
				tempUser = tempUser.substr(0, tempUser.indexOf("/"));
			}
			var userJID = "u" + hex_md5(tempUser);
			
			// 首次初始webIM
			if (!$("#" + userJID).get(0)) {
				// 初始IM面板;
				_opts.initWebIM(userJID, user);
			} 
			// 设置消息接受者的名称
			$("#" + userJID).find(remote.receiver).val(user);
			
			if ($("#" + userJID).get(0)) {
				// 消息提示
				if ($("div[id='" + userJID + "']:hidden").get(0)) {
					var haveMessage = $(".have-msg");
					haveMessage.show();
					$(".no-msg").hide();
				}
				
				_opts.messageTip("闪聊有了新消息,请查收!");
				// 向chat接收信息区域写消息
				remote.jsjac.chat.writeMessage(userJID, userName, content);
			} 
		},
		
		// 消息提示
		messageTip: function () {
			if (count % 2 == 0) {
				window.focus();
				document.title = "你来了新消息,请查收!";
			} else {
				document.title = "";				
			}
			if (count > 4) {
				document.title = "";	
				count = 0;			
			} else {
				window.setTimeout(_opts.messageTip, 1000);
				count ++;
			}
		}
	};
	
	// 初始化远程聊天程序相关方法
	var initRemoteIM = function (settings) {
		
		// 初始化远程消息
		remote.jsjac.chat.init();
		
		// 设置客户端写入信息方法
		remote.jsjac.chat.writeReceiveMessage = settings.writeReceiveMessage;
		
		// 注册事件
		$(window).bind({
		 	unload: remote.jsjac.chat.unloadHandler,
		 	error: remote.jsjac.chat.errorHandler,
		 	beforeunload: remote.jsjac.chat.logout
		});
	}
	
	$.extend({
		WebIM: function (opts) {
			opts = opts || {};
			// 覆盖默认配置
			defaultOptions = $.extend(defaultOptions, defaultOptions, opts);
			var settings = $.extend({}, defaultOptions, opts);	
			initRemoteIM(settings);
			
			settings.newWebIM(settings);
			
			$.WebIM.settings = settings;
		}
	});
	
	$.WebIM.settings = $.WebIM.settings || _opts;
	$.WebIM.initWebIM = _opts.initWebIM;
	$.WebIM.newWebIM = _opts.newWebIM;
	$.WebIM.messageHandler = _opts.messageHandler;
	
})(jQuery);

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

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

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

 

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

remote.jsjac.chat-2.0.js

/**
 * IM chat jsjac remote message
 * @author: hoojo
 * @email: hoojo_@126.com
 * @blog http://hoojo.cnblogs.com & http://blog.csdn.net/IBM_hoojo
 * @createDate: 2012-5-24
 * @version 2.0
 * @requires jQuery v1.2.3 or later
 * Copyright (c) 2012 M. hoo
 **/
 
var remote = {
	debug: "info, error",
	chat: "body",
	receiver: "#to", // 接受者jquery expression
	console: {
		errorEL: function () {
			if ($(remote.chat).get(0)) {
				return $(remote.chat).find("#error");
			} else {
				return $("body").find("#error");
			}
		},
		infoEL: function () {
			if ($(remote.chat).get(0)) {
				return $(remote.chat).find("#info");
			} else {
				return $("body").find("#info");
			}
		},
		// debug info
		info: function (html) {
			if (~remote.debug.indexOf("info")) {
				remote.console.infoEL().append(html);
				remote.console.infoEL().get(0).lastChild.scrollIntoView();
			}
		},
		// debug error
		error: function (html) {
			if (~remote.debug.indexOf("error")) {
				remote.console.errorEL().append(html); 
			}
		},
		// clear info/debug console
		clear: function (s) {
			if ("debug" == s) {
				remote.console.errorEL().html("");
			} else {
				remote.console.infoEL().html("");
			}
		}
	},
	
	userAddress: function (user) {
		if (user) {
			if (!~user.indexOf("@")) {
				user += "@" + remote.jsjac.domain;// + "/" + remote.jsjac.resource;
			} else if (~user.indexOf("/")) {
				user = user.substr(0, user.indexOf("/"));
			}
		}
		return user;
	},
	jsjac: {
		httpbase: window.contextPath + "/JHB/", //请求后台http-bind服务器url
		domain: window["serverDomin"], //"192.168.5.231", // 192.168.5.231 当前有效域名
		username: "",
		pass: "",
		timerval: 2000, // 设置请求超时
		resource: "WebIM", // 链接资源标识
		register: true // 是否注册
	}
};
remote.jsjac.chat = {
	writeReceiveMessage: function () {
	},
	setState: function () {
		var onlineStatus = new Object();
		onlineStatus["available"] = "在线";
		onlineStatus["chat"] = "欢迎聊天";
		onlineStatus["away"] = "离开";
		onlineStatus["xa"] = "不可用";
		onlineStatus["dnd"] = "请勿打扰";
		onlineStatus["invisible"] = "隐身";
		onlineStatus["unavailable"] = "离线";
		remote.jsjac.chat.state = onlineStatus;
		return onlineStatus;
	},
	state: null,
	init: function () {
		// Debugger plugin
		if (typeof (Debugger) == "function") {
			remote.dbger = new Debugger(2, remote.jsjac.resource);
			remote.dbger.start();
		} else {
	    	// if you're using firebug or safari, use this for debugging
	    	// oDbg = new JSJaCConsoleLogger(2);
	    	// comment in above and remove comments below if you don't need debugging
			remote.dbger = function () {
			};
			remote.dbger.log = function () {
			};
		}
		
		try { 
			// try to resume a session
			if (JSJaCCookie.read("btype").getValue() == "binding") {
				remote.connection = new JSJaCHttpBindingConnection({ "oDbg": remote.dbger});
				rdbgerjac.chat.setupEvent(remote.connection);
				if (remote.connection.resume()) {
					remote.console.clear("debug");
				}
			} 
		} catch (e) {
			remote.console.errorEL().html(e.name + ":" + e.message);
		} // reading cookie failed - never mind
		
		remote.jsjac.chat.setState();
	},
	login: function (loginForm) {
		remote.console.clear("debug"); // reset
		try {
			// 链接参数
			var connectionConfig = remote.jsjac;
			
			// Debugger console
			if (typeof (oDbg) != "undefined") {
				connectionConfig.oDbg = oDbg;
			}
			var connection = new JSJaCHttpBindingConnection(connectionConfig);
			remote.connection = connection;
			// 安装(注册)Connection事件模型
			remote.jsjac.chat.setupEvent(connection);
	
	    	// setup args for connect method
			if (loginForm) {
				//connectionConfig = new Object();
				//connectionConfig.domain = loginForm.domain.value;
				connectionConfig.username = loginForm.userName.value;
				connectionConfig.pass = loginForm.password.value;
				connectionConfig.register = loginForm.register.checked;
			}
			// 连接服务器
			connection.connect(connectionConfig);
			
			//remote.jsjac.chat.changeStatus("available", "online", 1, "chat");
		} catch (e) {
			remote.console.errorEL().html(e.toString());
		} finally {
			return false;
		}
	},
	// 改变用户状态
	changeStatus: function (type, status, priority, show) {
		type = type || "unavailable";
		status = status || "online";
		priority = priority || "1";
		show = show || "chat";
		var presence = new JSJaCPresence();
		presence.setType(type); // unavailable invisible
		if (remote.connection) {
			//remote.connection.send(presence);
		}
		
		//presence = new JSJaCPresence();
		presence.setStatus(status); // online
		presence.setPriority(priority); // 1
		presence.setShow(show); // chat
		if (remote.connection) {
			remote.connection.send(presence);
		}
	},
	
	// 为Connection注册事件
	setupEvent: function (con) {
		var remoteChat = remote.jsjac.chat;
	    con.registerHandler('message', remoteChat.handleMessage);
	    con.registerHandler('presence', remoteChat.handlePresence);
	    con.registerHandler('iq', remoteChat.handleIQ);
	    con.registerHandler('onconnect', remoteChat.handleConnected);
	    con.registerHandler('onerror', remoteChat.handleError);
	    con.registerHandler('status_changed', remoteChat.handleStatusChanged);
	    con.registerHandler('ondisconnect', remoteChat.handleDisconnected);
	
	    con.registerIQGet('query', NS_VERSION, remoteChat.handleIqVersion);
	    con.registerIQGet('query', NS_TIME, remoteChat.handleIqTime);
	},
	// 发送远程消息
	sendMessage: function (msg, to) {
		try {
			if (msg == "") {
				return false;
			}
			var user = "";
			if (to) {
				if (!~to.indexOf("@")) {
					user += "@" + remote.jsjac.domain;
					to += "/" + remote.jsjac.resource;
				} else if (~to.indexOf("/")) {
					user = to.substr(0, to.indexOf("/"));
				}
			} else {
				// 向chat接收信息区域写消息
				if (remote.jsjac.chat.writeReceiveMessage) {
					var html = "你没有指定发送者的名称";
					alert(html);
					//remote.jsjac.chat.writeReceiveMessage(receiverId, "server", html, false);
				}
				return false;
			}
			var userJID = "u" + hex_md5(user);
			$("#" + userJID).find(remote.receiver).val(to);
			// 构建jsjac的message对象
			var message = new JSJaCMessage();
			message.setTo(new JSJaCJID(to));
			message.setType("chat"); // 单独聊天,默认为广播模式
			message.setBody(msg);
			// 发送消息
			remote.connection.send(message);
			return false;
		} catch (e) {
			var html = "<div class='msg error''>Error: " + e.message + "</div>";
			remote.console.info(html);
			return false;
		}
	},
	// 退出、断开链接
	logout: function () {
		var presence = new JSJaCPresence();
		presence.setType("unavailable");
		if (remote.connection) {
			remote.connection.send(presence);
			remote.connection.disconnect();
		}
	},
	errorHandler: function (event) {
		var e = event || window.event;
		remote.console.errorEL().html(e);
		if (remote.connection && remote.connection.connected()) {
			remote.connection.disconnect();
		}
		return false;
	},
	unloadHandler: function () {
		var con = remote.connection;
		if (typeof con != "undefined" && con && con.connected()) {
	  		// save backend type
			if (con._hold) { // must be binding
				(new JSJaCCookie("btype", "binding")).write();
			} 
			if (con.suspend) {
				con.suspend();
			}
		}
	},
	writeMessage: function (userJID, userName, content) {
		// 向chat接收信息区域写消息
		if (remote.jsjac.chat.writeReceiveMessage && !!content) {
			remote.jsjac.chat.writeReceiveMessage(userJID, userName, content, false);
		}
	},
	// 重新连接服务器
	reconnection: function () {
		remote.jsjac.register = false;
		if (remote.connection.connected()) {
			remote.connection.disconnect();
		}
		remote.jsjac.chat.login();
	},
	/* ########################### Handler Event ############################# */
	
	handleIQ: function (aIQ) {
		var html = "<div class='msg'>IN (raw): " + aIQ.xml().htmlEnc() + "</div>";
		remote.console.info(html);
		remote.connection.send(aIQ.errorReply(ERR_FEATURE_NOT_IMPLEMENTED));
	},
	handleMessage: function (aJSJaCPacket) {
		var user = aJSJaCPacket.getFromJID().toString();
		//var userName = user.split("@")[0];
		//var userJID = "u" + hex_md5(user);
		var content = aJSJaCPacket.getBody();
		var html = "";
		html += "<div class=\"msg\"><b>消息来自 " + user + ":</b><br/>";
		html += content.htmlEnc() + "</div>";
		remote.console.info(html);
		
		$.WebIM.messageHandler(user, content);
	},
	handlePresence: function (aJSJaCPacket) {
		var user = aJSJaCPacket.getFromJID();
		var userName = user.toString().split("@")[0];
		var html = "<div class=\"msg\">";
		if (!aJSJaCPacket.getType() && !aJSJaCPacket.getShow()) {
			html += "<b>" + userName + " 上线了.</b>";
		} else {
			html += "<b>" + userName + " 设置 presence 为: ";
			if (aJSJaCPacket.getType()) {
				html += aJSJaCPacket.getType() + ".</b>";
			} else {
				html += aJSJaCPacket.getShow() + ".</b>";
			}
			if (aJSJaCPacket.getStatus()) {
				html += " (" + aJSJaCPacket.getStatus().htmlEnc() + ")";
			}
		}
		html += "</div>";
		remote.console.info(html);
		
		// 向chat接收信息区域写消息
		remote.jsjac.chat.writeMessage("", userName, html);
	},
	handleError: function (event) {
		var e = event || window.event;
		var html = "An error occured:<br />" 
			+ ("Code: " + e.getAttribute("code") 
			+ "\nType: " + e.getAttribute("type") 
			+ "\nCondition: " + e.firstChild.nodeName).htmlEnc();
		remote.error(html);
		
		var content = "";
		switch (e.getAttribute("code")) {
			case "401":
				content = "登陆验证失败!";
				break;
			// 当注册发现重复,表明该用户已经注册,那么直接进行登陆操作			
			case "409":
				//content = "注册失败!\n\n请换一个用户名!";
				remote.jsjac.chat.reconnection();
				break;
			case "503":
				content = "无法连接到IM服务器,请检查相关配置!";
				break;
			case "500":
				var contents = "服务器内部错误!\n\n连接断开!<br/><a href='javascript: self.parent.remote.jsjac.chat.reconnection();'>重新连接</a>";
				remote.jsjac.chat.writeMessage("", "系统", contents);
				break;
			default:
				break;
		}
		if (content) {
			alert("WeIM: " + content);
		}
		if (remote.connection.connected()) {
			remote.connection.disconnect();
		}
	},
	// 状态变化触发事件
	handleStatusChanged: function (status) {
		remote.console.info("<div>当前用户状态: " + status + "</div>");
		remote.dbger.log("当前用户状态: " + status);
		if (status == "disconnecting") {
			var html = "<b style='color:red;'>你离线了!</b>";
			// 向chat接收信息区域写消息
			remote.jsjac.chat.writeMessage("", "系统", html);
		}
	},
	// 建立链接触发事件方法
	handleConnected: function () {
		remote.console.clear("debug"); // reset
		remote.connection.send(new JSJaCPresence());
	},
	// 断开链接触发事件方法
	handleDisconnected: function () {
		
	},
	handleIqVersion: function (iq) {
		remote.connection.send(iq.reply([
			iq.buildNode("name", remote.jsjac.resource), 
			iq.buildNode("version", JSJaC.Version), 
			iq.buildNode("os", navigator.userAgent)
		]));
		return true;
	},
	handleIqTime: function (iq) {
		var now = new Date();
		remote.connection.send(iq.reply([
			iq.buildNode("display", now.toLocaleString()), 
			iq.buildNode("utc", now.jabberDate()), 
			iq.buildNode("tz", now.toLocaleString().substring(now.toLocaleString().lastIndexOf(" ") + 1))
		]));
		return true;
	}
};

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

 

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

/**
 * IM chat Send Message iframe editor
 * @author: hoojo
 * @email: hoojo_@126.com
 * @blog: http://blog.csdn.net/IBM_hoojo 
 * @createDate: 2012-5-24
 * @version 1.0
 **/
var agent = window.navigator.userAgent.toLowerCase();
var sendMessageEditor = {

 	// 获取iframe的window对象
	getWin: function () {
        return /*!/firefox/.test(agent)*/false ? sendMessageEditor.iframe.contentWindow : window.frames[sendMessageEditor.iframe.name];
    },

	//获取iframe的document对象
	getDoc: function () {
		return !/firefox/.test(agent) ? sendMessageEditor.getWin().document : (sendMessageEditor.iframe.contentDocument || sendMessageEditor.getWin().document);
	},

	init: function (userJID) {
		//打开document对象,向其写入初始化内容,以兼容FireFox
		var doc = sendMessageEditor.getDoc();
		doc.open();
		var html = [
			'<html>', 
			'<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>',
			'<body jid="', userJID, '"></body>', 
			'</html>'].join("");
		doc.write(html);
		//打开document对象编辑模式
		doc.designMode = "on";
		doc.close();
	},
 
 	getContent: function () {
 		var doc = sendMessageEditor.getDoc();
 		//获取编辑器的body对象
		var body = doc.body || doc.documentElement;
		//获取编辑器的内容
		var content = body.innerHTML;
		//对内容进行处理,例如替换其中的某些特殊字符等等
		//Some code
		
		//返回内容
		return content;
 	},
 	
 	 //统一的执行命令方法
	execCmd: function (cmd, value, d){
		var doc = d || sendMessageEditor.getDoc();
	    //doc对象的获取参照上面的代码
	    //调用execCommand方法执行命令
	    doc.execCommand(cmd, false, value === undefined ? null : value);
	},
	
	getStyleState: function (cmd) {
		var doc = sendMessageEditor.getDoc();
		//doc对象的获取参考上面的对面
		//光标处是否是粗体
		var state = doc.queryCommandState(cmd);
		if(state){
		  //改变按钮的样式
		}
		return state;
	},
	insertAtCursor: function (text, d, w){
		var doc = d || sendMessageEditor.getDoc();
		var win = w || sendMessageEditor.getWin();
		//win对象的获取参考上面的代码
		if (/msie/.test(agent)) {
			win.focus();
			var r = doc.selection.createRange();
			if (r) {
				r.collapse(true);
			    r.pasteHTML(text);      
			}
		} else if (/gecko/.test(agent) || /opera/.test(agent)) {
			win.focus();
			sendMessageEditor.execCmd('InsertHTML', text, doc);
		} else if (/safari/.test(agent)) {
			sendMessageEditor.execCmd('InsertText', text, doc);
		}
	}
};


5、css样式 chat-2.0.css

/**
 * function: im web chat css
 * author: hoojo
 * createDate: 2012-5-26 上午11:42:10
 */
@CHARSET "UTF-8";

*, body {
	font-family: Courier,serif,monospace;
	font-size: 12px;
	padding: 0;
	margin: 0;	
}

.chat-main {
	position: absolute;
	/*right: 80px;*/
	left: 50px;
	top: 20px;
	z-index: 999;
	display: none;
}

.chat-main .radius {
	background-color: white;
	border: 8px solid #94CADF;
	border-radius: 1em;
}

#chat {
	position: relative;
	/*left: 150px;*/
	padding: 0;
	margin: 0;
}
#chat table {
	border-collapse: collapse;
	width: 435px;
	*width: 460px;
	/*width: 410px;*/
	/*width: 320px;*/
}

#chat table .title {
	font-weight: bold;
	color: green;
	padding: 3px;
	background-color: #94CADF;
}

/* 收缩条 */
#chat table .split {
	background-color: #94CADF;
	cursor: pointer;
}

/* ################## product info #################### */
#chat table .product-info {
	width: 30%;
	/*display: none;*/
	padding: 0;
	margin: 0;
	vertical-align: top;
}

#chat table .product-info ul {
	margin: 0;
	padding: 0;
}

#chat table .product-info ul div.header {
	background-color: #EBEFFE;
	line-height: 22px;
	font-size: 12px;
	color: black;
}

#chat table .product-info ul li {
	list-style: none outside none;
	background-color: white;
	text-overflow: ellipsis;
	white-space: nowrap;
	overflow: hidden;
	padding-left: 5px;
	line-height: 22px;
	font-size: 11px;
	color: #6F6F6F;
	width: 140px;
}

#chat table .product-info ul li.pic {
	height: 200px;
	padding: 0 5px 0 5px;
	border: 1px dashed #ccc;
	text-align: center;
}

#chat table .product-info ul li.pic img {
}

#chat table .product-info ul li.product-name {
	font-weight: bold;
	color: black;
}

#chat table .product-info ul li.price span {
	font-family: Courier;
	font-size: 16px;
	font-weight: bold;
	color: #ED4E08;
}

#chat table .product-info ul li.market-price s {
	color: black;
}

#chat table .product-info ul li a {
	float: right;
}

#chat table .product-info ul li.info {
	display: none;
}

/*########### 接收消息区域 ############ */
#chat table .receive-message {
	height: 250px;
}

#chat table .send-message {
	width: 100%;
	/*height: auto;*/
}

#chat table td {
	/*border: 1px solid white;*/
}

#chat table .bottom-bar {
	background-color: #94CADF;
	text-align: right;
}

/* ############## 工具条 ################# start */
#chat table .tool-bar {
	height: 25px;
	background-color: #94CADF;
}

#chat table .tool-bar select {
	float: left;
}

#chat table .tool-bar select.family {
	width: 45px;
	*width: 55px;
}

#chat table .tool-bar div {
	width: 17px;
	height: 16px;
	float: left;
	cursor: pointer;
	margin-right: 2px;
	margin-top: 1px;
	*margin-top: 2px;
	background: transparent url("../images/tb-sprite.gif") no-repeat scroll 0 0;
}

#chat table .tool-bar .color {
	margin-left: 2px;
	background-position: -159px 0;
}
#chat table .tool-bar .bold {
	/*background-position: 0 0;*/
}
#chat table .tool-bar .italic {
	background-position: -18px 0;
}
#chat table .tool-bar .underline {
	background-position: -32px 0;
}
#chat table .tool-bar .face {
	margin: 2px 0 0 3px;
	background-image: url("../images/facehappy.gif");
}
#chat table .tool-bar .history {
	background-image: none;
	width: 60px;
	float: right;
	margin-top: 3px;
	font-size: 12px;
	display: none;
}
/* ###### 表情 ###### */
#chat #face {
	border: 1px solid black;
	width: 275px;
	*width: 277px;
	position: relative;
	left: 8px;
	top: -370px;
	_top: -359px;
	z-index: 3;
	display: none;
}

#chat #face img {
	border: 1px solid #ccc;
	border-right: none;
	border-bottom: none; 
	cursor: pointer;
}

#send {
	width: 90px;
	height: 25px;
}
#close {
	width: 40px;
	height: 25px;
}

.chat-message {
	position: absolute; 
	bottom: 0; 
	left: 0; 
	width: 100%; 
	height: 25px; 
	background-color: #fcfcfc;
}

.no-msg, .have-msg {
	cursor: pointer; 
	float: right; 
	margin: 5px 5px 0 0;
}

6、web.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
	<servlet>
		<servlet-name>Jabber HTTP Binding Servlet</servlet-name>
		<servlet-class>org.jabber.JabberHTTPBind.JHBServlet</servlet-class>
		<!-- 
		<init-param>
			<param-name>debug</param-name>
			<param-value>1</param-value>
		</init-param>
		 -->
	</servlet>

	<servlet-mapping>
		<servlet-name>Jabber HTTP Binding Servlet</servlet-name>
		<url-pattern>/JHB/</url-pattern>
	</servlet-mapping>

	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
</web-app>


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


【分享】JavaScript/jQueryHTMLCSS 构建 Web IM 远程及时聊天通信程序

08-13

[code=CSS]这篇文章主要介绍用JavaScript和jQuery、HTML、CSS以及用第三方聊天JavaScript(jsjac)框架构建一个BS Web的聊天应用程序。rn此程序可以和所有连接到Openfire服务器的应用进行通信、发送消息。如果要运行本程序还需要一个聊天服务器Openfire以及rn需要用到Http方式和Openfire通信的第三方库(JabberHTTPBind)。rnJabberHTTPBind是jabber提供的XMPP协议通信的Http bind发送的形式,它可以完成WebBrowser和Openfire建立长连接通信。[/code]rnrn[code=CSS]主要通信流程如下图所示:[/code]rn[img=http://my.csdn.net/uploads/201208/10/1344568247_9592.jpg][/img]rnrn[url=http://blog.csdn.net/ibm_hoojo/article/details/7850540]传送门:原文地址、源码[/url]rnrn[code=CSS]用户A通过JavaScript jsjac.js库发送一条消息到JabberHTTPBind这个Servlet容器,然后JabberHTTPBind的Servlet容器会向rnOpenfire发送XMPP协议的XML报文。Openfire Server接收到报文后解析,然后发送给指定的用户B。JabberHTTPBind获取到rnOpenfire Server发送的数据后,解析报文向当前Servlet容器中的链接的Session中找到指定的用户再发送数据给用户B。rnWebBrowser端用的是jsjac和JabberHTTPBind建立的连接,所有数据都要经过JabberHTTPBind解析/转换发送给Openfire。[/code]rn rnrn[code=CSS]先上张图看看效果,呵呵~这里是用户hoojo和girl的聊天画面,双方在进行互聊……[/code]rn[img=http://my.csdn.net/uploads/201208/13/1344822965_3764.png][/img]rn[code=CSS]可以发送表情、改变字体样式(对方界面也可以看到你的字体样式),同时右侧是显示/收缩详情的信息[/code]rn[img=http://my.csdn.net/uploads/201208/13/1344822971_1121.png][/img]rn[code=CSS]收缩详情[/code]rn[img=http://my.csdn.net/uploads/201208/13/1344822975_1697.png][/img]rnrn[b]聊天界面部分截图[/b]rn[code=CSS]用户登录、注册,sendTo表示你登录后向谁发送聊天消息、并且建立一个聊天窗口[/code]rn[img=http://my.csdn.net/uploads/201208/13/1344823036_3645.png][/img]rn[img=http://my.csdn.net/uploads/201208/13/1344822981_6036.png][/img]rn[code=CSS]登录成功后,你可以在日志控制台看到你的登陆状态、或是在firebug控制台中看到你的连接请求状态[/code]rn[img=http://my.csdn.net/uploads/201208/13/1344822985_3139.png][/img]rn[img=http://my.csdn.net/uploads/201208/13/1344822991_7612.png][/img]rn[code=CSS]登陆失败[/code]rn[img=http://my.csdn.net/uploads/201208/13/1344823013_2246.png][/img]rn[code=CSS]只有connecting,就没有下文了[/code]rn[img=http://my.csdn.net/uploads/201208/13/1344823006_1147.png][/img]rn[code=CSS]登陆成功后,你就可以给指定用户发送消息,且设置你想发送消息的新用户点击new Chat按钮创建新会话[/code]rn[img=http://my.csdn.net/uploads/201208/13/1344823024_4681.png][/img]rn[code=CSS]如果你来了新消息,在浏览器的标题栏会有新消息提示[/code]rn[img=http://my.csdn.net/uploads/201208/13/1344823031_9472.png][/img]rn[code=CSS]如果你当前聊天界面的窗口都是关闭状态,那么在右下角会有消息提示的闪动图标[/code]rn rn[b][color=#FF0000]这里已经贴出了所有的源代码了,如果你非常的需要源代码(但我希望你能自己创建一个工程去复制源代码,这是我希望看到的),那么你可以通过以下方式联系我[/color][/b]rn[code=CSS]Email:hoojo_@126.comrnBlog:http://blog.csdn.net/IBM_hoojornhttp://hoojo.cnblogs.com/rnhttp://hoojo.blogjava.net[/code]rn[b][color=#FF0000]注:我不会保证在第一时间给你代码,但我会在空闲的时间给你发送源码[/color][/b]rn rn[b]导读[/b]rn[code=CSS]如果你对openfire还不是很了解或是不知道安装,建议你看看这2篇文章rn http://www.cnblogs.com/hoojo/archive/2012/05/17/2506769.htmlrn http://www.cnblogs.com/hoojo/archive/2012/05/13/2498151.htmlrn因为这里还用到了JabberHTTPBind 以及在使用它或是运行示例的时候会遇到些问题,那么你可以看看这篇文章rn http://www.cnblogs.com/hoojo/archive/2012/05/17/2506845.html[/code]rn rn[b]开发环境[/b]rn[code=CSS]System:WindowsrnJavaEE Server:Tomcat 5.0.28+/Tomcat 6rnWebBrowser:IE6+、Firefox3.5+、Chrome 已经兼容浏览器rnJavaSDK:JDK 1.6+rnOpenfire 3.7.1rnIDE:eclipse 3.2、MyEclipse 6.5[/code]rnrn[b]开发依赖库[/b]rn[code=CSS]jdk1.4+rnserializer.jarrnxalan.jarrnjhb-1.0.jarrnlog4j-1.2.16.jarrnjhb-1.0.jar 这个就是JabberHTTPBind,我把编译的class打成jar包了[/code]rnrn[b]JavaScript lib[/b]rn[code=CSS]jquery.easydrag.js 窗口拖拽JavaScript librnjquery-1.7.1.min.js jquery librnjsjac.js 通信核心库rnlocal.chat-2.0.js 本地会话窗口发送消息JavaScript库rnremote.jsjac.chat-2.0.js 远程会话消息JavaScript库rnsend.message.editor-1.0.js 窗口编辑器JavaScript库 [/code]rnrn rnrn[b]一、准备工作[/b]rn[code=CSS] jsjac JavaScript lib下载:https://github.com/sstrigler/JSJaC/rn 如果你不喜欢用jsjac JavaScript lib和Openfire通信,那么有一款jQuery的plugin可以供你使用,下载地址rn jQuery-XMPP-plugin https://github.com/maxpowel/jQuery-XMPP-pluginrn 这里有所以能支持Openfire通信的第三方库,有兴趣的可以研究下 http://xmpp.org/xmpp-software/libraries/rn jquery.easydrag 下载:http://fromvega.com/code/easydrag/jquery.easydrag.jsrn jquery 下载:http://code.jquery.com/jquery-1.7.1.min.jsrn JabberHTTPBind jhb.jar 下载:http://download.csdn.net/detail/ibm_hoojo/4489188rn images 图片素材:http://download.csdn.net/detail/ibm_hoojo/4489439[/code]rnrn 工程目录结构rn[img=http://my.csdn.net/uploads/201208/13/1344823534_5457.png][/img]rn rnrn[b]二、核心代码演示[/b]rn 1、主界面(登陆、消息提示、日志、建立新聊天窗口)代码 index.jsprnrn [code=HTML]<%@ page language="java" pageEncoding="UTF-8" %>rn <%rn String path = request.getContextPath();rn String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";rn %>rnrn rn rn rn rn rn WebIM Chatrn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn userName:rn password:rn rn register: rn sendTo: rn rn rn rn rn User:rn sendTo: rn rn rn rn rn rn rn rn rn rn rn rn rn [/code]rnrn 下面这段代码尤为重要,它是设置你链接openfire的地址。这个地址一段错误你将无法进行通信!rn[code=JScript] [/code]rnrn $.WebIM方法是主函数,用它可以覆盖local.chat中的基本配置,它可以完成聊天窗口的创建。$.WebIM.newWebIM方法是新创建一个窗口,只是消息的接收者是一个新用户。rn [code=JScript]$.WebIM(rn sender: userName,rn receiver: receiverrn ); rnrn $.WebIM.newWebIM(rn receiver: receiverrn );[/code]rnrn[code=CSS]rn remote.jsjac.chat.login(document.userForm);方法是用户登录到Openfire服务器rn 参数如下:rn httpbase: window.contextPath + "/JHB/", //请求后台http-bind服务器urlrn domain: window["serverDomin"], //"192.168.5.231", // 192.168.5.231 当前有效域名rn username: "", // 登录用户名rn pass: "", // 密码rn timerval: 2000, // 设置请求超时rn resource: "WebIM", // 链接资源标识rn register: true // 是否注册rn rn remote.jsjac.chat.logout();是退出、断开openfire的链接[/code]rnrn[code=CSS]rn 这里的方法基本上是聊天窗口上的应用,主要是本地聊天程序的js、HTML元素的操作。如字体、字体大小、颜色、表情、消息的发送等,不涉及到聊天消息发送的核心代码,其中有用到发送远程消息的方法。rn remote.jsjac.chat.sendMessage(text, receiver); 这个是发送远程消息的方法,参数1是消息内容、参数2是消息的接收者rn 如果你有看到这篇文章http://www.cnblogs.com/hoojo/archive/2012/06/18/2553886.html 它是一个单纯的WebIM本地的聊天界面。[/code]rnrn[u][b][color=#FF0000]就贴那么多意思下,如果要看全文点击下面链接。这里贴代码太辛苦了……[/color][/b][/u]rnrn其他代码见博客文章地址:[url=http://blog.csdn.net/ibm_hoojo/article/details/7850540]http://blog.csdn.net/ibm_hoojo/article/details/7850540[/url]

没有更多推荐了,返回首页

私密
私密原因:
请选择设置私密原因
  • 广告
  • 抄袭
  • 版权
  • 政治
  • 色情
  • 无意义
  • 其他
其他原因:
120
出错啦
系统繁忙,请稍后再试