首页 web前端 js教程 JavaScript/jQuery、HTML、CSS 构建 Web IM 远程及时聊天通信程序_jquery

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

May 16, 2016 pm 05:51 PM

以及需要用到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

image

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

image

image

登陆失败

image

只有connecting,就没有下文了

image

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

image

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

image

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

这里已经贴出了所有的源代码了,如果你非常的需要源代码(但我希望你能自己创建一个工程去复制源代码,这是我希望看到的),那么你可以通过以下方式联系我
Email:hoojo_@126.com
Blog:http://blog.csdn.net/IBM_hoojo
http://hoojo.cnblogs.com/
http://hoojo.blogjava.net
注:我不会保证在第一时间给你代码,但我会在空闲的时间给你发送源码

开发环境
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 
二、核心代码演示
1、主界面(登陆、消息提示、日志、建立新聊天窗口)代码 index.jsp

复制代码 代码如下:


String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>




WebIM Chat





















userName:
password:
register:
sendTo:









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




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



$.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: [
'',
'',
'',
''
].join(""),
writeReceiveStyle: function (receiverId) {
this.receiveMessageDoc(receiverId)[0].get(0).write(this.receiveStyle);
},
datetimeFormat: function (v) {
if (~~v 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 = [ "", content, "" ].join("");
}
return [
'

', _opts.getDatetime(), ' ', userName, ':

',
'

', content, '

'
].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("
", "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 = [ "", content, "" ].join("");
remote.jsjac.chat.sendMessage(content, receiver);
}
// 清空发送区域
$(doc).find("body").html("");
}
},
faceImagePath: "images/emotions/",
faceElTpl: function (i) {
return [
"JavaScript/jQuery、HTML、CSS 构建 Web IM 远程及时聊天通信程序_jquery"
].join("");
},
// 创建表情html elements
createFaceElement: function ($chat) {
var faces = [];
for (var i = 1; i faces.push(this.faceElTpl(i));
if (i % 11 == 0) {
faces.push("
");
}
}
$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 = "JavaScript/jQuery、HTML、CSS 构建 Web IM 远程及时聊天通信程序_jquery";
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 = [''].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="max-width:90%";
}
return [
'
',
'
',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'
',
'',
'
',
'
    ',
    '
    商品详情
    ',
    '
  • ',
    'JavaScript/jQuery、HTML、CSS 构建 Web IM 远程及时聊天通信程序_jquery
  • ',
    '
  • ', product.name, '
  • ',
    '
  • 团购价:', product.price, '
  • ',
    '
  • 市场价:', product.marketPrice, '
  • ',
    '
  • 快递公司:', product.deliverOrgs, '
  • ',
    '
  • 仓库:', product.wareHouses, '
  • ',
    product.skuAttrs,
    '
',
'
',
'',
'',
'',
'
',
'
',
'
',
'
',
'
消息记录
',
'
',
'',
'
',
'
',
'
',
'
',
'
'
].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 = "
Error: " + e.message + "
";
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 = "
IN (raw): " + aIQ.xml().htmlEnc() + "
";
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 += "
消息来自 " + user + ":
";
html += content.htmlEnc() + "
";
remote.console.info(html);
$.WebIM.messageHandler(user, content);
},
handlePresence: function (aJSJaCPacket) {
var user = aJSJaCPacket.getFromJID();
var userName = user.toString().split("@")[0];
var html = "
";
if (!aJSJaCPacket.getType() && !aJSJaCPacket.getShow()) {
html += "" + userName + " 上线了.";
} else {
html += "" + userName + " 设置 presence 为: ";
if (aJSJaCPacket.getType()) {
html += aJSJaCPacket.getType() + ".
";
} else {
html += aJSJaCPacket.getShow() + ".";
}
if (aJSJaCPacket.getStatus()) {
html += " (" + aJSJaCPacket.getStatus().htmlEnc() + ")";
}
}
html += "
";
remote.console.info(html);
// 向chat接收信息区域写消息
remote.jsjac.chat.writeMessage("", userName, html);
},
handleError: function (event) {
var e = event || window.event;
var html = "An error occured:
"
+ ("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请换一个用户名!";
remote.jsjac.chat.reconnection();
break;
case "503":
content = "无法连接到IM服务器,请检查相关配置!";
break;
case "500":
var contents = "服务器内部错误!\n\n连接断开!
重新连接";
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("
当前用户状态: " + status + "
");
remote.dbger.log("当前用户状态: " + status);
if (status == "disconnecting") {
var html = "你离线了!";
// 向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 = [
'',
'',
'',
''].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配置
复制代码 代码如下:


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">

Jabber HTTP Binding Servlet
org.jabber.JabberHTTPBind.JHBServlet



Jabber HTTP Binding Servlet
/JHB/


index.jsp



至此,这个应用的全部代码已经贴出来,如果你按照我这边的结构形式应该是可以完成这个聊天应用的。如果你有什么问题或想法,欢迎你给我留言或评论!
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

前端热敏纸小票打印遇到乱码问题怎么办? 前端热敏纸小票打印遇到乱码问题怎么办? Apr 04, 2025 pm 02:42 PM

前端热敏纸小票打印的常见问题与解决方案在前端开发中,小票打印是一个常见的需求。然而,很多开发者在实...

谁得到更多的Python或JavaScript? 谁得到更多的Python或JavaScript? Apr 04, 2025 am 12:09 AM

Python和JavaScript开发者的薪资没有绝对的高低,具体取决于技能和行业需求。1.Python在数据科学和机器学习领域可能薪资更高。2.JavaScript在前端和全栈开发中需求大,薪资也可观。3.影响因素包括经验、地理位置、公司规模和特定技能。

神秘的JavaScript:它的作用以及为什么重要 神秘的JavaScript:它的作用以及为什么重要 Apr 09, 2025 am 12:07 AM

JavaScript是现代Web开发的基石,它的主要功能包括事件驱动编程、动态内容生成和异步编程。1)事件驱动编程允许网页根据用户操作动态变化。2)动态内容生成使得页面内容可以根据条件调整。3)异步编程确保用户界面不被阻塞。JavaScript广泛应用于网页交互、单页面应用和服务器端开发,极大地提升了用户体验和跨平台开发的灵活性。

如何使用JavaScript将具有相同ID的数组元素合并到一个对象中? 如何使用JavaScript将具有相同ID的数组元素合并到一个对象中? Apr 04, 2025 pm 05:09 PM

如何在JavaScript中将具有相同ID的数组元素合并到一个对象中?在处理数据时,我们常常会遇到需要将具有相同ID�...

如何实现视差滚动和元素动画效果,像资生堂官网那样?
或者:
怎样才能像资生堂官网一样,实现页面滚动伴随的动画效果? 如何实现视差滚动和元素动画效果,像资生堂官网那样? 或者: 怎样才能像资生堂官网一样,实现页面滚动伴随的动画效果? Apr 04, 2025 pm 05:36 PM

实现视差滚动和元素动画效果的探讨本文将探讨如何实现类似资生堂官网(https://www.shiseido.co.jp/sb/wonderland/)中�...

console.log输出结果差异:两次调用为何不同? console.log输出结果差异:两次调用为何不同? Apr 04, 2025 pm 05:12 PM

深入探讨console.log输出差异的根源本文将分析一段代码中console.log函数输出结果的差异,并解释其背后的原因。�...

JavaScript难以学习吗? JavaScript难以学习吗? Apr 03, 2025 am 12:20 AM

学习JavaScript不难,但有挑战。1)理解基础概念如变量、数据类型、函数等。2)掌握异步编程,通过事件循环实现。3)使用DOM操作和Promise处理异步请求。4)避免常见错误,使用调试技巧。5)优化性能,遵循最佳实践。

PowerPoint可以运行JavaScript吗? PowerPoint可以运行JavaScript吗? Apr 01, 2025 pm 05:17 PM

在PowerPoint中可以运行JavaScript,通过VBA调用外部JavaScript文件或嵌入HTML文件来实现。1.使用VBA调用JavaScript文件,需启用宏并具备VBA编程知识。2.嵌入包含JavaScript的HTML文件,简单易行但受安全限制。优点包括扩展功能和灵活性,劣势涉及安全性、兼容性和复杂性,实际应用需注意安全性、兼容性、性能和用户体验。

See all articles