HTML5基于websocket的仿微信聊天,即时聊天IM前后端实现,简易聊天室源代码分享
部分截图:
部分源码:
html部分
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>WebIM-DEMO</title>
<link rel="stylesheet" href="css/bootstrap.css" />
<script src="sdk/jquery-1.11.1.js"></script>
<script src="sdk/strophe.js"></script>
<script src="sdk/json2.js"></script>
<script src="sdk/easemob.im-1.0.7.js"></script>
<script src="easemob.im.config.js"></script>
<script src="bootstrap.js"></script>
<link rel="stylesheet" href="css/webim.css" />
<!--[if lte IE 9]>
<script src="sdk/jplayer/jquery.jplayer.min.js"></script>
<script src="sdk/swfupload/swfupload.js"></script>
<![endif]-->
<script type="text/javascript">
var curUserId = null;
var curChatUserId = null;
var conn = null;
var curRoomId = null;
var msgCardDivId = "chat01";
var talkToDivId = "talkTo";
var talkInputId = "talkInputId";
var fileInputId = "fileInput";
var bothRoster = [];
var toRoster = [];
var maxWidth = 200;
var groupFlagMark = "group--";
var groupQuering = false;
var textSending = false;
var time = 0;
var swfupload = null;
var flashFilename = '';
var audioDom = [];
//处理不支持<audio>标签的浏览器,当前只支持MP3
var playAudioShim = function(dom, url, t) {
var d = $(dom),
play = d.next(),
pause = play.next(),
u = url;
if(!d.jPlayer) return;
Easemob.im.Helper.getIEVersion() < 9 && audioDom.push(d);
d.jPlayer({
ready: function () {
$(this).jPlayer("setMedia", {
mp3: u
});
},
solution: (Easemob.im.Helper.getIEVersion() != 9 ? "html, flash" : "flash"),
swfPath: "sdk/jplayer",
supplied: "mp3",
ended: function() {
pause.hide();
play.show();
}
});
play.on('click', function(){
d.jPlayer('play');
play.hide();
pause.show();
});
pause.on('click', function(){
d.jPlayer('pause');
play.show();
pause.hide();
});
}
//处理不支持异步上传的浏览器,使用swfupload作为解决方案
var uploadType = null;
var uploadShim = function(fileInputId) {
var pageTitle = document.title;
var uploadBtn = $('#' + fileInputId);
if(typeof SWFUpload === 'undefined' || uploadBtn.length < 1) return;
return new SWFUpload({
file_post_name: 'file'
, flash_url: "sdk/swfupload/swfupload.swf"
, button_placeholder_id: fileInputId
, button_width: uploadBtn.width() || 120
, button_height: uploadBtn.height() || 30
, button_cursor: SWFUpload.CURSOR.HAND
, button_text: '点击上传'
, button_window_mode: SWFUpload.WINDOW_MODE.TRANSPARENT
, file_size_limit: 10485760
, file_upload_limit: 0
, file_queued_handler: function(file) {
if(this.getStats().files_queued > 1) {
this.cancelUpload();
}
var checkType = uploadType === 'audio' ? audtype : pictype;
if(!checkType[file.type.slice(1)]) {
conn.onError({
type : EASEMOB_IM_UPLOADFILE_ERROR,
msg : '不支持此文件类型' + file.type
});
this.setButtonText('点击上传');
this.cancelUpload();
} else if(10485760 < file.size) {
conn.onError({
type : EASEMOB_IM_UPLOADFILE_ERROR,
msg : '文件大小超过限制!请上传大小不超过10M的文件'
});
this.setButtonText('点击上传');
this.cancelUpload();
} else {
this.setButtonText(file.name);
flashFilename = file.name;
}
}
, file_dialog_start_handler: function() {
if(Easemob.im.Helper.getIEVersion() < 10) {
document.title = pageTitle;
}
}
, upload_error_handler: function(file, code, msg){
if(code != SWFUpload.UPLOAD_ERROR.FILE_CANCELLED && code != SWFUpload.UPLOAD_ERROR.UPLOAD_LIMIT_EXCEEDED && code != SWFUpload.UPLOAD_ERROR.FILE_VALIDATION_FAILED) {
this.uploadOptions.onFileUploadError && this.uploadOptions.onFileUploadError({type: EASEMOB_IM_UPLOADFILE_ERROR, msg: msg});
}
}
, upload_complete_handler: function(){
this.setButtonText('点击上传');
}
, upload_success_handler: function(file, response){
//处理上传成功的回调
try{
var res = Easemob.im.Helper.parseUploadResponse(response);
res = $.parseJSON(res);
res.filename = file.name;
this.uploadOptions.onFileUploadComplete && this.uploadOptions.onFileUploadComplete(res);
} catch (e) {
conn.onError({
type : EASEMOB_IM_UPLOADFILE_ERROR,
msg : '上传图片发生错误'
});
}
}
});
}
//提供上传接口
var flashUpload = function(url, options){
if(swfupload.settings.button_text == '点击上传') {
conn.onError({
type : EASEMOB_IM_UPLOADFILE_ERROR,
msg : '请选择文件'
});
return;
}
swfupload.setUploadURL(url);
swfupload.uploadOptions = options;
swfupload.startUpload();
}
window.URL = window.URL || window.webkitURL || window.mozURL
|| window.msURL;
var getLoginInfo = function() {
return {
isLogin : false
};
};
var showLoginUI = function() {
$('#loginmodal').modal('show');
$('#username').focus();
};
var hiddenLoginUI = function() {
$('#loginmodal').modal('hide');
};
var showWaitLoginedUI = function() {
$('#waitLoginmodal').modal('show');
};
var hiddenWaitLoginedUI = function() {
$('#waitLoginmodal').modal('hide');
};
var showChatUI = function() {
$('#content').css({
"display" : "block"
});
var login_userEle = document.getElementById("login_user").children[0];
login_userEle.innerHTML = curUserId;
login_userEle.setAttribute("title", curUserId);
};
//登录之前不显示web对话框
var hiddenChatUI = function() {
$('#content').css({
"display" : "none"
});
document.getElementById(talkInputId).value = "";
};
//定义消息编辑文本域的快捷键,enter和ctrl+enter为发送,alt+enter为换行
//控制提交频率
$(function() {
$("textarea").keydown(function(event) {
if (event.altKey && event.keyCode == 13) {
e = $(this).val();
$(this).val(e + '\n');
} else if (event.ctrlKey && event.keyCode == 13) {
//e = $(this).val();
//$(this).val(e + '<br>');
event.returnValue = false;
sendText();
return false;
} else if (event.keyCode == 13) {
event.returnValue = false;
sendText();
return false;
}
});
$("#usetoken").on("click", function(){
if ($("#password").attr("disabled")) {
$("#password").removeAttr("disabled");
} else {
$("#password").attr("disabled", "disabled");
}
if ($("#token").attr("disabled")) {
$("#token").removeAttr("disabled");
} else {
$("#token").attr("disabled", "disabled");
}
});
});
//easemobwebim-sdk注册回调函数列表
$(document).ready(function() {
if(!Easemob.im.Helper.isCanUploadFileAsync && typeof uploadShim === 'function') {
swfupload = uploadShim('fileInput');
}
handleConfig();
conn = new Easemob.im.Connection();
//初始化连接
conn.init({
https : Easemob.im.config.https,
url: Easemob.im.config.xmppURL,
//当连接成功时的回调方法
onOpened : function() {
handleOpen(conn);
},
//当连接关闭时的回调方法
onClosed : function() {
handleClosed();
},
//收到文本消息时的回调方法
onTextMessage : function(message) {
handleTextMessage(message);
},
//收到表情消息时的回调方法
onEmotionMessage : function(message) {
handleEmotion(message);
},
//收到图片消息时的回调方法
onPictureMessage : function(message) {
handlePictureMessage(message);
},
//收到音频消息的回调方法
onAudioMessage : function(message) {
handleAudioMessage(message);
},
//收到位置消息的回调方法
onLocationMessage : function(message) {
handleLocationMessage(message);
},
//收到文件消息的回调方法
onFileMessage : function(message) {
handleFileMessage(message);
},
//收到视频消息的回调方法
onVideoMessage : function(message) {
handleVideoMessage(message);
},
//收到联系人订阅请求的回调方法
onPresence : function(message) {
handlePresence(message);
},
//收到联系人信息的回调方法
onRoster : function(message) {
handleRoster(message);
},
//收到群组邀请时的回调方法
onInviteMessage : function(message) {
handleInviteMessage(message);
},
//异常时的回调方法
onError : function(message) {
handleError(message);
}
});
var loginInfo = getLoginInfo();
if (loginInfo.isLogin) {
showWaitLoginedUI();
} else {
showLoginUI();
}
//发送文件的模态窗口
$('#fileModal').on('hidden.bs.modal', function(e) {
document.getElementById("fileSend").disabled = false;
document.getElementById("cancelfileSend").disabled = false;
if(!Easemob.im.Helper.isCanUploadFileAsync) return;
var ele = document.getElementById(fileInputId);
ele.value = "";
if (!window.addEventListener) {
ele.outerHTML = ele.outerHTML;
}
});
$('#addFridentModal').on('hidden.bs.modal', function(e) {
var ele = document.getElementById("addfridentId");
ele.value = "";
if (!window.addEventListener) {
ele.outerHTML = ele.outerHTML;
}
document.getElementById("addFridend").disabled = false;
document.getElementById("cancelAddFridend").disabled = false;
});
$('#delFridentModal').on('hidden.bs.modal', function(e) {
var ele = document.getElementById("delfridentId");
ele.value = "";
if (!window.addEventListener) {
ele.outerHTML = ele.outerHTML;
}
document.getElementById("delFridend").disabled = false;
document.getElementById("canceldelFridend").disabled = false;
});
$('#confirm-block-div-modal').on('hidden.bs.modal', function(e) {
});
$('#option-room-div-modal').on('hidden.bs.modal', function(e) {
});
$('#notice-block-div').on('hidden.bs.modal', function(e) {
});
$('#regist-div-modall').on('hidden.bs.modal', function(e) {
});
//在 密码输入框时的回车登录
$('#password').keypress(function(e) {
var key = e.which;
if (key == 13) {
login();
}
});
$(function() {
$(window).bind('beforeunload', function() {
if (conn) {
conn.close();
if (navigator.userAgent.indexOf("Firefox") > 0)
return ' ';
else
return '';
}
});
});
});
var handleConfig = function() {
if(Easemob.im.Helper.getIEVersion() < 10) {
Easemob.im.config.https = location.protocol == 'https:' ? true : false;
if(!Easemob.im.config.https) {
if(Easemob.im.config.xmppURL.indexOf('https') == 0) {
Easemob.im.config.xmppURL = Easemob.im.config.xmppURL.replace(/^https/, 'http');
}
if(Easemob.im.config.apiURL.indexOf('https') == 0) {
Easemob.im.config.apiURL = Easemob.im.config.apiURL.replace(/^https/, 'http');
}
} else {
if(Easemob.im.config.xmppURL.indexOf('https') != 0) {
Easemob.im.config.xmppURL = Easemob.im.config.xmppURL.replace(/^http/, 'https');
}
if(Easemob.im.config.apiURL.indexOf('https') != 0) {
Easemob.im.config.apiURL = Easemob.im.config.apiURL.replace(/^http/, 'https');
}
}
}
}
//处理连接时函数,主要是登录成功后对页面元素做处理
var handleOpen = function(conn) {
//从连接中获取到当前的登录人注册帐号名
curUserId = conn.context.userId;
//获取当前登录人的联系人列表
conn.getRoster({
success : function(roster) {
// 页面处理
hiddenWaitLoginedUI();
showChatUI();
var curroster;
for ( var i in roster) {
var ros = roster[i];
//both为双方互为好友,要显示的联系人,from我是对方的单向好友
if (ros.subscription == 'both'
|| ros.subscription == 'from') {
bothRoster.push(ros);
} else if (ros.subscription == 'to') {
//to表明了联系人是我的单向好友
toRoster.push(ros);
}
}
if (bothRoster.length > 0) {
curroster = bothRoster[0];
buildContactDiv("contractlist", bothRoster);//联系人列表页面处理
if (curroster)
setCurrentContact(curroster.name);//页面处理将第一个联系人作为当前聊天div
}
//获取当前登录人的群组列表
conn.listRooms({
success : function(rooms) {
if (rooms && rooms.length > 0) {
buildListRoomDiv("contracgrouplist", rooms);//群组列表页面处理
if (curChatUserId == null) {
setCurrentContact(groupFlagMark
+ rooms[0].roomId);
$('#accordion2').click();
}
}
conn.setPresence();//设置用户上线状态,必须调用
},
error : function(e) {
}
});
}
});
//启动心跳
if (conn.isOpened()) {
conn.heartBeat(conn);
}
};
//连接中断时的处理,主要是对页面进行处理
var handleClosed = function() {
curUserId = null;
curChatUserId = null;
curRoomId = null;
bothRoster = [];
toRoster = [];
hiddenChatUI();
for(var i=0,l=audioDom.length;i<l;i++) {
if(audioDom[i].jPlayer) audioDom[i].jPlayer('destroy');
}
clearContactUI("contactlistUL", "contactgrouplistUL",
"momogrouplistUL", msgCardDivId);
showLoginUI();
groupQuering = false;
textSending = false;
};
//easemobwebim-sdk中收到联系人订阅请求的处理方法,具体的type值所对应的值请参考xmpp协议规范
var handlePresence = function(e) {
//(发送者希望订阅接收者的出席信息),即别人申请加你为好友
if (e.type == 'subscribe') {
if (e.status) {
if (e.status.indexOf('resp:true') > -1) {
agreeAddFriend(e.from);
return;
}
}
var subscribeMessage = e.from + "请求加你为好友。\n验证消息:" + e.status;
showNewNotice(subscribeMessage);
$('#confirm-block-footer-confirmButton').click(function() {
//同意好友请求
agreeAddFriend(e.from);//e.from用户名
//反向添加对方好友
conn.subscribe({
to : e.from,
message : "[resp:true]"
});
$('#confirm-block-div-modal').modal('hide');
});
$('#confirm-block-footer-cancelButton').click(function() {
rejectAddFriend(e.from);//拒绝加为好友
$('#confirm-block-div-modal').modal('hide');
});
return;
}
//(发送者允许接收者接收他们的出席信息),即别人同意你加他为好友
if (e.type == 'subscribed') {
toRoster.push({
name : e.from,
jid : e.fromJid,
subscription : "to"
});
return;
}
//(发送者取消订阅另一个实体的出席信息),即删除现有好友
if (e.type == 'unsubscribe') {
//单向删除自己的好友信息,具体使用时请结合具体业务进行处理
delFriend(e.from);
return;
}
//(订阅者的请求被拒绝或以前的订阅被取消),即对方单向的删除了好友
if (e.type == 'unsubscribed') {
delFriend(e.from);
return;
}
};
//easemobwebim-sdk中处理出席状态操作
var handleRoster = function(rosterMsg) {
for (var i = 0; i < rosterMsg.length; i++) {
var contact = rosterMsg[i];
if (contact.ask && contact.ask == 'subscribe') {
continue;
}
if (contact.subscription == 'to') {
toRoster.push({
name : contact.name,
jid : contact.jid,
subscription : "to"
});
}
//app端删除好友后web端要同时判断状态from做删除对方的操作
if (contact.subscription == 'from') {
toRoster.push({
name : contact.name,
jid : contact.jid,
subscription : "from"
});
}
if (contact.subscription == 'both') {
var isexist = contains(bothRoster, contact);
if (!isexist) {
var lielem = $('<li>').attr({
"id" : contact.name,
"class" : "offline",
"className" : "offline"
}).click(function() {
chooseContactDivClick(this);
});
$('<img>').attr({
"src" : "img/head/contact_normal.png"
}).appendTo(lielem);
$('<span>').html(contact.name).appendTo(lielem);
$('#contactlistUL').append(lielem);
bothRoster.push(contact);
}
}
if (contact.subscription == 'remove') {
var isexist = contains(bothRoster, contact);
if (isexist) {
removeFriendDomElement(contact.name);
}
}
}
};
//异常情况下的处理方法
var handleError = function(e) {
e && e.upload && $('#fileModal').modal('hide');
if (curUserId == null) {
hiddenWaitLoginedUI();
alert(e.msg + ",请重新登录");
showLoginUI();
} else {
var msg = e.msg;
if (e.type == EASEMOB_IM_CONNCTION_SERVER_CLOSE_ERROR) {
if (msg == "" || msg == 'unknown' ) {
alert("服务器断开连接,可能是因为在别处登录");
} else {
alert("服务器断开连接");
}
} else if (e.type === EASEMOB_IM_CONNCTION_SERVER_ERROR) {
if (msg.toLowerCase().indexOf("user removed") != -1) {
alert("用户已经在管理后台删除");
}
} else {
alert(msg);
}
}
conn.stopHeartBeat(conn);
};
//判断要操作的联系人和当前联系人列表的关系
var contains = function(roster, contact) {
var i = roster.length;
while (i--) {
if (roster[i].name === contact.name) {
return true;
}
}
return false;
};
Array.prototype.indexOf = function(val) {
for (var i = 0; i < this.length; i++) {
if (this[i].name == val.name)
return i;
}
return -1;
};
Array.prototype.remove = function(val) {
var index = this.indexOf(val);
if (index > -1) {
this.splice(index, 1);
}
};
//登录系统时的操作方法
var login = function() {
if ($("#usetoken").is(":checked")) {
var user = $("#username").val();
var token = $("#token").val();
if (user == '' || token == '') {
alert("请输入用户名和令牌");
return;
}
hiddenLoginUI();
showWaitLoginedUI();
//根据用户名令牌登录系统
conn.open({
apiUrl : Easemob.im.config.apiURL,
user : user,
accessToken : token,
//连接时提供appkey
appKey : Easemob.im.config.appkey
});
} else {
var user = $("#username").val();
var pass = $("#password").val();
if (user == '' || pass == '') {
alert("请输入用户名和密码");
return;
}
hiddenLoginUI();
showWaitLoginedUI();
//根据用户名密码登录系统
conn.open({
apiUrl : Easemob.im.config.apiURL,
user : user,
pwd : pass,
//连接时提供appkey
appKey : Easemob.im.config.appkey
});
}
return false;
};
//注册新用户操作方法
var regist = function() {
var user = $("#regist_username").val();
var pass = $("#regist_password").val();
var nickname = $("#regist_nickname").val();
if (user == '' || pass == '' || nickname == '') {
alert("用户名/密码/昵称 不能为空");
return;
}
var options = {
username : user,
password : pass,
nickname : nickname,
appKey : Easemob.im.config.appkey,
success : function(result) {
alert("注册成功!");
$('#loginmodal').modal('show');
$('#regist-div-modal').modal('hide');
},
error : function(e) {
alert(e.error);
},
apiUrl : Easemob.im.config.apiURL
};
Easemob.im.Helper.registerUser(options);
};
//注册页面返回登录页面操作
var showlogin = function() {
$('#loginmodal').modal('show');
$('#regist-div-modal').modal('hide');
};
var logout = function() {
conn.stopHeartBeat(conn);
conn.close();
};
//设置当前显示的聊天窗口div,如果有联系人则默认选中联系人中的第一个联系人,如没有联系人则当前div为null-nouser
var setCurrentContact = function(defaultUserId) {
showContactChatDiv(defaultUserId);
if (curChatUserId != null) {
hiddenContactChatDiv(curChatUserId);
} else {
$('#null-nouser').css({
"display" : "none"
});
}
curChatUserId = defaultUserId;
};
//构造联系人列表
var buildContactDiv = function(contactlistDivId, roster) {
var uielem = document.getElementById("contactlistUL");
var cache = {};
for (i = 0; i < roster.length; i++) {
if (!(roster[i].subscription == 'both' || roster[i].subscription == 'from')) {
continue;
}
var jid = roster[i].jid;
var userName = jid.substring(jid.indexOf("_") + 1).split("@")[0];
if (userName in cache) {
continue;
}
cache[userName] = true;
var lielem = $('<li>').attr({
'id' : userName,
'class' : 'offline',
'className' : 'offline',
'type' : 'chat',
'displayName' : userName
}).click(function() {
chooseContactDivClick(this);
});
$('<img>').attr("src", "img/head/contact_normal.png").appendTo(
lielem);
$('<span>').html(userName).appendTo(lielem);
$('#contactlistUL').append(lielem);
}
var contactlist = document.getElementById(contactlistDivId);
var children = contactlist.children;
if (children.length > 0) {
contactlist.removeChild(children[0]);
}
contactlist.appendChild(uielem);
};
//构造群组列表
var buildListRoomDiv = function(contactlistDivId, rooms) {
var uielem = document.getElementById("contactgrouplistUL");
var cache = {};
for (i = 0; i < rooms.length; i++) {
var roomsName = rooms[i].name;
var roomId = rooms[i].roomId;
if (roomId in cache) {
continue;
}
cache[roomId] = true;
var lielem = $('<li>').attr({
'id' : groupFlagMark + roomId,
'class' : 'offline',
'className' : 'offline',
'type' : 'groupchat',
'displayName' : roomsName,
'roomId' : roomId,
'joined' : 'false'
}).click(function() {
chooseContactDivClick(this);
});
$('<img>').attr({
'src' : 'img/head/group_normal.png'
}).appendTo(lielem);
$('<span>').html(roomsName).appendTo(lielem);
$('#contactgrouplistUL').append(lielem);
}
var contactlist = document.getElementById(contactlistDivId);
var children = contactlist.children;
if (children.length > 0) {
contactlist.removeChild(children[0]);
}
contactlist.appendChild(uielem);
};
//选择联系人的处理
var getContactLi = function(chatUserId) {
return document.getElementById(chatUserId);
};
//构造当前聊天记录的窗口div
var getContactChatDiv = function(chatUserId) {
return document.getElementById(curUserId + "-" + chatUserId);
};
//如果当前没有某一个联系人的聊天窗口div就新建一个
var createContactChatDiv = function(chatUserId) {
var msgContentDivId = curUserId + "-" + chatUserId;
var newContent = document.createElement("div");
$(newContent).attr({
"id" : msgContentDivId,
"class" : "chat01_content",
"className" : "chat01_content",
"style" : "display:none"
});
return newContent;
};
//显示当前选中联系人的聊天窗口div,并将该联系人在联系人列表中背景色置为蓝色
var showContactChatDiv = function(chatUserId) {
var contentDiv = getContactChatDiv(chatUserId);
if (contentDiv == null) {
contentDiv = createContactChatDiv(chatUserId);
document.getElementById(msgCardDivId).appendChild(contentDiv);
}
contentDiv.style.display = "block";
var contactLi = document.getElementById(chatUserId);
if (contactLi == null) {
return;
}
contactLi.style.backgroundColor = "#33CCFF";
var dispalyTitle = null;//聊天窗口显示当前对话人名称
if (chatUserId.indexOf(groupFlagMark) >= 0) {
dispalyTitle = "群组" + $(contactLi).attr('displayname') + "聊天中";
curRoomId = $(contactLi).attr('roomid');
$("#roomMemberImg").css('display', 'block');
} else {
dispalyTitle = "与" + chatUserId + "聊天中";
$("#roomMemberImg").css('display', 'none');
}
document.getElementById(talkToDivId).children[0].innerHTML = dispalyTitle;
};
//对上一个联系人的聊天窗口div做隐藏处理,并将联系人列表中选择的联系人背景色置空
var hiddenContactChatDiv = function(chatUserId) {
var contactLi = document.getElementById(chatUserId);
if (contactLi) {
contactLi.style.backgroundColor = "";
}
var contentDiv = getContactChatDiv(chatUserId);
if (contentDiv) {
contentDiv.style.display = "none";
}
};
//切换联系人聊天窗口div
var chooseContactDivClick = function(li) {
var chatUserId = li.id;
if ($(li).attr("type") == 'groupchat'
&& ('true' != $(li).attr("joined"))) {
conn.join({
roomId : $(li).attr("roomId")
});
$(li).attr("joined", "true");
}
if (chatUserId != curChatUserId) {
if (curChatUserId == null) {
showContactChatDiv(chatUserId);
} else {
showContactChatDiv(chatUserId);
hiddenContactChatDiv(curChatUserId);
}
curChatUserId = chatUserId;
}
//对默认的null-nouser div进行处理,走的这里说明联系人列表肯定不为空所以对默认的聊天div进行处理
$('#null-nouser').css({
"display" : "none"
});
var badgespan = $(li).children(".badge");
if (badgespan && badgespan.length > 0) {
li.removeChild(li.children[2]);
}
//点击有未读消息对象时对未读消息提醒的处理
var badgespanGroup = $(li).parent().parent().parent().find(".badge");
if (badgespanGroup && badgespanGroup.length == 0) {
$(li).parent().parent().parent().prev().children().children()
.remove();
}
};
var clearContactUI = function(contactlistUL, contactgrouplistUL,
momogrouplistUL, contactChatDiv) {
//清除左侧联系人内容
$('#contactlistUL').empty();
$('#contactgrouplistUL').empty();
$('#momogrouplistUL').empty();
//处理联系人分组的未读消息处理
var accordionChild = $('#accordionDiv').children();
for (var i = 1; i <= accordionChild.length; i++) {
var badgegroup = $('#accordion' + i).find(".badgegroup");
if (badgegroup && badgegroup.length > 0) {
$('#accordion' + i).children().remove();
}
}
;
//清除右侧对话框内容
document.getElementById(talkToDivId).children[0].innerHTML = "";
var chatRootDiv = document.getElementById(contactChatDiv);
var children = chatRootDiv.children;
for (var i = children.length - 1; i > 1; i--) {
chatRootDiv.removeChild(children[i]);
}
$('#null-nouser').css({
"display" : "block"
});
};
var emotionFlag = false;
var showEmotionDialog = function() {
if (emotionFlag) {
$('#wl_faces_box').css({
"display" : "block"
});
return;
}
emotionFlag = true;
// Easemob.im.Helper.EmotionPicData设置表情的json数组
var sjson = Easemob.im.Helper.EmotionPicData;
for ( var key in sjson) {
var emotions = $('<img>').attr({
"id" : key,
"src" : sjson[key],
"style" : "cursor:pointer;"
}).click(function() {
selectEmotionImg(this);
});
$('<li>').append(emotions).appendTo($('#emotionUL'));
}
$('#wl_faces_box').css({
"display" : "block"
});
};
//表情选择div的关闭方法
var turnoffFaces_box = function() {
$("#wl_faces_box").fadeOut("slow");
};
var selectEmotionImg = function(selImg) {
var txt = document.getElementById(talkInputId);
txt.value = txt.value + selImg.id;
txt.focus();
};
var showSendPic = function() {
$('#fileModal').modal('toggle');
$('#sendfiletype').val('pic');
$('#send-file-warning').html("");
uploadType = 'pic';
};
var showSendAudio = function() {
$('#fileModal').modal('toggle');
$('#sendfiletype').val('audio');
$('#send-file-warning').html("");
uploadType = 'audio';
};
var sendText = function() {
if (textSending) {
return;
}
textSending = true;
var msgInput = document.getElementById(talkInputId);
var msg = msgInput.value;
if (msg == null || msg.length == 0) {
return;
}
var to = curChatUserId;
if (to == null) {
return;
}
var options = {
to : to,
msg : msg,
type : "chat"
};
// 群组消息和个人消息的判断分支
if (curChatUserId.indexOf(groupFlagMark) >= 0) {
options.type = 'groupchat';
options.to = curRoomId;
}
//easemobwebim-sdk发送文本消息的方法 to为发送给谁,meg为文本消息对象
conn.sendTextMessage(options);
//当前登录人发送的信息在聊天窗口中原样显示
var msgtext = msg.replace(/\n/g, '<br>');
appendMsg(curUserId, to, msgtext);
turnoffFaces_box();
msgInput.value = "";
msgInput.focus();
setTimeout(function() {
textSending = false;
}, 1000);
};
var pictype = {
"jpg" : true,
"gif" : true,
"png" : true,
"bmp" : true
};
var sendFile = function() {
var type = $("#sendfiletype").val();
if (type == 'pic') {
sendPic();
} else {
sendAudio();
}
};
//发送图片消息时调用方法
var sendPic = function() {
var to = curChatUserId;
if (to == null) {
return;
}
// Easemob.im.Helper.getFileUrl为easemobwebim-sdk获取发送文件对象的方法,fileInputId为 input 标签的id值
var fileObj = Easemob.im.Helper.getFileUrl(fileInputId);
if (Easemob.im.Helper.isCanUploadFileAsync && (fileObj.url == null || fileObj.url == '')) {
$('#send-file-warning').html("<font color='#FF0000'>请选择发送图片</font>");
return;
}
var filetype = fileObj.filetype;
var filename = fileObj.filename;
if (!Easemob.im.Helper.isCanUploadFileAsync || filetype in pictype) {
document.getElementById("fileSend").disabled = true;
document.getElementById("cancelfileSend").disabled = true;
var opt = {
type : 'chat',
fileInputId : fileInputId,
filename : flashFilename || '',
to : to,
apiUrl: Easemob.im.config.apiURL,
onFileUploadError : function(error) {
$('#fileModal').modal('hide');
var messageContent = (error.msg || '') + ",发送图片文件失败:" + (filename||flashFilename);
appendMsg(curUserId, to, messageContent);
},
onFileUploadComplete : function(data) {
var file = document.getElementById(fileInputId);
if (file && file.files) {
var objUrl = getObjectURL(file.files[0]);
if (objUrl) {
var img = document.createElement("img");
img.src = objUrl;
img.width = maxWidth;
}
} else {
filename = data.filename || '';
var img = document.createElement("img");
img.src = data.uri + '/' + data.entities[0].uuid + '?token=';
img.width = maxWidth;
}
appendMsg(curUserId, to, {
data : [ {
type : 'pic',
filename : (filename||flashFilename),
data : img
} ]
});
$('#fileModal').modal('hide');
},
flashUpload: flashUpload
};
if (curChatUserId.indexOf(groupFlagMark) >= 0) {
opt.type = 'groupchat';
opt.to = curRoomId;
}
conn.sendPicture(opt);
return;
}
$('#send-file-warning').html("<font color='#FF0000'>不支持此图片类型" + filetype + "</font>");
};
var audtype = {
"mp3" : true,
"wma" : true,
"wav" : true,
"amr" : true,
"avi" : true
};
//发送音频消息时调用的方法
var sendAudio = function() {
var to = curChatUserId;
if (to == null) {
return;
}
//利用easemobwebim-sdk提供的方法来构造一个file对象
var fileObj = Easemob.im.Helper.getFileUrl(fileInputId);
if (Easemob.im.Helper.isCanUploadFileAsync && (fileObj.url == null || fileObj.url == '')) {
$('#send-file-warning').html("<font color='#FF0000'>请选择发送音频</font>");
return;
}
var filetype = fileObj.filetype;
var filename = fileObj.filename;
if (!Easemob.im.Helper.isCanUploadFileAsync || filetype in audtype) {
document.getElementById("fileSend").disabled = true;
document.getElementById("cancelfileSend").disabled = true;
var opt = {
type : "chat",
fileInputId : fileInputId,
filename : flashFilename || '',
to : to,//发给谁
apiUrl: Easemob.im.config.apiURL,
onFileUploadError : function(error) {
$('#fileModal').modal('hide');
var messageContent = (error.msg || '') + ",发送音频失败:" + (filename || flashFilename);
appendMsg(curUserId, to, messageContent);
},
onFileUploadComplete : function(data) {
var messageContent = "发送音频" + (filename || flashFilename);
$('#fileModal').modal('hide');
appendMsg(curUserId, to, messageContent);
},
flashUpload: flashUpload
};
//构造完opt对象后调用easemobwebim-sdk中发送音频的方法
if (curChatUserId.indexOf(groupFlagMark) >= 0) {
opt.type = 'groupchat';
opt.to = curRoomId;
}
conn.sendAudio(opt);
return;
}
$('#send-file-warning').html("<font color='#FF0000'>不支持此音频类型" + filetype + "</font>");
};
//easemobwebim-sdk收到文本消息的回调方法的实现
var handleTextMessage = function(message) {
var from = message.from;//消息的发送者
var mestype = message.type;//消息发送的类型是群组消息还是个人消息
var messageContent = message.data;//文本消息体
//TODO 根据消息体的to值去定位那个群组的聊天记录
var room = message.to;
if (mestype == 'groupchat') {
appendMsg(message.from, message.to, messageContent, mestype);
} else {
appendMsg(from, from, messageContent);
}
};
//easemobwebim-sdk收到表情消息的回调方法的实现,message为表情符号和文本的消息对象,文本和表情符号sdk中做了
//统一的处理,不需要用户自己区别字符是文本还是表情符号。
var handleEmotion = function(message) {
var from = message.from;
var room = message.to;
var mestype = message.type;//消息发送的类型是群组消息还是个人消息
if (mestype == 'groupchat') {
appendMsg(message.from, message.to, message, mestype);
} else {
appendMsg(from, from, message);
}
};
//easemobwebim-sdk收到图片消息的回调方法的实现
var handlePictureMessage = function(message) {
var filename = message.filename;//文件名称,带文件扩展名
var from = message.from;//文件的发送者
var mestype = message.type;//消息发送的类型是群组消息还是个人消息
var contactDivId = from;
if (mestype == 'groupchat') {
contactDivId = groupFlagMark + message.to;
}
var options = message;
// 图片消息下载成功后的处理逻辑
options.onFileDownloadComplete = function(response, xhr) {
var objectURL = Easemob.im.Helper.parseDownloadResponse.call(this, response);
img = document.createElement("img");
img.onload = function(e) {
img.onload = null;
window.URL && window.URL.revokeObjectURL && window.URL.revokeObjectURL(img.src);
};
img.onerror = function() {
img.onerror = null;
if (typeof FileReader == 'undefined') {
img.alter = "当前浏览器不支持blob方式";
return;
}
img.onerror = function() {
img.alter = "当前浏览器不支持blob方式";
};
var reader = new FileReader();
reader.onload = function(event) {
img.src = this.result;
};
reader.readAsDataURL(response);
}
img.src = objectURL;
var pic_real_width = options.width;
if (!pic_real_width || pic_real_width == 0) {
$("<img/>").attr("src", objectURL).load(function() {
pic_real_width = this.width;
if (pic_real_width > maxWidth) {
img.width = maxWidth;
} else {
img.width = pic_real_width;
}
appendMsg(from, contactDivId, {
data : [ {
type : 'pic',
filename : filename || '',
data : img
} ]
});
});
} else {
if (pic_real_width > maxWidth) {
img.width = maxWidth;
} else {
img.width = pic_real_width;
}
appendMsg(from, contactDivId, {
data : [ {
type : 'pic',
filename : filename || '',
data : img
} ]
});
}
};
var redownLoadFileNum = 0;
options.onFileDownloadError = function(e) {
//下载失败时只重新下载一次
if(redownLoadFileNum < 1){
redownLoadFileNum++;
options.accessToken = options_c;
Easemob.im.Helper.download(options);
}else{
appendMsg(from, contactDivId, e.msg + ",下载图片" + filename + "失败");
redownLoadFileNum = 0;
}
};
//easemobwebim-sdk包装的下载文件对象的统一处理方法。
Easemob.im.Helper.download(options);
};
//easemobwebim-sdk收到音频消息回调方法的实现
var handleAudioMessage = function(message) {
var filename = message.filename;
var filetype = message.filetype;
var from = message.from;
var mestype = message.type;//消息发送的类型是群组消息还是个人消息
var contactDivId = from;
if (mestype == 'groupchat') {
contactDivId = groupFlagMark + message.to;
}
var options = message;
options.onFileDownloadComplete = function(response, xhr) {
var objectURL = Easemob.im.Helper.parseDownloadResponse.call(this, response);
var audio = document.createElement("audio");
if (Easemob.im.Helper.getIEVersion() != 9 && ("src" in audio) && ("controls" in audio)) {
audio.onload = function() {
audio.onload = null;
window.URL && window.URL.revokeObjectURL && window.URL.revokeObjectURL(audio.src);
};
audio.onerror = function() {
audio.onerror = null;
appendMsg(from, contactDivId, "当前浏览器不支持播放此音频:" + (filename || ''));
};
audio.controls = "controls";
audio.src = objectURL;
appendMsg(from, contactDivId, {
data : [ {
type : 'audio',
filename : filename || '',
data : audio
} ]
});
//audio.play();
return;
} else {
appendMsg(from, contactDivId, {
data : [ {
type : 'audio',
filename : filename || '',
data : {currentSrc: objectURL},
audioShim: true
} ]
});
}
};
options.onFileDownloadError = function(e) {
appendMsg(from, contactDivId, e.msg + ",下载音频" + filename + "失败");
};
options.headers = {
"Accept" : "audio/mp3"
};
Easemob.im.Helper.download(options);
};
//处理收到文件消息
var handleFileMessage = function(message) {
var filename = message.filename;
var filetype = message.filetype;
var from = message.from;
var mestype = message.type;//消息发送的类型是群组消息还是个人消息
var contactDivId = from;
if (mestype == 'groupchat') {
contactDivId = groupFlagMark + message.to;
}
var options = message;
options.onFileDownloadComplete = function(response, xhr) {
var spans = "收到文件消息:" + filename;
appendMsg(from, contactDivId, spans);
return;
};
options.onFileDownloadError = function(e) {
appendMsg(from, contactDivId, e.msg + ",下载文件" + filename + "失败");
};
Easemob.im.Helper.download(options);
};
//收到视频消息
var handleVideoMessage = function(message) {
var filename = message.filename;
var filetype = message.filetype;
var from = message.from;
var mestype = message.type;//消息发送的类型是群组消息还是个人消息
var contactDivId = from;
if (mestype == 'groupchat') {
contactDivId = groupFlagMark + message.to;
}
var options = message;
options.onFileDownloadComplete = function(response, xhr) {
var spans = "收到视频消息:" + filename;
appendMsg(from, contactDivId, spans);
};
options.onFileDownloadError = function(e) {
appendMsg(from, contactDivId, e.msg + ",下载音频" + filename + "失败");
};
Easemob.im.Helper.download(options);
};
var handleLocationMessage = function(message) {
var from = message.from;
var to = message.to;
var mestype = message.type;
var content = message.addr;
if (mestype == 'groupchat') {
appendMsg(from, to, content, mestype);
} else {
appendMsg(from, from, content, mestype);
}
};
var handleInviteMessage = function(message) {
var type = message.type;
var from = message.from;
var roomId = message.roomid;
//获取当前登录人的群组列表
conn.listRooms({
success : function(rooms) {
if (rooms) {
for (i = 0; i < rooms.length; i++) {
var roomsName = rooms[i].name;
var roomId = rooms[i].roomId;
var existRoom = $('#contactgrouplistUL').children(
'#group--' + roomId);
if (existRoom && existRoom.length == 0) {
var lielem = $('<li>').attr({
'id' : groupFlagMark + roomId,
'class' : 'offline',
'className' : 'offline',
'type' : 'groupchat',
'displayName' : roomsName,
'roomId' : roomId,
'joined' : 'false'
}).click(function() {
chooseContactDivClick(this);
});
$('<img>').attr({
'src' : 'img/head/group_normal.png'
}).appendTo(lielem);
$('<span>').html(roomsName).appendTo(lielem);
$('#contactgrouplistUL').append(lielem);
//return;
}
}
//cleanListRoomDiv();//先将原群组列表中的内容清除,再将最新的群组列表加入
//buildListRoomDiv("contracgrouplist", rooms);//群组列表页面处理
}
},
error : function(e) {
}
});
};
var cleanListRoomDiv = function cleanListRoomDiv() {
$('#contactgrouplistUL').empty();
};
//收到陌生人消息时创建陌生人列表
var createMomogrouplistUL = function createMomogrouplistUL(who, message) {
var momogrouplistUL = document.getElementById("momogrouplistUL");
var cache = {};
if (who in cache) {
return;
}
cache[who] = true;
var lielem = document.createElement("li");
$(lielem).attr({
'id' : who,
'class' : 'offline',
'className' : 'offline',
'type' : 'chat',
'displayName' : who
});
lielem.onclick = function() {
chooseContactDivClick(this);
};
var imgelem = document.createElement("img");
imgelem.setAttribute("src", "img/head/contact_normal.png");
lielem.appendChild(imgelem);
var spanelem = document.createElement("span");
spanelem.innerHTML = who;
lielem.appendChild(spanelem);
momogrouplistUL.appendChild(lielem);
};
//显示聊天记录的统一处理方法
var appendMsg = function(who, contact, message, chattype) {
var contactUL = document.getElementById("contactlistUL");
var contactDivId = contact;
if (chattype && chattype == 'groupchat') {
contactDivId = groupFlagMark + contact;
}
var contactLi = getContactLi(contactDivId);
if (contactLi == null) {
createMomogrouplistUL(who, message);
}
// 消息体 {isemotion:true;body:[{type:txt,msg:ssss}{type:emotion,msg:imgdata}]}
var localMsg = null;
if (typeof message == 'string') {
localMsg = Easemob.im.Helper.parseTextMessage(message);
localMsg = localMsg.body;
} else {
localMsg = message.data;
}
var headstr = [ "<p1>" + who + " <span></span>" + " </p1>",
"<p2>" + getLoacalTimeString() + "<b></b><br/></p2>" ];
var header = $(headstr.join(''))
var lineDiv = document.createElement("div");
for (var i = 0; i < header.length; i++) {
var ele = header[i];
lineDiv.appendChild(ele);
}
var messageContent = localMsg;
for (var i = 0; i < messageContent.length; i++) {
var msg = messageContent[i];
var type = msg.type;
var data = msg.data;
if (type == "emotion") {
var eletext = "<p3><img src='" + data + "'/></p3>";
var ele = $(eletext);
for (var j = 0; j < ele.length; j++) {
lineDiv.appendChild(ele[j]);
}
} else if (type == "pic" || type == 'audio' || type == 'video') {
var filename = msg.filename;
var fileele = $("<p3>" + filename + "</p3><br>");
for (var j = 0; j < fileele.length; j++) {
lineDiv.appendChild(fileele[j]);
}
data.nodeType && lineDiv.appendChild(data);
if(type == 'audio' && msg.audioShim) {
var d = $(lineDiv),
t = new Date().getTime();
d.append($('<div class="'+t+'"></div>\
<button class="play'+t+'">播放</button><button style="display:none" class="play'+t+'">暂停</button>'));
}
} else {
var eletext = "<p3>" + data + "</p3>";
var ele = $(eletext);
ele[0].setAttribute("class", "chat-content-p3");
ele[0].setAttribute("className", "chat-content-p3");
if (curUserId == who) {
ele[0].style.backgroundColor = "#EBEBEB";
}
for (var j = 0; j < ele.length; j++) {
lineDiv.appendChild(ele[j]);
}
}
}
if (curChatUserId == null && chattype == null) {
setCurrentContact(contact);
if (time < 1) {
$('#accordion3').click();
time++;
}
}
if (curChatUserId && curChatUserId.indexOf(contact) < 0) {
var contactLi = getContactLi(contactDivId);
if (contactLi == null) {
return;
}
contactLi.style.backgroundColor = "green";
var badgespan = $(contactLi).children(".badge");
if (badgespan && badgespan.length > 0) {
var count = badgespan.text();
var myNum = new Number(count);
myNum++;
badgespan.text(myNum);
} else {
$(contactLi).append('<span class="badge">1</span>');
}
//联系人不同分组的未读消息提醒
var badgespanGroup = $(contactLi).parent().parent().parent().prev()
.children().children(".badgegroup");
if (badgespanGroup && badgespanGroup.length == 0) {
$(contactLi).parent().parent().parent().prev().children()
.append('<span class="badgegroup">New</span>');
}
}
var msgContentDiv = getContactChatDiv(contactDivId);
if (curUserId == who) {
lineDiv.style.textAlign = "right";
} else {
lineDiv.style.textAlign = "left";
}
var create = false;
if (msgContentDiv == null) {
msgContentDiv = createContactChatDiv(contactDivId);
create = true;
}
msgContentDiv.appendChild(lineDiv);
if (create) {
document.getElementById(msgCardDivId).appendChild(msgContentDiv);
}
if(type == 'audio' && msg.audioShim) {
setTimeout(function(){
playAudioShim(d.find('.'+t), data.currentSrc, t);
}, 0);
}
msgContentDiv.scrollTop = msgContentDiv.scrollHeight;
return lineDiv;
};
var showAddFriend = function() {
$('#addFridentModal').modal('toggle');
$('#addfridentId').val('好友账号');//输入好友账号
$('#add-frident-warning').html("");
};
//添加输入框鼠标焦点进入时清空输入框中的内容
var clearInputValue = function(inputId) {
$('#' + inputId).val('');
};
var showDelFriend = function() {
$('#delFridentModal').modal('toggle');
$('#delfridentId').val('好友账号');//输入好友账号
$('#del-frident-warning').html("");
};
//消息通知操作时条用的方法
var showNewNotice = function(message) {
$('#confirm-block-div-modal').modal('toggle');
$('#confirm-block-footer-body').html(message);
};
var showWarning = function(message) {
$('#notice-block-div').modal('toggle');
$('#notice-block-body').html(message);
};
//主动添加好友操作的实现方法
var startAddFriend = function() {
var user = $('#addfridentId').val();
if (user == '') {
$('#add-frident-warning').html(
"<font color='#FF0000'> 请输入好友名称</font>");
return;
}
if (bothRoster)
for (var i = 0; i < bothRoster.length; i++) {
if (bothRoster[i].name == user) {
$('#add-frident-warning').html(
"<font color='#FF0000'> 已是您的好友</font>");
return;
}
}
//发送添加好友请求
conn.subscribe({
to : user,
message : "加个好友呗-" + getLoacalTimeString()
});
$('#addFridentModal').modal('hide');
return;
};
//回调方法执行时同意添加好友操作的实现方法
var agreeAddFriend = function(user) {
conn.subscribed({
to : user,
message : "[resp:true]"
});
};
//拒绝添加好友的方法处理
var rejectAddFriend = function(user) {
conn.unsubscribed({
to : user,
message : getLoacalTimeString()
});
};
//直接调用删除操作时的调用方法
var directDelFriend = function() {
var user = $('#delfridentId').val();
if (validateFriend(user, bothRoster)) {
conn.removeRoster({
to : user,
success : function() {
conn.unsubscribed({
to : user
});
//删除操作成功时隐藏掉dialog
$('#delFridentModal').modal('hide');
},
error : function() {
$('#del-frident-warning').html(
"<font color='#FF0000'>删除联系人失败!</font>");
}
});
} else {
$('#del-frident-warning').html(
"<font color='#FF0000'>该用户不是你的好友!</font>");
}
};
//判断要删除的好友是否在当前好友列表中
var validateFriend = function(optionuser, bothRoster) {
for ( var deluser in bothRoster) {
if (optionuser == bothRoster[deluser].name) {
return true;
}
}
return false;
};
//回调方法执行时删除好友操作的方法处理
var delFriend = function(user) {
conn.removeRoster({
to : user,
groups : [ 'default' ],
success : function() {
conn.unsubscribed({
to : user
});
}
});
};
var removeFriendDomElement = function(userToDel, local) {
var contactToDel;
if (bothRoster.length > 0) {
for (var i = 0; i < bothRoster.length; i++) {
if (bothRoster[i].name == userToDel) {
contactToDel = bothRoster[i];
break;
}
}
}
if (contactToDel) {
bothRoster.remove(contactToDel);
}
// 隐藏删除好友窗口
if (local) {
$('#delFridentModal').modal('hide');
}
//删除通讯录
$('#' + userToDel).remove();
//删除聊天
var chatDivId = curUserId + "-" + userToDel;
var chatDiv = $('#' + chatDivId);
if (chatDiv) {
chatDiv.remove();
}
if (curChatUserId != userToDel) {
return;
} else {
var displayName = '';
//将第一个联系人作为当前聊天div
if (bothRoster.length > 0) {
curChatUserId = bothRoster[0].name;
$('#' + curChatUserId).css({
"background-color" : "#33CCFF"
});
var currentDiv = getContactChatDiv(curChatUserId)
|| createContactChatDiv(curChatUserId);
document.getElementById(msgCardDivId).appendChild(currentDiv);
$(currentDiv).css({
"display" : "block"
});
displayName = '与' + curChatUserId + '聊天中';
} else {
$('#null-nouser').css({
"display" : "block"
});
displayName = '';
}
$('#talkTo').html('<a href="#">' + displayName + '</a>');
}
};
//清除聊天记录
var clearCurrentChat = function clearCurrentChat() {
var currentDiv = getContactChatDiv(curChatUserId)
|| createContactChatDiv(curChatUserId);
currentDiv.innerHTML = "";
};
//显示成员列表
var showRoomMember = function showRoomMember() {
if (groupQuering) {
return;
}
groupQuering = true;
queryOccupants(curRoomId);
};
//根据roomId查询room成员列表
var queryOccupants = function queryOccupants(roomId) {
var occupants = [];
conn.queryRoomInfo({
roomId : roomId,
success : function(occs) {
if (occs) {
for (var i = 0; i < occs.length; i++) {
occupants.push(occs[i]);
}
}
conn.queryRoomMember({
roomId : roomId,
success : function(members) {
if (members) {
for (var i = 0; i < members.length; i++) {
occupants.push(members[i]);
}
}
showRoomMemberList(occupants);
groupQuering = false;
},
error : function() {
groupQuering = false;
}
});
},
error : function() {
groupQuering = false;
}
});
};
var showRoomMemberList = function showRoomMemberList(occupants) {
var list = $('#room-member-list')[0];
var childs = list.childNodes;
for (var i = childs.length - 1; i >= 0; i--) {
list.removeChild(childs.item(i));
}
for (i = 0; i < occupants.length; i++) {
var jid = occupants[i].jid;
var userName = jid.substring(jid.indexOf("_") + 1).split("@")[0];
var txt = $("<p></p>").text(userName);
$('#room-member-list').append(txt);
}
$('#option-room-div-modal').modal('toggle');
};
var showRegist = function showRegist() {
$('#loginmodal').modal('hide');
$('#regist-div-modal').modal('toggle');
};
var getObjectURL = function getObjectURL(file) {
var url = null;
if (window.createObjectURL != undefined) { // basic
url = window.createObjectURL(file);
} else if (window.URL != undefined) { // mozilla(firefox)
url = window.URL.createObjectURL(file);
} else if (window.webkitURL != undefined) { // webkit or chrome
url = window.webkitURL.createObjectURL(file);
}
return url;
};
var getLoacalTimeString = function getLoacalTimeString() {
var date = new Date();
var time = date.getHours() + ":" + date.getMinutes() + ":"
+ date.getSeconds();
return time;
}
</script>
</head>
<body>
<div id="loginmodal" class="modal hide in" role="dialog"
aria-hidden="true" data-backdrop="static">
<div class="modal-header">
<h3>用户登录</h3>
</div>
<div class="modal-body">
<table>
<tr>
<td width="65%">
<label for="username">用户名:</label>
<input type="text" name="username" value="" id="username" tabindex="1"/>
<label for="password">密码:</label>
<input type="password" name="password" value="" id="password" tabindex="2" />
<label for="token">令牌:</label>
<input type="text" name="token" value="" id="token" disabled="disabled" tabindex="3" />
</td>
</tr>
</table>
<label class="checkbox">
<input type="checkbox" name="usetoken" id="usetoken" tabindex="4" />使用令牌登录
</label>
</div>
<div class="modal-footer">
<button class="flatbtn-blu" onclick="login()" tabindex="3">登录</button>
<button class="flatbtn-blu" onclick="showRegist()" tabindex="4">注册</button>
</div>
</div>
<!-- 注册操作界面 -->
<div id="regist-div-modal" class="alert modal hide" role="dialog"
aria-hidden="true" data-backdrop="static">
<div class="modal-header">
<h3>用户注册</h3>
</div>
<div class="modal-body">
<div id="regist_div" style="overflow-y: auto">
<table>
<tr>
<td width="65%"><label>用户名:</label> <input type="text"
value="" id="regist_username" tabindex="1" /> <label>密码:</label>
<input type="password" value="" id="regist_password" tabindex="2" />
<label>昵称:</label> <input type="text" value=""
id="regist_nickname" tabindex="3" /></td>
</tr>
</table>
</div>
</div>
<div class="modal-footer">
<button id="confirm-regist-confirmButton" class="btn btn-primary"
onclick="regist()">完成</button>
<button id="confirm-regist-cancelButton" class="btn"
onclick="showlogin()">返回</button>
</div>
</div>
<div id="waitLoginmodal" class="modal hide" data-backdrop="static">
<img src="img/waitting.gif"> 正在努力加载中...</img>
</div>
<div class="content" id="content" style="display: none">
<div class="leftcontact" id="leftcontact">
<div id="headerimg" class="leftheader">
<span> <img src="img/head/header2.jpg" alt="logo"
class="img-circle" width="60px" height="60px"
style="margin-top: -40px; margin-left: 20px" /></span> <span
id="login_user" class="login_user_title"> <a
class="leftheader-font" href="#"></a>
</span> <span>
<div class="btn-group" style="margin-left: 5px;">
<button class="btn btn-inverse dropdown-toggle" data-toggle="dropdown">
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li><a href="javascript:;" onclick="showAddFriend()">添加好友</a></li>
<li><a href="javascript:;" onclick="showDelFriend()">删除好友</a></li>
<li class="divider"></li>
<li><a href="javascript:;" onclick="logout();return false;">退出</a></li>
</ul>
</div>
</span>
</div>
<div id="leftmiddle">
<!--
<input style="width: 120px; color: #999999; margin-top: 8px;"
type="text" id="searchfriend" value="搜索"
onFocus="if(value==defaultValue){value='';this.style.color='#000'}"
onBlur="if(!value){value=defaultValue;this.style.color='#999'}" />
<button id="searchFriend" style="background: #cccccc">查询</button>
-->
</div>
<div id="contractlist11"
style="height: 492px; overflow-y: auto; overflow-x: auto;">
<div class="accordion" id="accordionDiv">
<div class="accordion-group">
<div class="accordion-heading">
<a id="accordion1" class="accordion-toggle"
data-toggle="collapse" data-parent="#accordionDiv"
href="#collapseOne">我的好友 </a>
</div>
<div id="collapseOne" class="accordion-body collapse in">
<div class="accordion-inner" id="contractlist">
<ul id="contactlistUL" class="chat03_content_ul"></ul>
</div>
</div>
</div>
<div class="accordion-group">
<div class="accordion-heading">
<a id="accordion2" class="accordion-toggle collapsed"
data-toggle="collapse" data-parent="#accordionDiv"
href="#collapseTwo">我的群组</a>
</div>
<div id="collapseTwo" class="accordion-body collapse">
<div class="accordion-inner" id="contracgrouplist">
<ul id="contactgrouplistUL" class="chat03_content_ul"></ul>
</div>
</div>
</div>
<div class="accordion-group">
<div class="accordion-heading">
<a id="accordion3" class="accordion-toggle collapsed"
data-toggle="collapse" data-parent="#accordionDiv"
href="#collapseThree">陌生人</a>
</div>
<div id="collapseThree" class="accordion-body collapse">
<div class="accordion-inner" id="momogrouplist">
<ul id="momogrouplistUL" class="chat03_content_ul"></ul>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="rightTop" style="height: 78px;"></div>
<!-- 聊天页面 -->
<div class="chatRight">
<div id="chat01">
<div class="chat01_title">
<ul class="talkTo">
<li id="talkTo"><a href="#"></a></li>
<li id="recycle" style="float: right;"><img
src="img/recycle.png" onclick="clearCurrentChat();"
style="margin-right: 15px; cursor: hand; width: 18px;" title="清屏" /></li>
<li id="roomInfo" style="float: right;"><img
id="roomMemberImg"
src="img/head/find_more_friend_addfriend_icon.png"
onclick="showRoomMember();"
style="margin-right: 15px; cursor: hand; width: 18px; display: none"
title="群组成员" /></li>
</ul>
</div>
<div id="null-nouser" class="chat01_content"></div>
</div>
<div class="chat02">
<div class="chat02_title">
<a class="chat02_title_btn ctb01" onclick="showEmotionDialog()"
title="选择表情"></a> <a class="chat02_title_btn ctb03" title="选择图片"
onclick="showSendPic()" href="#"> </a> <a
class="chat02_title_btn ctb02" onclick="showSendAudio()" href="#"
title="选择语音"><span></span></a> <label id="chat02_title_t"></label>
<div id="wl_faces_box" class="wl_faces_box">
<div class="wl_faces_content">
<div class="title">
<ul>
<li class="title_name">常用表情</li>
<li class="wl_faces_close"><span
onclick='turnoffFaces_box()'> </span></li>
</ul>
</div>
<div id="wl_faces_main" class="wl_faces_main">
<ul id="emotionUL">
</ul>
</div>
</div>
<div class="wlf_icon"></div>
</div>
</div>
<div id="input_content" class="chat02_content">
<textarea id="talkInputId" style="resize: none;"></textarea>
</div>
<div class="chat02_bar">
<ul>
<li style="right: 5px; top: 5px;"><img src="img/send_btn.jpg"
onclick="sendText()" /></li>
</ul>
</div>
<div style="clear: both;"></div>
</div>
<div id="fileModal" class="modal hide" role="dialog"
aria-hidden="true" data-backdrop="static">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-hidden="true">×</button>
<h3>文件选择框</h3>
</div>
<div class="modal-body">
<input type='file' id="fileInput" /> <input type='hidden'
id="sendfiletype" />
<div id="send-file-warning"></div>
</div>
<div class="modal-footer">
<button id="fileSend" class="btn btn-primary" onclick="sendFile()">发送</button>
<button id="cancelfileSend" class="btn" data-dismiss="modal">取消</button>
</div>
</div>
</div>
<div id="addFridentModal" class="modal hide" role="dialog"
aria-hidden="true" data-backdrop="static">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-hidden="true">×</button>
<h3>添加好友</h3>
</div>
<div class="modal-body">
<input id="addfridentId" onfocus='clearInputValue("addfridentId")' />
<div id="add-frident-warning"></div>
</div>
<div class="modal-footer">
<button id="addFridend" class="btn btn-primary"
onclick="startAddFriend()">添加</button>
<button id="cancelAddFridend" class="btn" data-dismiss="modal">取消</button>
</div>
</div>
<div id="delFridentModal" class="modal hide" role="dialog"
aria-hidden="true" data-backdrop="static">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-hidden="true">×</button>
<h3>删除好友</h3>
</div>
<div class="modal-body">
<input id="delfridentId" onfocus='clearInputValue("delfridentId")' />
<div id="del-frident-warning"></div>
</div>
<div class="modal-footer">
<button id="delFridend" class="btn btn-primary"
onclick="directDelFriend()">删除</button>
<button id="canceldelFridend" class="btn" data-dismiss="modal">取消</button>
</div>
</div>
<!-- 一般消息通知 -->
<div id="notice-block-div" class="modal hide">
<button type="button" class="close" data-dismiss="alert">×</button>
<div class="modal-body">
<h4>Warning!</h4>
<div id="notice-block-body"></div>
</div>
</div>
<!-- 确认消息通知 -->
<div id="confirm-block-div-modal" class="modal hide"
role="dialog" aria-hidden="true" data-backdrop="static">
<div class="modal-header">
<h3>订阅通知</h3>
</div>
<div class="modal-body">
<div id="confirm-block-footer-body"></div>
</div>
<div class="modal-footer">
<button id="confirm-block-footer-confirmButton"
class="btn btn-primary">同意</button>
<button id="confirm-block-footer-cancelButton" class="btn"
data-dismiss="modal">拒绝</button>
</div>
</div>
<!-- 群组成员操作界面 -->
<div id="option-room-div-modal" class="alert modal hide"
role="dialog" aria-hidden="true" data-backdrop="static">
<button type="button" class="close" data-dismiss="modal"
aria-hidden="true">×</button>
<div class="modal-header">
<h3>群组成员</h3>
</div>
<div class="modal-body">
<div id="room-member-list" style="height: 100px; overflow-y: auto"></div>
</div>
</div>
</div>
</body>
</html>
css部分代码:(webim.css)
/** custom login button **/
.flatbtn-blu {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
display: inline-block;
outline: 0;
border: 0;
color: #edf4f9;
text-decoration: none;
background-color: #4f94cf;
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
font-size: 1.4em;
font-weight: bold;
padding: 12px 26px 12px 26px;
line-height: normal;
text-align: center;
vertical-align: middle;
cursor: pointer;
text-transform: uppercase;
text-shadow: 0 1px 0 rgba(0, 0, 0, 0.3);
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
-webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
-moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
}
.flatbtn-blu:hover {
color: #fff;
background-color: #519dde;
}
.flatbtn-blu:active {
-webkit-box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.1);
-moz-box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.1);
box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.1);
}
#loginmodal {
box-sizing: border-box;
padding: 15px 20px 0 50px;
background: #f3f6fa;
}
#loginform label {
display: block;
font-size: 1.1em;
font-weight: bold;
color: #7c8291;
margin-bottom: 3px;
}
* {
margin: 0;
padding: 0;
border: none;
font-size: 12px;
text-align: left;
}
ul {
list-style: none;
}
a {
text-decoration: none;
}
a:hover {
text-decoration: underline;
color: #f60;
}
.content {
width: 1000px;
height: auto;
margin: 0 auto;
valign: middle;
text-align: center;
}
.content_login {
width: 1000px;
height: auto;
padding: 25px;
margin: 0 auto;
valign: middle;
text-align: center;
}
.leftcontact {
float: left;
width: 196px;
border: 1px #666666 solid;
height: auto;
margin: 0 auto;
margin-top: 80px;
margin-left: 120px;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
position: relative;
}
.leftheader {
border: 1px #666666 solid;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
z-index: 1000;
position: relative;
width: 196px;
background-color: #5D6978;
}
.login_user_title {
display: -moz-inline-box;
display: inline-block;
width: 65px;
overflow: hidden;
}
.leftheader-font {
font-size: 14px;
font-weight: bold;
color: #333;
text-decoration: none;
}
.chatRight {
border-right: 1px #bebebe solid;
width: 562px;
height: auto;
margin-left: 340px;
position: relative;
border: 1px #666666 solid;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
.chat01_title {
background-color: #5D6978;
height: 42px;
margin-top: -10px;
}
.chat03_title {
background-color: #5D6978;
height: 30px;
position: relative;
}
.talkTo {
}
.talkTo li {
line-height: 17px;
float: left;
padding-left: 6px;
margin: 12px 20px;
_margin-left: 9px;
}
.talkTo li a {
padding: 4px 11px 4px 7px;
_padding-top: 0px;
_padding-bottom: 0px;
height: 19px;
font-size: 14px;
font-weight: bold;
color: #333;
text-decoration: none;
}
.close_btn {
background: url('../img/icon.png') no-repeat 0 0;
position: absolute;
top: 10px;
right: 8px;
display: block;
width: 15px;
height: 15px;
}
.chat02_title {
background: url('../img/chat_title_bg.jpg') repeat-x 0 0;
height: 25px;
position: relative;
}
.chat02_bar {
background: url('../img/chat_bar_bg.jpg') repeat-x 0 0;
height: 35px;
position: relative;
margin-bottom: 0px;
}
.chat02_bar ul {
height: 100%;
background: url('../img/wlf_bg.png') no-repeat 10px 8px;
}
.chat02_bar li {
position: absolute;
}
.chat03_title_t {
background: url('../img/icon.png') no-repeat 0px -370px;
position: absolute;
padding-left: 25px;
top: 8px;
left: 20px;
display: block;
width: auto;
height: 15px;
font-size: 12px;
font-weight: bold;
}
.chat01_content {
height: 312px;
width: 555px;
overflow-x: none;
overflow-y: auto;
}
.chat02_content {
height: auto;
}
.chat03_content_ul {
text-align: left;
font-size: 12px;
color: #333;
margin: 0px 0px;
overflow-y: auto;
position: relative;
resize: none;
}
.chat03_content {
height: 480px;
text-align: left;
font-size: 12px;
color: #333;
margin: 0px 0px;
overflow-y: auto;
position: relative;
resize: vertical;
}
.chat02_content textarea {
border: medium none;
display: block;
width: 552px;
height: 96px;
overflow-y: auto;
padding: 5px;
resize: vertical;
}
.chat03_name {
color: #333;
position: absolute;
top: 9px;
left: 40px;
display: block;
height: 480px;
}
.chat-content-p3 {
white-space: pre-wrap;
border-radius: 5px;
background-color: #C0C0C0;
position: relative;
/*padding: 5px 10px 5px 5px;*/
}
.chat03_content ul {
position: relative;
}
.chat03_content ul li {
position: relative;
padding: 3px 6px;
height: 31px;
_padding-bottom: 0px;
}
.chat03_content ul li.hover {
background: #ebeef3;
}
.chat03_content ul li.choosed {
background: #ebeef3;
}
.chat03_content ul li a {
}
.chat03_content ul img {
width: 30px;
height: 30px;
}
.chat02_title_btn {
background: url('../img/icon.png') no-repeat 0 0;
cursor: pointer;
float: left;
display: block;
width: 15px;
height: 15px;
margin: 5px 6px;
}
.ctb01 {
background-position: 0 -90px;
margin-left: 18px;
_margin-left: 8px;
}
.ctb03 {
background-position: 0 -152px;
}
.ctb02 {
background-position: 0 -457px;
}
.chat02_title_t {
background: url('../img/icon.png') no-repeat 0px -487px;
position: absolute;
padding-left: 170px;
top: 8px;
right: 20px;
display: block;
width: auto;
height: 15px;
}
.chat02_title_t a {
color: #333;
font-size: 12px;
text-decoration: none;
}
.chat02_title_t a:hover {
color: #f60;
text-decoration: underline;
}
.wl_faces_box {
background: url('../img/wlf_bg.png') repeat 0 0;
position: absolute;
width: 428px;
height: 225px;
bottom: 22px;
left: -50px;
display: none;
}
.wl_faces_content {
background: #fff;
border: 1px #ccc solid;
width: 417px;
height: 216px;
margin: 3px 4px;
}
.wl_faces_content .title {
background: url('../img/wlf_title_bg.jpg') repeat-x 0 0;
height: 40px;
position: relative;
}
.wl_faces_content .title ul {
}
.wl_faces_content .title ul li {
position: absolute;
display: block;
}
.wl_faces_content .title ul li.title_name {
background: url('../img/wlf_title_btn.jpg') no-repeat 0 0;
width: 82px;
height: 30px;
bottom: 0;
_bottom: -2px;
left: 15px;
text-align: center;
line-height: 32px;
font-weight: bold;
color: #333;
}
.wl_faces_content .title ul li.wl_faces_close {
right: 8px;
top: 15px;
}
.wl_faces_content .title ul li.wl_faces_close span {
background: url('../img/icon.png') repeat-x 0 0;
cursor: pointer;
display: block;
width: 15px;
height: 15px;
}
.wl_faces_main {
}
.wl_faces_main ul {
margin: 12px 28px;
overflow: hidden;
border-top: 1px #CCC solid;
border-left: 1px #CCC solid;
width: 360px;
}
.wl_faces_main ul li {
float: left;
border-right: 1px #CCC solid;
border-bottom: 1px #CCC solid;
height: 22px;
width: 26px;
margin: -1px 0 0 -1px;
padding: 4px 2px;
text-align: center;
}
.wl_faces_main ul li img {
width: 22px;
height: 22px;
}
.wlf_icon {
background: url('../img/layer_arrow.png') no-repeat 0 0;
position: absolute;
width: 22px;
height: 9px;
bottom: -4px;
_bottom: -11px;
left: 61px;
}
.chat03_content li label {
display: block;
position: absolute;
width: 9px;
height: 9px;
left: 27px;
}
label.online {
background: url('../img/status.gif') no-repeat 0 0;
_background: url('../img/status.gif') no-repeat 0 5px;
bottom: 4px;
_bottom: 2px;
}
label.offline {
background: url('../img/status.gif') no-repeat 0 -11px;
bottom: 4px;
_top: 25px;
align: center
}
.fade {
opacity: 0;
-webkit-transition: opacity 0.15s linear;
-moz-transition: opacity 0.15s linear;
-o-transition: opacity 0.15s linear;
transition: opacity 0.15s linear;
}
.modal-backdrop {
*display: none;
}
.fade.in {
opacity: 1;
}
.badgegroup,
.badge {
*margin-top: -30px;
}
.accordion-inner {
*position: relative;
}
完整源代码
源代码免费下载,下载地址:请点击这里下载
*****SUMER UI3.0****