This article is mainly for introduction. JavaScript and jQuery,HTML,CSS And using the third-party chat JavaScript (jsjac) framework to build a BS Web chat application. This program can communicate and send messages with all applications connected to the Openfire server. If you want to run this program, you need a chat server, Openfire.
And third-party libraries (Jabber HTTPBind) that require Http and Openfire communications.
Jabber HTTPBind is a form of Http bind transmission for XMPP protocol communication provided by jabber. It can complete long-connection communication between Web Browser and Openfire.
The main communication flow is shown in the following figure:
User A sends a message through the JavaScript jsjac.js library to the JabberHTTPBind Servlet container, and then the JabberHTTPBind Servlet container sends an XML message of the XMPP protocol to Openfire. After receiving the message, Openfire Server parses it and sends it to the specified user B. After JabberHTTPBind obtains the data sent by Openfire Server, it parses the message to find the specified user in the Session of the link in the current Servlet container and sends the data to User B.
WebBrowser uses a connection between jsjac and Jabber HTTPBind, and all data is sent to Openfire through Jabber HTTPBind parsing/conversion.
First of all, let's take a picture to see the effect. Here are the chat pictures of users hoojo and girl. Both sides are chatting with each other.
You can send expressions, change the font style (your font style can also be seen in the other interface), and on the right side is information showing / shrinking details.
Contraction details
Section screenshot of chat interface
Users login, register, sendTo means who you send chat messages to after login, and establish a chat window
After successful login, you can see your login status in the log console or your connection request status in the firebug console.
Landing failed
If only connected, there will be no following
Once the login is successful, you can send a message to the designated user and set the new user you want to send the message to click the new Chat button to create a new session.
If you have new news, there will be a new message in the title bar of the browser.
If all the windows in your current chat interface are closed, there will be a flashing icon in the lower right corner of the chat interface.
All the source code has been posted here. If you need the source code very much (but I hope you can create a project to copy the source code, which I hope to see), then you can contact me in the following way
Email: hoojo_@126.com
Blog: http://blog.csdn.net/IBM_hoojo
Note: I won't guarantee to give you the code in the first place, but I will send you the source code in my spare time.
Guide reading
If you don't know much about openfire or know how to install it, I suggest you read these two articles.
http://www.cnblogs.com/hoojo/archive/2012/05/17/2506769.html
http://www.cnblogs.com/hoojo/archive/2012/05/13/2498151.html
Because Jabber HTTPBind is also used here and there are some problems when using it or running the sample, you can read this article.
http://www.cnblogs.com/hoojo/archive/2012/05/17/2506845.html
development environment
System: Windows
JavaEE Server: Tomcat 5.0.28+/Tomcat 6
Web Browser: IE6+, Firefox 3.5+, Chrome are compatible with browsers
JavaSDK: JDK 1.6+
Openfire 3.7.1
IDE: eclipse 3.2,MyEclipse 6.5
Developing dependency Libraries
jdk1.4+
serializer.jar
xalan.jar
jhb-1.0.jar
log4j-1.2.16.jar
jhb-1.0.jar This is Jabber HTTPBind. I've typed the compiled class es into jar packages.
JavaScript lib
jquery.easydrag.js Window drag and drop JavaScript lib
jquery-1.7.1.min.js jquery lib
jsjac.js Communication Core Library
local.chat-2.0.js Local Session Window Sends Messages JavaScript library
remote.jsjac.chat-2.0.js Remote session message JavaScript library
send.message.editor-1.0.js Window Editor JavaScript library
I. Preparations
jsjac JavaScript lib download: https://github.com/sstrigler/JSJaC/
If you don't like using jsjac JavaScript lib to communicate with Openfire, then there's a jQuery plugin for you to use, download address
jQuery-XMPP-plugin https://github.com/maxpowel/jQuery-XMPP-plugin
There are so many third-party libraries that can support Openfire communications, which are interesting to study. http://xmpp.org/xmpp-software/libraries/
jquery.easydrag Download: http://fromvega.com/code/easydrag/jquery.easydrag.js
jquery Download: http://code.jquery.com/jquery-1.7.1.min.js
Jabber HTTPBind jhb.jar Download: http://download.csdn.net/detail/ibm_hoojo/4489188
images Picture Material: http://download.csdn.net/detail/ibm_hoojo/4489439
2. Demonstration of Core Code
1,Home interface (login, message prompt, log, new chat window) code 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();// Establish a chat window application and set up senders and message receivers
$.WebIM({sender: userName,receiver: receiver});// Log on to the openfire server
remote.jsjac.chat.login(document.userForm);$("label").text(userName);
$("form").hide();
$("#newConn").show();
});$("#logout").click(function () {// Log out of openfire and disconnect
remote.jsjac.chat.logout();$("form").show();
$("#newConn").hide();
$("#chat").hide(800);
});$("#newSession").click(function () {var receiver = $("#sendTo").val();// Create a new chat window and set up the message recipient (to whom?)
$.WebIM.newWebIM({receiver: receiver});});});</script></head><body><!-- Landing form --><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><!-- New window chat --><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><!-- log information --><div id="error" style="display: ; background-color: red;"></div><div id="info" style="display: ; background-color: #999999;"></div><!-- Chat to Message Tips --><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>
The following code is particularly important. It sets the address of your link to openfire. You will not be able to communicate if there is an error in this address!
<script type="text/javascript">
window.contextPath = "<%=path%>";
window["serverDomin"] = "192.168.8.22";
</script>
$.WebIM The method is the main function, which can be overridden. local.chat In the basic configuration, it can complete the creation of chat window. $.WebIM.newWebIM The method is to create a new window, but the recipient of the message is a new user.
$.WebIM({sender: userName,receiver: receiver});$.WebIM.newWebIM({receiver: receiver});
remote.jsjac.chat.login(document.userForm);The method is that the user logs in Openfire The server
The parameters are as follows:
httpbase: window.contextPath + "/JHB/", //Request the background http-bind server urldomain: window["serverDomin"], //"192.168.5.231", //192.168.5.231 Currently valid domain nameusername: "", // Usernamepass: "", // Passwordtimerval: 2000, // Setting request timeout
resource: "WebIM", // Link Resource Identificationregister: true // Is it registered?
remote.jsjac.chat.logout();It's withdrawal and disconnection. openfire Links
2,Local Chat Application Core Code 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: "", // senderreceiver: "", // RecipientsetTitle: function (chatEl) {
var receiver = this.getReceiver(chatEl);chatEl.find(".title").html("and" + receiver + "Chat Dialogue");},getReceiver: function (chatEl) {
var receiver = chatEl.attr("receiver");if (~receiver.indexOf("@")) {receiver = receiver.split("@")[0];
}return receiver;
},// Receiving message iframe style
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 () {
// Set the current delivery date
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;
},/***
* Format template for sending messages
* flag = true Indicates that the current user is herself, otherwise it is the other party.
**/
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("");
},// Tool class button trigger event returns to html template
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;
}},// Write a message to the receiving message iframe region
writeReceiveMessage: function (receiverId, userName, content, flag) {
if (content) {
// Style of sending messages
var styleTpl = _opts.sendMessageStyle.getStyleTpl();
var receiveMessageDoc = _opts.receiveMessageDoc(receiverId);
$.each(receiveMessageDoc, function () {
var $body = this.find("body");// Write the transmitted data to the receiving information area
$body.append(_opts.receiveMessageTpl(userName, styleTpl, content, flag));// Roll the scroll bar to the bottom
this.scrollTop(this.height());});}},// send message
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"), "");// Get the content to be sent
if (content) {
var sender = $chatMain.attr("sender");var receiverId = $chatMain.attr("id");// Write message in receiving area
_opts.writeReceiveMessage(receiverId, sender, content, true);
//############# XXX
var receiver = $chatMain.find("#to").val();//var receiver = $chatMain.attr("receiver");
// Determine whether it's a cell phone session, send pure text if it's not, or send html code?
var flag = _opts.isMobileClient(receiver);
if (flag) {
var text = $(doc.body).text();
text = $.trim(text);if (text) {
// Send messages remotely
remote.jsjac.chat.sendMessage(text, receiver);}} else { // Non-mobile communication can send html codevar styleTpl = _opts.sendMessageStyle.getStyleTpl();
content = [ "<span style='", styleTpl, "'>", content, "</span>" ].join("");remote.jsjac.chat.sendMessage(content, receiver);}// Clean up the sending area
$(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("");
},// Create expression 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);
},// Insertion expression
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);});// Facial expression hiding
$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);});},/***
* Send Message Toolbar Button Event Method
**/
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());}}// Setting style css of sendMessage iframe
_opts.writeSendStyle();},// Setting style css of sendMessage iframe
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;},// Chat interface html elements
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">Commodity details</div>',
'<li class="pic">',
'<img src="', product.pic, '"/></li>','<li class="product-name">', product.name, '</li>','<li class="price">Group buying price:<span>', product.price, '</span>element</li>','<li class="market-price">Market value:<s><i>', product.marketPrice, '</i></s>element</li>','<li>Courier Services Company:', product.deliverOrgs, '</li>','<li>Warehouse:', product.wareHouses, '</li>',product.skuAttrs,'</ul>',
'</td>',
'</tr>',
'<tr class="tool-bar">',
'<td>',
'<select name="font-family" class="family">',
'<option>Song style</option>',
'<option>Blackbody</option>',
'<option>Young circle</option>',
'<option>STXingkai</option>',
'<option>stkaiti</option>',
'<option>stkaiti</option>',
'<option>STCaiyun</option>',
'<option>STLiti</option>',
'<option>Microsoft YaHei</option>',
'<option>Fixedsys</option>',
'</select>',
'<select name="font-size">',
'<option value="12px">Size</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">colour</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">Message record</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; display: none;"/><input type="button" value="Close" id="close"/>',
'<input type="button" value="Send out(Enter)" id="send"/> </td>',
'</tr>',
'</table></div>',
'<div id="face"></div>',
'</div>',
'</div>'
].join("");
},initWebIM: function (userJID, receiver) {
var product = {
name: "Little bear",
pic: "http://avatar.csdn.net/9/7/A/2_ibm_hoojo.jpg",
price: "198.00",
marketPrice: "899.90",
deliverOrgs: "EMS",
wareHouses: "A library",
skuAttrs: ""
};var chatEl = $(_opts.chatLayoutTemplate(userJID, _opts.sender, receiver, product));
$("body").append(chatEl);
// Drag and drop
$("#" + userJID).easydrag();
// Initialize sendMessageEditor related information
sendMessageEditor.iframe = this.sendMessageIFrame(userJID);
sendMessageEditor.init(userJID);_opts.setTitle(chatEl);_opts.writeReceiveStyle(userJID);_opts.writeSendStyle();_opts.createFaceElement(chatEl);// See more details
chatEl.find(".more").click(function () {var $ul = $(this).parents("ul");$ul.find(".more").toggle();
$ul.find(".info").toggle();
$ul.find(".pic").toggle();
});// Contraction details
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");});// Tool class binding event 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);});// First, cancel event binding. When multiple messages are sent at one time, multiple identical events are bound at the same time.
$(".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);}});},// Create a new chat window
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);
},// Execution function when sending message remotely
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);// First Initial webIM
if (!$("#" + userJID).get(0)) {// Initial IM panel;
_opts.initWebIM(userJID, user);}// Set the name of the message recipient
$("#" + userJID).find(remote.receiver).val(user);
if ($("#" + userJID).get(0)) {// Message hint
if ($("div[id='" + userJID + "']:hidden").get(0)) {var haveMessage = $(".have-msg");haveMessage.show();$(".no-msg").hide();
}_opts.messageTip("There is new news in the flash chat, please check it!");
// Write messages to the chat receiving area
remote.jsjac.chat.writeMessage(userJID, userName, content);}},// Message hint
messageTip: function () {
if (count % 2 == 0) {
window.focus();document.title = "You're here for new information, please check it out! uuuuuuuuuuu";
} else {
document.title = "";
}if (count > 4) {
document.title = "";
count = 0;} else {
window.setTimeout(_opts.messageTip, 1000);count ++;}}};// Initialization of Relevant Methods for Remote Chat Programs
var initRemoteIM = function (settings) {// Initialize remote messages
remote.jsjac.chat.init();// Setting Up Client Write Information Method
remote.jsjac.chat.writeReceiveMessage = settings.writeReceiveMessage;// Registration event
$(window).bind({unload: remote.jsjac.chat.unloadHandler,error: remote.jsjac.chat.errorHandler,beforeunload: remote.jsjac.chat.logout});}$.extend({WebIM: function (opts) {
opts = opts || {};// Override default configuration
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);The method here is basically the application of chat window, mainly local chat program. js,HTML The operation of elements. For example, font, font size, color, expression, message sending, etc., do not involve the core code of chat message sending, which is useful to send remote messages.
remote.jsjac.chat.sendMessage(text, receiver); This is the way to send a remote message. Parameter 1 is the content of the message and parameter 2 is the receiver of the message.
If you read this article http://www.cnblogs.com/hoojo/archive/2012/06/18/2553886.html It's a simple one. WebIM Local chat interface.
3,Remote chat JavaScript Core code, which is and jsjac Library-related.
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", // Recipient jquery expressionconsole: {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/", //Request the background http-bind server urldomain: window["serverDomin"], //"192.168.5.231", //192.168.5.231 Currently valid domain nameusername: "",
pass: "",
timerval: 2000, // Setting request timeout
resource: "WebIM", // Link Resource Identificationregister: true // Is it registered?}};remote.jsjac.chat = {writeReceiveMessage: function () {
},setState: function () {
var onlineStatus = new Object();onlineStatus["available"] = "On-line";onlineStatus["chat"] = "Welcome to chat";onlineStatus["away"] = "leave";onlineStatus["xa"] = "Unavailable";onlineStatus["dnd"] = "Do not disturb.";onlineStatus["invisible"] = "Invisible";onlineStatus["unavailable"] = "Off-line";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"); // resettry {
// Link parameter
var connectionConfig = remote.jsjac;
// Debugger console
if (typeof (oDbg) != "undefined") {connectionConfig.oDbg = oDbg;}var connection = new JSJaCHttpBindingConnection(connectionConfig);remote.connection = connection;// Install (register) Connection event model
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;
}// Connect servers
connection.connect(connectionConfig);//remote.jsjac.chat.changeStatus("available", "online", 1, "chat");
} catch (e) {
remote.console.errorEL().html(e.toString());} finally {
return false;}},// Change user status
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);}},// Register events for 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);
},// Sending remote messages
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 {
// Write messages to the chat receiving area
if (remote.jsjac.chat.writeReceiveMessage) {
var html = "You did not specify the sender's name";alert(html);//remote.jsjac.chat.writeReceiveMessage(receiverId, "server", html, false);
}return false;}var userJID = "u" + hex_md5(user);$("#" + userJID).find(remote.receiver).val(to);
// Constructing message object of jsjac
var message = new JSJaCMessage();message.setTo(new JSJaCJID(to));
message.setType("chat"); // Individual chat, default to broadcast modemessage.setBody(msg);// send message
remote.connection.send(message);return false;} catch (e) {
var html = "<div class='msg error''>Error: " + e.message + "</div>";remote.console.info(html);return false;}},// Exit, disconnect
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) {
// Write messages to the chat receiving area
if (remote.jsjac.chat.writeReceiveMessage && !!content) {
remote.jsjac.chat.writeReceiveMessage(userJID, userName, content, false);
}},// Reconnect the server
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>News comes from " + 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 + " Online..</b>";} else {
html += "<b>" + userName + " Set up presence For: ";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);// Write messages to the chat receiving area
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 = "Login verification failed!";
break;
// When the registration discovers duplication, indicating that the user has registered, the login operation is performed directly.
case "409"://content = failed registration! \n\n Please change a username! ";
remote.jsjac.chat.reconnection();break;
case "503":content = "Unable to connect IM Server, please check the configuration!";
break;
case "500":var contents = "Server internal error!\n\n Connection disconnected!<br/><a href='javascript: self.parent.remote.jsjac.chat.reconnection();'>Reconnect</a>";remote.jsjac.chat.writeMessage("", "system", contents);break;
default:
break;
}if (content) {
alert("WeIM: " + content);
}if (remote.connection.connected()) {
remote.connection.disconnect();}},// State change trigger event
handleStatusChanged: function (status) {
remote.console.info("<div>Current user status: " + status + "</div>");remote.dbger.log("Current user status: " + status);
if (status == "disconnecting") {var html = "<b style='color:red;'>You're offline!</b>";// Write messages to the chat receiving area
remote.jsjac.chat.writeMessage("", "system", html);}},// Establishing Link Triggering Event Method
handleConnected: function () {
remote.console.clear("debug"); // resetremote.connection.send(new JSJaCPresence());
},// Disconnecting Link Triggering Event Method
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;}};The code for this file is to use jsjac Library and openfire The core code for establishing communication has been commented in the code, so I will not go into it here. If you don't know anything, you can leave a message for me.
4,Message area, editor code 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 = {
// Get the window object of iframe
getWin: function () {
return /*!/firefox/.test(agent)*/false ? sendMessageEditor.iframe.contentWindow : window.frames[sendMessageEditor.iframe.name];},//Get the document object of iframe
getDoc: function () {
return !/firefox/.test(agent) ? sendMessageEditor.getWin().document : (sendMessageEditor.iframe.contentDocument || sendMessageEditor.getWin().document);
},init: function (userJID) {
//Open the document object and write initialization to it to be compatible with 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);//Open document object editing mode
doc.designMode = "on";
doc.close();},getContent: function () {
var doc = sendMessageEditor.getDoc();
//Get the body object of the editor
var body = doc.body || doc.documentElement;
//Get the content of the editor
var content = body.innerHTML;
//Processing content, such as replacing some special characters, etc.
//Some code
//Return content
return content;
},//A Unified Method of Executing Commands
execCmd: function (cmd, value, d){
var doc = d || sendMessageEditor.getDoc();
//The doc object is retrieved with reference to the above code
//Call the execCommand method to execute commands
doc.execCommand(cmd, false, value === undefined ? null : value);},getStyleState: function (cmd) {
var doc = sendMessageEditor.getDoc();
//The doc object gets reference to the opposite side above
//Is the cursor bold?
var state = doc.queryCommandState(cmd);
if(state){
//Change the style of the button
}return state;
},insertAtCursor: function (text, d, w){
var doc = d || sendMessageEditor.getDoc();
var win = w || sendMessageEditor.getWin();
//Get the win object to refer to the code above
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 style chat-2.0.css
/**
* function: im web chat css
* author: hoojo
* createDate: 2012-5-26 11:42:10 a.m.
*/
@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;}/* Shrink strip */
#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;}/*########### Receiving Message Area \\\\\\\\\\\\\\ */
#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;}/* ############## Toolbar 6550 */
#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;}/* ###### Expressions \\\\\\\\\\\ */
#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 Configuration
<?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>
So far, all the code of this application has been posted, if you follow the structure of my side should be able to complete the chat application. If you have any questions or ideas, please leave me a message or comment!
For reproducing, please indicate the address of this article: JavaScript/jQuery, HTML and CSS to Build Web IM Remote and Timely Chat Communication Program