12 changed files with 1241 additions and 0 deletions
@ -0,0 +1,248 @@ |
|||
<html lang="en"> |
|||
|
|||
<head> |
|||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> |
|||
<meta name="viewport" |
|||
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"> |
|||
<title></title> |
|||
<script type="text/javascript" src="/chat/js/jquery.min.js"></script> |
|||
<link href="/chat/css/jquery-sina-emotion.min.css" rel="stylesheet"> |
|||
<link href="/chat/css/chat.css?v=0915" rel="stylesheet"> |
|||
<script type="text/javascript" src="/chat/js/jquery-sina-emotion.js"></script> |
|||
<script type="text/javascript" src="/chat/js/swfobject.js"></script> |
|||
<script type="text/javascript" src="/chat/js/web_socket.js"></script> |
|||
<style> |
|||
.offtips { |
|||
color: #e8e8e8; |
|||
padding: 10px; |
|||
} |
|||
</style> |
|||
|
|||
<body onload="connect();"> |
|||
<div class="newWindow "> |
|||
<div class="window-header"> |
|||
<img src="/chat/img/btcex.png" width="40px" height="40px" |
|||
style="margin-right:10px;float:left;margin-top:4px;border-radius:2px;" alt="avatar"> |
|||
<p class="company-name font16">BTCEXCOIN </p> |
|||
<p class="autograph font12" title="Provide you with online pre-sales answers">Provide you with online pre-sales answers</p> |
|||
</div> |
|||
<div class="window-content"> |
|||
<div class="content-left"> |
|||
<div class="chat-content"> |
|||
<div style="display:none"> |
|||
|
|||
</div> |
|||
</div> |
|||
<div class="pc-visitor-footer"> |
|||
<form> |
|||
<div class="function-bar"> |
|||
<div class="talk-function-bar"> |
|||
<div class="svgWrap"> |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<label class="changeColor-wrap"> |
|||
<svg data-title="emote" class="function-icon icon-face face" width="24px" |
|||
height="24px" viewBox="0 0 24 24" version="1.1" |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
xmlns:xlink="http://www.w3.org/1999/xlink"><!-- emjoy --> |
|||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" |
|||
fill-rule="evenodd"> |
|||
<g id="Imported-Layers-Copy-7"> |
|||
<rect id="Rectangle-3" x="0" y="0" width="24" height="24"></rect> |
|||
<path class="svgColor" |
|||
d="M5,12 C5,15.8656805 8.1343195,19 12,19 C15.8656805,19 19,15.8656805 19,12 C19,8.1343195 15.8656805,5 12,5 C8.1343195,5 5,8.1343195 5,12 Z M3,12 C3,7.02975 7.02975,3 12,3 C16.97025,3 21,7.02975 21,12 C21,16.97025 16.97025,21 12,21 C7.02975,21 3,16.97025 3,12 Z" |
|||
id="Combined-Shape" fill="#8FA1B3" fill-rule="nonzero"></path> |
|||
<path class="svgColor" |
|||
d="M9,8 C8.172,8 7.5,8.672 7.5,9.5 C7.5,10.328 8.172,11 9,11 C9.828,11 10.5,10.328 10.5,9.5 C10.5,8.672 9.828,8 9,8" |
|||
id="Fill-2" fill="#8FA1B3"></path> |
|||
<path class="svgColor" |
|||
d="M15,8 C14.172,8 13.5,8.672 13.5,9.5 C13.5,10.328 14.172,11 15,11 C15.828,11 16.5,10.328 16.5,9.5 C16.5,8.672 15.828,8 15,8" |
|||
id="Fill-2-Copy" fill="#8FA1B3"></path> |
|||
<path class="svgColor" |
|||
d="M9.55730755,18.9802954 C12.5582692,18.9802954 15.0860829,16.7646048 15.4989445,13.8196019 C15.5756198,13.2726656 15.1943979,12.7671285 14.6474616,12.6904532 C14.1005252,12.6137779 13.5949881,12.9949998 13.5183128,13.5419361 C13.2434436,15.5026194 11.5576081,16.9802954 9.55730755,16.9802954 C9.0050228,16.9802954 8.55730755,17.4280106 8.55730755,17.9802954 C8.55730755,18.5325801 9.0050228,18.9802954 9.55730755,18.9802954 Z" |
|||
id="Oval-26" fill="#8FA1B3" fill-rule="nonzero" |
|||
transform="translate(12.033030, 15.830470) rotate(39.000000) translate(-12.033030, -15.830470) "> |
|||
</path> |
|||
</g> |
|||
</g> |
|||
</svg> |
|||
</label> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="inputArea"> |
|||
<textarea class="textarea" id="textarea" name="content" |
|||
placeholder="enter your message here"></textarea> |
|||
</div> |
|||
</form> |
|||
|
|||
<span class="send-btn submit-btn-wrap">Send</span> |
|||
</div> |
|||
</div> |
|||
<div class="content-right"> |
|||
<div class="content-right-top font14">About BTCEXCOIN</div> |
|||
<div class="company-content font12"> |
|||
<!-- site infomation --> |
|||
<p><br/></p> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<script type="text/javascript"> |
|||
if (typeof console == "undefined") { |
|||
this.console = { |
|||
log: function (msg) { |
|||
} |
|||
}; |
|||
} |
|||
|
|||
var ws; |
|||
|
|||
function connect() { |
|||
//ws = new WebSocket("ws://{$sysconfig['gateway']}"); |
|||
ws = new WebSocket("wss://cs.btcaholic.com/ct"); |
|||
ws.onmessage = onmessage; |
|||
|
|||
// ws.onopen = function(){ |
|||
// if (ws.readyState===1) { |
|||
// ws.send(); |
|||
|
|||
// } |
|||
// } |
|||
|
|||
ws.onclose = function () { |
|||
console.log("reconnct timer."); |
|||
// setTimeout(function(){ |
|||
// connect(); |
|||
// },1000); |
|||
connect(); |
|||
}; |
|||
ws.onerror = function (e) { |
|||
console.log("An error occurred", e); |
|||
// setTimeout(function(){ |
|||
// ws.close(); |
|||
// },3000); |
|||
}; |
|||
// ws.onclose = function(e){ |
|||
// console.log(e) |
|||
// } |
|||
} |
|||
|
|||
|
|||
function onmessage(e) { |
|||
// console.log(e) |
|||
console.log("Msg From Server:" + e.data); |
|||
var data = JSON.parse(e.data); |
|||
switch (data['type']) { |
|||
case 'login': |
|||
var bild = '{"type":"bild","room_id":"{$room_id}","cuid":"{$cuid}"}'; |
|||
ws.send(bild); |
|||
break; |
|||
case 'bild': |
|||
var id = data.room_id; |
|||
// if (!id) { |
|||
// alert('Ops,An error occurred!'); |
|||
// } |
|||
break; |
|||
case "say": |
|||
$(".chat-content").append('<div class="heisay"><img class="portrait" src="/chat/img/0.jpg"><div class="say_content"><p>Customer Service' + data.time.substr(10, 9) + '</p><span>' + data.content + '</span></div></div>').parseEmotion(); |
|||
$(".chat-content").scrollTop(3000); |
|||
return; |
|||
case "save": |
|||
|
|||
if (data['isonline'] == 0) { |
|||
$(".chat-content").append('<div class="heisay"><div class="say_content"><p class="offtips">Customer service is temporarily away for a while. If there is anything I can do for you, please leave me a message and I will reply to you as soon as possible.~</div></div>').parseEmotion(); |
|||
$(".chat-content").scrollTop(3000); |
|||
} |
|||
// console.log("msgdata") |
|||
save_message(data); |
|||
return; |
|||
} |
|||
} |
|||
|
|||
// |
|||
$(".send-btn").click(function () { |
|||
var text = $(".textarea").val(); |
|||
//解析新浪微博图片 |
|||
text.replace(/(http|https):\/\/[\w]+.sinaimg.cn[\S]+(jpg|png|gif)/gi, function (img) { |
|||
return "<a target='_blank' href='" + img + "'>" + "<img src='" + img + "'>" + "</a>"; |
|||
} |
|||
); |
|||
//解析url |
|||
text.replace(/(http|https):\/\/[\S]+/gi, function (url) { |
|||
if (url.indexOf(".sinaimg.cn/") < 0) |
|||
return "<a target='_blank' href='" + url + "'>" + url + "</a>"; |
|||
else |
|||
return url; |
|||
} |
|||
); |
|||
if (text == '') { |
|||
return; |
|||
} |
|||
var time = getNowFormatDate(); |
|||
var message = '{"content":"' + text + '","type":"say","room_id":"{$room_id}","toid":"{$chat_user}","cuid":"{$cuid}" }'; |
|||
$(".chat-content").append('<div class="mysay"><p>Me ' + time + '</p><span>' + text + '</span></div>').parseEmotion(); |
|||
$(".chat-content").scrollTop(3000); |
|||
// |
|||
// if (ws.readyState===1) { |
|||
ws.send(message); |
|||
// } |
|||
$(".textarea").val(""); |
|||
}) |
|||
// |
|||
$('.face').click(function (event) { |
|||
$(this).sinaEmotion(); |
|||
event.stopPropagation(); |
|||
}); |
|||
|
|||
document.write('<meta name="viewport" content="width=device-width,initial-scale=1">'); |
|||
$("textarea").on("keydown", function (e) { |
|||
// 按enter键自动提交 |
|||
if (e.keyCode === 13 && !e.ctrlKey) { |
|||
e.preventDefault(); |
|||
$(".send-btn").click(); |
|||
return false; |
|||
} |
|||
// 按ctrl+enter组合键换行 |
|||
if (e.keyCode === 13 && e.ctrlKey) { |
|||
$(this).val(function (i, val) { |
|||
return val + "\n"; |
|||
}); |
|||
} |
|||
}); |
|||
|
|||
function getNowFormatDate() { |
|||
var date = new Date(); |
|||
var currentdate = date.toLocaleTimeString(); |
|||
return currentdate; |
|||
} |
|||
|
|||
// |
|||
function save_message(data) { |
|||
$.post("{:url('Index/save_message')}", data, function (data) { |
|||
//do nothing |
|||
}); |
|||
} |
|||
|
|||
$(function () { |
|||
$.post("{:url('Index/chat_record')}", "foid={$chat_user}&room_id={$room_id}", function (data) { |
|||
for (var i = 0; i < data.length; i++) { |
|||
if (data[i].fid !== '{$room_id}') { |
|||
$(".chat-content").append('<div class="heisay"><img class="portrait" src="/static/css/chat/img/0.jpg"><div class="say_content"><p>Customer Service' + data[i].time.substr(10, 9) + '</p><span>' + data[i].content + '</span></div></div>').parseEmotion(); |
|||
} else { |
|||
$(".chat-content").append('<div class="mysay"><p>Me ' + data[i].time.substr(10, 9) + '</p><span>' + data[i].content + '</span></div>').parseEmotion(); |
|||
} |
|||
} |
|||
$(".chat-content").append('<div class="mysay"> </div>'); |
|||
$(".chat-content").scrollTop(3000); |
|||
}); |
|||
}) |
|||
</script> |
|||
<script type="text/javascript"> |
|||
|
|||
// document.addEventListener('dblclick', function(e) { |
|||
// e.preventDefault(); |
|||
|
|||
// }, { passive: false }); |
|||
|
|||
</script> |
|||
</script> |
|||
@ -0,0 +1,234 @@ |
|||
<html> |
|||
|
|||
<head> |
|||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> |
|||
<title>聊天室</title> |
|||
<script type="text/javascript" src="__CSS__/kefu/js/jquery.min.js"></script> |
|||
<link href="__CSS__/kefu/css/jquery-sina-emotion.min.css" rel="stylesheet"> |
|||
<link href="__CSS__/kefu/css/chat.css" rel="stylesheet"> |
|||
<script type="text/javascript" src="__CSS__/kefu/js/jquery-sina-emotion.js"></script> |
|||
<script type="text/javascript" src="__CSS__/kefu/js/swfobject.js"></script> |
|||
<script type="text/javascript" src="__CSS__/kefu/js/web_socket.js"></script> |
|||
|
|||
<body onload="connect();"> |
|||
<div class="newWindow "> |
|||
<div class="window-header"> |
|||
<img src="/static/css/kefu/img/btcex.png" width="40px" height="40px" |
|||
style="margin-right:10px;float:left;margin-top:4px;border-radius:2px;" alt="头像"> |
|||
<p class="company-name font16">BTCEXCOIN</p> |
|||
<p class="autograph font12" title="">BTCEXCOIN</p> |
|||
</div> |
|||
<div class="window-content"> |
|||
<div class="content-left"> |
|||
<div class="chat-content"> |
|||
|
|||
|
|||
</div> |
|||
<div class="pc-visitor-footer"> |
|||
<form> |
|||
<div class="function-bar"> |
|||
<div class="talk-function-bar"> |
|||
<div class="svgWrap"> |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<label class="changeColor-wrap"> |
|||
<svg data-title="表情" class="function-icon icon-face face" width="24px" |
|||
height="24px" viewBox="0 0 24 24" version="1.1" |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
xmlns:xlink="http://www.w3.org/1999/xlink"><!-- 表情 --> |
|||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" |
|||
fill-rule="evenodd"> |
|||
<g id="Imported-Layers-Copy-7"> |
|||
<rect id="Rectangle-3" x="0" y="0" width="24" height="24"></rect> |
|||
<path class="svgColor" |
|||
d="M5,12 C5,15.8656805 8.1343195,19 12,19 C15.8656805,19 19,15.8656805 19,12 C19,8.1343195 15.8656805,5 12,5 C8.1343195,5 5,8.1343195 5,12 Z M3,12 C3,7.02975 7.02975,3 12,3 C16.97025,3 21,7.02975 21,12 C21,16.97025 16.97025,21 12,21 C7.02975,21 3,16.97025 3,12 Z" |
|||
id="Combined-Shape" fill="#8FA1B3" fill-rule="nonzero"></path> |
|||
<path class="svgColor" |
|||
d="M9,8 C8.172,8 7.5,8.672 7.5,9.5 C7.5,10.328 8.172,11 9,11 C9.828,11 10.5,10.328 10.5,9.5 C10.5,8.672 9.828,8 9,8" |
|||
id="Fill-2" fill="#8FA1B3"></path> |
|||
<path class="svgColor" |
|||
d="M15,8 C14.172,8 13.5,8.672 13.5,9.5 C13.5,10.328 14.172,11 15,11 C15.828,11 16.5,10.328 16.5,9.5 C16.5,8.672 15.828,8 15,8" |
|||
id="Fill-2-Copy" fill="#8FA1B3"></path> |
|||
<path class="svgColor" |
|||
d="M9.55730755,18.9802954 C12.5582692,18.9802954 15.0860829,16.7646048 15.4989445,13.8196019 C15.5756198,13.2726656 15.1943979,12.7671285 14.6474616,12.6904532 C14.1005252,12.6137779 13.5949881,12.9949998 13.5183128,13.5419361 C13.2434436,15.5026194 11.5576081,16.9802954 9.55730755,16.9802954 C9.0050228,16.9802954 8.55730755,17.4280106 8.55730755,17.9802954 C8.55730755,18.5325801 9.0050228,18.9802954 9.55730755,18.9802954 Z" |
|||
id="Oval-26" fill="#8FA1B3" fill-rule="nonzero" |
|||
transform="translate(12.033030, 15.830470) rotate(39.000000) translate(-12.033030, -15.830470) "> |
|||
</path> |
|||
</g> |
|||
</g> |
|||
</svg> |
|||
</label> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="inputArea"> |
|||
<textarea class="textarea" id="textarea" name="content" placeholder="请输入文字"></textarea> |
|||
</div> |
|||
</form> |
|||
|
|||
<span class="send-btn submit-btn-wrap">发送</span> |
|||
</div> |
|||
</div> |
|||
<div class="content-right"> |
|||
<div class="content-right-top font14">关于我们</div> |
|||
<div class="company-content font12"> |
|||
|
|||
|
|||
|
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
|
|||
</div> |
|||
|
|||
|
|||
|
|||
<script type="text/javascript"> |
|||
if (typeof console == "undefined") { this.console = { log: function (msg) { } }; } |
|||
|
|||
var ws, name, client_list = {}; |
|||
function connect() { |
|||
ws = new WebSocket("wss://cs.btcaholic.com/ct"); |
|||
|
|||
ws.onmessage = onmessage; |
|||
ws.onclose = function () { |
|||
console.log("连接关闭,定时重连"); |
|||
connect(); |
|||
}; |
|||
ws.onerror = function () { |
|||
console.log("出现错误"); |
|||
}; |
|||
} |
|||
|
|||
|
|||
function onmessage(e) { |
|||
|
|||
var data = JSON.parse(e.data); |
|||
console.log(data) |
|||
switch (data['type']) { |
|||
case 'login': |
|||
var bild = '{"type":"bild","room_id":"{:session('kefu')}"}'; |
|||
ws.send(bild); |
|||
break; |
|||
case 'bild': |
|||
var id = data.room_id; |
|||
if (!id) { |
|||
alert('房间出错!'); |
|||
} |
|||
break; |
|||
case "say": |
|||
if (data.group == '{:session('kefu')}<?php echo $_GET['toid']?>') |
|||
{ |
|||
$(".chat-content").append('<div class="heisay"><div class="say_content"><p>游客' + data.time.substr(10, 9) + '</p><span>' + data.content + '</span></div></div>').parseEmotion(); |
|||
$(".chat-content").scrollTop(3000); |
|||
} |
|||
return; |
|||
case "save": |
|||
|
|||
save_message(data); |
|||
return; |
|||
} |
|||
|
|||
} |
|||
$(".send-btn").click(function () { |
|||
var text = $(".textarea").val(); |
|||
//解析新浪微博图片 |
|||
text.replace(/(http|https):\/\/[\w]+.sinaimg.cn[\S]+(jpg|png|gif)/gi, function (img) { |
|||
return "<a target='_blank' href='" + img + "'>" + "<img src='" + img + "'>" + "</a>"; |
|||
} |
|||
); |
|||
//解析url |
|||
text.replace(/(http|https):\/\/[\S]+/gi, function (url) { |
|||
if (url.indexOf(".sinaimg.cn/") < 0) |
|||
return "<a target='_blank' href='" + url + "'>" + url + "</a>"; |
|||
else |
|||
return url; |
|||
} |
|||
); |
|||
if (text == '') { |
|||
return; |
|||
} |
|||
var time = getNowFormatDate(); |
|||
var message = '{"content":"' + text + '","type":"say","room_id":"{:session('kefu')}","toid":"<?php echo $_GET['toid']?>","group":"{:session('kefu')}<?php echo $_GET['toid']?>"}'; |
|||
$(".chat-content").append('<div class="mysay"><p>我 ' + time + '</p><span>' + text + '</span></div>').parseEmotion(); |
|||
$(".chat-content").scrollTop(3000); |
|||
console.log(11111); |
|||
ws.send(message); |
|||
$(".textarea").val(""); |
|||
}) |
|||
$('.face').click(function (event) { |
|||
$(this).sinaEmotion(); |
|||
event.stopPropagation(); |
|||
}); |
|||
|
|||
document.write('<meta name="viewport" content="width=device-width,initial-scale=1">'); |
|||
$("textarea").on("keydown", function (e) { |
|||
// 按enter键自动提交 |
|||
if (e.keyCode === 13 && !e.ctrlKey) { |
|||
e.preventDefault(); |
|||
$(".send-btn").click(); |
|||
return false; |
|||
} |
|||
// 按ctrl+enter组合键换行 |
|||
if (e.keyCode === 13 && e.ctrlKey) { |
|||
$(this).val(function (i, val) { |
|||
return val + "\n"; |
|||
}); |
|||
} |
|||
}); |
|||
function getNowFormatDate() { |
|||
var date = new Date(); |
|||
var currentdate = date.toLocaleTimeString(); |
|||
return currentdate; |
|||
} |
|||
function save_message(data) { |
|||
$.post("{:url('Index/save_message')}", data, function (e) { |
|||
// |
|||
}); |
|||
} |
|||
$(function () { |
|||
$.post("{:url('Index/chat_record')}", "fid=<?php echo $_GET['toid']?>", function (data) { |
|||
for (var i = 0; i < data.length; i++) { |
|||
if (data[i].fid !== '{:session('kefu')}'){ |
|||
$(".chat-content").append('<div class="heisay"><div class="say_content"><p>' + data[i].fid + '' + data[i].time.substr(10, 9) + '</p><span>' + data[i].content + '</span></div></div>').parseEmotion(); |
|||
} |
|||
else { |
|||
$(".chat-content").append('<div class="mysay"><p>我 ' + data[i].time.substr(10, 9) + '</p><span>' + data[i].content + '</span></div>').parseEmotion(); |
|||
} |
|||
} |
|||
$(".chat-content").append('<div class="mysay"> </div>'); |
|||
$(".chat-content").scrollTop(3000); |
|||
}); |
|||
}) |
|||
</script> |
|||
<script> |
|||
document.addEventListener('visibilitychange', function () { |
|||
var isHidden = document.hidden; |
|||
if (isHidden) { |
|||
console.log('暂停'); |
|||
} else { |
|||
console.log('开始'); |
|||
} |
|||
}); |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
/* |
|||
window.onfocus = function() { |
|||
console.log('开始'); |
|||
}; |
|||
|
|||
//当前窗口失去焦点 |
|||
window.onblur = function() { |
|||
console.log('暂停'); |
|||
}; |
|||
*/ |
|||
|
|||
|
|||
|
|||
</script> |
|||
@ -0,0 +1,52 @@ |
|||
@media only screen and (max-width: 750px) { |
|||
.newWindow {width:100%;background: #FFF !important;box-shadow: 0 0 20px 0 rgba(0,0,0,.15);-moz-box-shadow: 0 0 20px 0 rgba(0,0,0,.15);-webkit-box-shadow: 0 0 20px 0 rgba(0,0,0,.15);border-radius: 2px;overflow: hidden;box-sizing: content-box;} |
|||
} |
|||
@media (min-width:750px) { |
|||
.newWindow {left:50%;top:50%;width:800px;margin-left:-400px;margin-top: -300px;position: absolute;background: #FFF !important;box-shadow: 0 0 20px 0 rgba(0,0,0,.15);-moz-box-shadow: 0 0 20px 0 rgba(0,0,0,.15);-webkit-box-shadow: 0 0 20px 0 rgba(0,0,0,.15);border-radius: 2px;overflow: hidden;box-sizing: content-box;} |
|||
} |
|||
|
|||
.toDeveloper {height: 40px !important;width: 66% !important;background: #FFF !important;bottom: 0 !important;z-index: 66;} |
|||
p,ul,li,h1,h2,h3,h4,h5,h6{margin:0;padding:0;} |
|||
li,ul{list-style: none;} |
|||
* {margin:0;padding:0;tap-highlight-color: rgba(0,0,0,0);-webkit-tap-highlight-color: rgba(0,0,0,0);line-height: 1.5;box-sizing: border-box;} |
|||
body {margin:0;background-color: #fafafa;overflow: auto;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,"Helvetica Neue", Helvetica, "PingFang SC", SimSun, sans-serif;} |
|||
html,body {height:100%;} |
|||
input {outline: none;border:none;} |
|||
::-moz-placeholder {font-size: 13px;color: #8DA2B5;letter-spacing: 0.73px;} |
|||
::-webkit-input-placeholder {font-size: 13px;color: #8DA2B5;letter-spacing: 0.73px;} |
|||
:-ms-input-placeholder {font-size: 13px;color: #8DA2B5;letter-spacing: 0.73px;} |
|||
::selection {background:#FC4B4B!important;} |
|||
::-moz-selection {background:#FC4B4B!important;} |
|||
::-webkit-selection {background:#FC4B4B!important;} |
|||
.font12 {font-size: 12px;letter-spacing: 0.6px;} |
|||
.font14 {font-size: 14px;letter-spacing: 1px;} |
|||
.font16 {font-size: 16px;letter-spacing: 1px;} |
|||
.color-grey-deep {color: #28334B;} |
|||
.talk {display:block;position:relative;} |
|||
.pc-visitor-footer {height:160px;width: 100%;} |
|||
.pc-visitor-footer .function-bar {position:relative;background: #F8FAFC;height:40px;border-top:1px solid #E9EEF2;border-bottom:1px solid #E9EEF2;padding-left: 10px;} |
|||
.pc-visitor-footer .function-bar .svgWrap ,.pc-visitor-footer .function-bar .svgWrap svg ,.pc-visitor-footer .function-bar .svgWrap svg:hover .svgColor {fill:#1F8CEB;} |
|||
.pc-visitor-footer .function-bar label.active .svgColor {fill:#1F8CEB;} |
|||
.pc-visitor-footer .function-bar .talk-function-bar {height:100%;width:100%;padding-top: 8px;} |
|||
.pc-visitor-footer .inputArea textarea { width: 100%;height: 75px;padding:8px 5px;font-size: 14px;color: #28334B;letter-spacing: 0.28px;line-height: 19px;border: none;outline: none;resize: none;} |
|||
.submit-btn-wrap{float:right;margin-right:10px;width:80px;height:30px;background-color:#1e89e6;border-radius:2px;color:#fff;cursor:pointer;display:inline-block;text-align:center;line-height:30px;vertical-align: middle;} |
|||
.toDeveloperP {width:460px;font-size: 12px;height: 40px;background: #FFF;padding-top: 10px;line-height: 30px;padding-left: 5px;float:left} |
|||
.toDeveloper{color: #62778C;letter-spacing: 0.6px;text-decoration: none;} |
|||
.toDeveloper:hover{color:#218BFC;text-decoration: underline;} |
|||
.window-header {width: 100%;background: #1F8CEB;height:60px;display:block;padding-left: 15px;padding-top: 6px;} |
|||
.company-name {height:24px;line-height: 24px; color: #FFFFFF; letter-spacing: 0;} |
|||
.autograph {height:24px;line-height:24px;color: #FFFFFF;letter-spacing: 0;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;padding-right: 20px; } |
|||
.newWindow .window-content {height: 100%;width: 100%; } |
|||
.content-left{width:560px;float:left;height:540px} |
|||
.chat-content{overflow-y:auto;width:560px;height:377px} |
|||
.content-right {float:left;width:239px;vertical-align: top;height:540px;border-left:1px solid #DDE5ED;} |
|||
.content-right-top {border-bottom:1px solid #DDE5ED;width:100%;font-size: 14px;height:40px;color: #28334B;text-align:center;line-height:40px;letter-spacing: 0;} |
|||
.company-content {word-wrap:break-word;width:97%;padding-top:10px;padding-left:10px;overflow-y:auto;height:335px;} |
|||
.mysay{width:98%;margin:0;color:#3A3C4C;font-size:13px;float:right;margin-right:10px} |
|||
.heisay{width:98%;margin:0;color:#3A3C4C;font-size:13px;float:left;margin-left:10px} |
|||
.mysay p{text-align:right} |
|||
.heisay p{text-align:left;height:40px;display:table-cell;vertical-align:bottom;} |
|||
.mysay span{max-width:98%;padding-left:10px;padding-right:5px;padding-top:5px;padding-bottom:5px;float:right;background-color:rgb(31, 140, 232);color:fff;border-radius: 2px;} |
|||
.heisay span{max-width:98%;padding-left:5px;padding-right:10px;padding-top:5px;padding-bottom:5px;float:left;background-color:#EFF3F6;border-radius: 2px;} |
|||
.portrait{width:40px;height:40px;float:left} |
|||
.say_content{float:left} |
|||
@ -0,0 +1 @@ |
|||
#sina-emotion{z-index:999;width:373px;padding:10px;display:none;font-size:12px;background:#fff;position:absolute;border-radius:3px;border:1px solid #ccc;box-shadow:0 4px 20px 1px rgba(0,0,0,.2)}#sina-emotion .switch{float:right}#sina-emotion .next,#sina-emotion .prev{float:left;color:#555;width:22px;height:22px;font-size:20px;margin-left:5px;line-height:22px;text-align:center;background:#f8f8f8;text-decoration:none}#sina-emotion .item{float:left;list-style:none}#sina-emotion .categories,#sina-emotion .faces,#sina-emotion .pages{margin:0;padding:0;overflow:hidden}#sina-emotion .category{float:left;color:#0a8cd2;cursor:pointer;padding:0 8px;line-height:22px;border-radius:4px;white-space:nowrap}#sina-emotion .category:hover{text-decoration:underline}#sina-emotion .categories .current,#sina-emotion .categories .current:hover{color:#333;cursor:default;background:#e6e6e6;text-decoration:none}#sina-emotion .faces{width:372px;padding:11px 0 0 1px}#sina-emotion .face{z-index:1;float:left;width:26px;height:26px;cursor:pointer;overflow:hidden;padding:4px 2px;position:relative;text-align:center;margin:-1px 0 0 -1px;border:1px solid #e8e8e8}#sina-emotion .face:hover{z-index:2;border:1px solid #0095cd}#sina-emotion .pages{float:right;margin-top:8px}#sina-emotion .page{float:left;height:22px;padding:0 8px;color:#0a8cd2;margin-left:5px;line-height:22px;border-radius:1px;background:#f2f2f2;text-decoration:none}#sina-emotion .pages .current{color:#333;cursor:default;background:#fff}.sina-emotion{border:0;width:22px;height:22px;vertical-align:text-bottom} |
|||
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
@ -0,0 +1,296 @@ |
|||
/** |
|||
* jQuery Sina Emotion |
|||
* @author [Jealous](http://www.clanfei.com/)
|
|||
* @license MIT |
|||
*/ |
|||
(function (global, factory) { |
|||
if (typeof module === 'object' && typeof module.exports === 'object') { |
|||
factory(require('jquery')); |
|||
} else { |
|||
factory(global.jQuery); |
|||
} |
|||
}(this, function ($) { |
|||
'use strict'; |
|||
|
|||
var STATE_UNINITIALIZED = 0; |
|||
var STATE_LOADING = 1; |
|||
var STATE_LOADED = 2; |
|||
|
|||
var $target; |
|||
var options; |
|||
var callbacks = []; |
|||
var emotions = {}; |
|||
var categories = []; |
|||
var emotionsMap = {}; |
|||
var defCategory = '默认'; |
|||
var state = STATE_UNINITIALIZED; |
|||
|
|||
function initEvents() { |
|||
var $sinaEmotion = $('#sina-emotion'); |
|||
|
|||
$('body').bind({ |
|||
click: function () { |
|||
$sinaEmotion.hide(); |
|||
} |
|||
}); |
|||
$sinaEmotion.bind({ |
|||
click: function (event) { |
|||
event.stopPropagation(); |
|||
} |
|||
}).delegate('.prev', { |
|||
click: function (event) { |
|||
var page = $sinaEmotion.find('.categories').data('page'); |
|||
showCatPage(page - 1); |
|||
event.preventDefault(); |
|||
} |
|||
}).delegate('.next', { |
|||
click: function (event) { |
|||
var page = $sinaEmotion.find('.categories').data('page'); |
|||
showCatPage(page + 1); |
|||
event.preventDefault(); |
|||
} |
|||
}).delegate('.category', { |
|||
click: function (event) { |
|||
$sinaEmotion.find('.categories .current').removeClass('current'); |
|||
showCategory($.trim($(this).addClass('current').text())); |
|||
event.preventDefault(); |
|||
} |
|||
}).delegate('.page', { |
|||
click: function (event) { |
|||
$sinaEmotion.find('.pages .current').removeClass('current'); |
|||
var page = parseInt($(this).addClass('current').text(), 10) - 1; |
|||
showFacePage(page); |
|||
event.preventDefault(); |
|||
} |
|||
}).delegate('.face', { |
|||
click: function (event) { |
|||
$sinaEmotion.hide(); |
|||
$target.insertText($(this).children('img').prop('alt')).focus(); |
|||
event.preventDefault(); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
function loadEmotions(callback) { |
|||
if (state === STATE_LOADED) { |
|||
callback && callback(); |
|||
return; |
|||
} else if (state === STATE_LOADING) { |
|||
callback && callbacks.push(callback); |
|||
return; |
|||
} else { |
|||
callback && callbacks.push(callback); |
|||
} |
|||
|
|||
state = STATE_LOADING; |
|||
options = options || $.fn.sinaEmotion.options; |
|||
|
|||
var $sinaEmotion = $('<div id="sina-emotion">正在加载,请稍后...</div>'); |
|||
$('body').append($sinaEmotion); |
|||
|
|||
initEvents(); |
|||
|
|||
$.getJSON('https://api.weibo.com/2/emotions.json?callback=?', { |
|||
source: options.appKey, |
|||
language: options.language |
|||
}, function (res) { |
|||
var item; |
|||
var category; |
|||
var data = res.data; |
|||
|
|||
$('#sina-emotion').html('<div class="switch">' + |
|||
'<a href="#" class="prev">«</a>' + |
|||
'<a href="#" class="next">»</a>' + |
|||
'</div>' + |
|||
'<ul class="categories"></ul>' + |
|||
'<ul class="faces"></ul>' + |
|||
'<ul class="pages"></ul>' |
|||
); |
|||
|
|||
for (var i = 0, l = data.length; i < l; ++i) { |
|||
item = data[i]; |
|||
category = item['category'] || defCategory; |
|||
|
|||
if (!emotions[category]) { |
|||
emotions[category] = []; |
|||
categories.push(category); |
|||
} |
|||
|
|||
emotions[category].push({ |
|||
icon: item['icon'], |
|||
phrase: item['phrase'] |
|||
}); |
|||
|
|||
emotionsMap[item['phrase']] = item.icon; |
|||
} |
|||
|
|||
for (var j = 0, m = callbacks.length; j < m; ++j) { |
|||
callbacks[j](); |
|||
} |
|||
|
|||
if (categories.length <= 5) { |
|||
$sinaEmotion.children('.switch').remove(); |
|||
} |
|||
|
|||
state = STATE_LOADED; |
|||
}); |
|||
} |
|||
|
|||
function showCatPage(page) { |
|||
|
|||
var html = ''; |
|||
var length = categories.length; |
|||
var maxPage = Math.ceil(length / 5); |
|||
var $categories = $('#sina-emotion').find('.categories'); |
|||
var category = $categories.data('category') || defCategory; |
|||
|
|||
page = (page + maxPage) % maxPage; |
|||
|
|||
for (var i = page * 5; i < length && i < (page + 1) * 5; ++i) { |
|||
html += '<li class="item">' + |
|||
'<a href="#" class="category' + (category === categories[i] ? ' current' : '') + '">' + categories[i] + '</a>' + |
|||
'</li>'; |
|||
} |
|||
|
|||
$categories.data('page', page).html(html); |
|||
} |
|||
|
|||
function showCategory(category) { |
|||
$('#sina-emotion').find('.categories').data('category', category); |
|||
showFacePage(0); |
|||
showPages(); |
|||
} |
|||
|
|||
function showFacePage(page) { |
|||
var face; |
|||
var html = ''; |
|||
var rows = options.rows; |
|||
var $sinaEmotion = $('#sina-emotion'); |
|||
var category = $sinaEmotion.find('.categories').data('category'); |
|||
var faces = emotions[category]; |
|||
page = page || 0; |
|||
|
|||
for (var i = page * rows, l = faces.length; i < l && i < (page + 1) * rows; ++i) { |
|||
face = faces[i]; |
|||
html += '<li class="item">' + |
|||
'<a href="#" class="face">' + |
|||
'<img class="sina-emotion" src="' + face['icon'] + '" alt="' + face['phrase'] + '" />' + |
|||
'</a>' + |
|||
'</li>'; |
|||
} |
|||
|
|||
$sinaEmotion.find('.faces').html(html); |
|||
} |
|||
|
|||
function showPages() { |
|||
|
|||
var html = ''; |
|||
var rows = options.rows; |
|||
var $sinaEmotion = $('#sina-emotion'); |
|||
var category = $sinaEmotion.find('.categories').data('category'); |
|||
var faces = emotions[category]; |
|||
var length = faces.length; |
|||
|
|||
if (length > rows) { |
|||
for (var i = 0, l = Math.ceil(length / rows); i < l; ++i) { |
|||
html += '<li class="item">' + |
|||
'<a href="#" class="page' + (i === 0 ? ' current' : '') + '">' + (i + 1) + '</a>' + |
|||
'</li>'; |
|||
} |
|||
$sinaEmotion.find('.pages').html(html).show(); |
|||
} else { |
|||
$sinaEmotion.find('.pages').hide(); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 为某个元素设置点击事件,点击弹出表情选择窗口 |
|||
* @param {String|function} target 用于插入表情文本框选择器,或返回文本框 jQuery 对象的方法 |
|||
*/ |
|||
$.fn.sinaEmotion = function (target) { |
|||
|
|||
var $this = $(this).last(); |
|||
var offset = $this.offset(); |
|||
|
|||
target = target || function () { |
|||
return $this.parents('form').find('textarea, input[type=text]').eq(0); |
|||
}; |
|||
|
|||
if ($this.is(':visible')) { |
|||
if (typeof target === 'function') { |
|||
$target = target.call($this); |
|||
} else { |
|||
$target = $(target); |
|||
} |
|||
|
|||
loadEmotions(function () { |
|||
showCategory(defCategory); |
|||
showCatPage(0); |
|||
}); |
|||
|
|||
$('#sina-emotion').css({ |
|||
top: offset.top + $this.outerHeight() + 5, |
|||
left: offset.left |
|||
}).show(); |
|||
} |
|||
|
|||
return this; |
|||
}; |
|||
|
|||
$.fn.parseEmotion = function () { |
|||
var $this = $(this); |
|||
loadEmotions(function () { |
|||
$this.each(function () { |
|||
var $this = $(this); |
|||
var html = $this.html(); |
|||
|
|||
html = html.replace(/<.*?>/g, function ($1) { |
|||
$1 = $1.replace('[', '['); |
|||
$1 = $1.replace(']', ']'); |
|||
return $1; |
|||
}).replace(/\[[^\[\]]*?]/g, function ($1) { |
|||
var url = emotionsMap[$1]; |
|||
if (url) { |
|||
return '<img class="sina-emotion" src="' + url + '" alt="' + $1 + '" />'; |
|||
} |
|||
return $1; |
|||
}); |
|||
|
|||
$this.html(html); |
|||
}); |
|||
}); |
|||
return this; |
|||
}; |
|||
|
|||
$.fn.insertText = function (text) { |
|||
|
|||
this.each(function () { |
|||
|
|||
if (this.tagName !== 'INPUT' && this.tagName !== 'TEXTAREA') { |
|||
return; |
|||
} |
|||
if (document.selection) { |
|||
this.focus(); |
|||
var cr = document.selection.createRange(); |
|||
cr.text = text; |
|||
cr.collapse(); |
|||
cr.select(); |
|||
} else if (this.selectionStart !== undefined) { |
|||
var start = this.selectionStart; |
|||
var end = this.selectionEnd; |
|||
this.value = this.value.substring(0, start) + text + this.value.substring(end, this.value.length); |
|||
this.selectionStart = this.selectionEnd = start + text.length; |
|||
} else { |
|||
this.value += text; |
|||
} |
|||
}); |
|||
|
|||
return this; |
|||
}; |
|||
|
|||
$.fn.sinaEmotion.options = { |
|||
rows: 72, // 每页显示的表情数
|
|||
language: 'cnname', // 简体(cnname)、繁体(twname)
|
|||
appKey: '1362404091' // 新浪微博开放平台的应用ID
|
|||
}; |
|||
})); |
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,398 @@ |
|||
// Copyright: Hiroshi Ichikawa <http://gimite.net/en/>
|
|||
// License: New BSD License
|
|||
// Reference: http://dev.w3.org/html5/websockets/
|
|||
// Reference: http://tools.ietf.org/html/rfc6455
|
|||
|
|||
(function() { |
|||
|
|||
if (window.WEB_SOCKET_FORCE_FLASH) { |
|||
// Keeps going.
|
|||
} else if (window.WebSocket) { |
|||
return; |
|||
} else if (window.MozWebSocket) { |
|||
// Firefox.
|
|||
window.WebSocket = MozWebSocket; |
|||
return; |
|||
} |
|||
|
|||
var logger; |
|||
if (window.WEB_SOCKET_LOGGER) { |
|||
logger = WEB_SOCKET_LOGGER; |
|||
} else if (window.console && window.console.log && window.console.error) { |
|||
// In some environment, console is defined but console.log or console.error is missing.
|
|||
logger = window.console; |
|||
} else { |
|||
logger = {log: function(){ }, error: function(){ }}; |
|||
} |
|||
|
|||
// swfobject.hasFlashPlayerVersion("10.0.0") doesn't work with Gnash.
|
|||
if (swfobject.getFlashPlayerVersion().major < 10) { |
|||
logger.error("Flash Player >= 10.0.0 is required."); |
|||
return; |
|||
} |
|||
if (location.protocol == "file:") { |
|||
logger.error( |
|||
"WARNING: web-socket-js doesn't work in file:///... URL " + |
|||
"unless you set Flash Security Settings properly. " + |
|||
"Open the page via Web server i.e. http://..."); |
|||
} |
|||
|
|||
/** |
|||
* Our own implementation of WebSocket class using Flash. |
|||
* @param {string} url |
|||
* @param {array or string} protocols |
|||
* @param {string} proxyHost |
|||
* @param {int} proxyPort |
|||
* @param {string} headers |
|||
*/ |
|||
window.WebSocket = function(url, protocols, proxyHost, proxyPort, headers) { |
|||
var self = this; |
|||
self.__id = WebSocket.__nextId++; |
|||
WebSocket.__instances[self.__id] = self; |
|||
self.readyState = WebSocket.CONNECTING; |
|||
self.bufferedAmount = 0; |
|||
self.__events = {}; |
|||
if (!protocols) { |
|||
protocols = []; |
|||
} else if (typeof protocols == "string") { |
|||
protocols = [protocols]; |
|||
} |
|||
// Uses setTimeout() to make sure __createFlash() runs after the caller sets ws.onopen etc.
|
|||
// Otherwise, when onopen fires immediately, onopen is called before it is set.
|
|||
self.__createTask = setTimeout(function() { |
|||
WebSocket.__addTask(function() { |
|||
self.__createTask = null; |
|||
WebSocket.__flash.create( |
|||
self.__id, url, protocols, proxyHost || null, proxyPort || 0, headers || null); |
|||
}); |
|||
}, 0); |
|||
}; |
|||
|
|||
/** |
|||
* Send data to the web socket. |
|||
* @param {string} data The data to send to the socket. |
|||
* @return {boolean} True for success, false for failure. |
|||
*/ |
|||
WebSocket.prototype.send = function(data) { |
|||
if (this.readyState == WebSocket.CONNECTING) { |
|||
throw "INVALID_STATE_ERR: Web Socket connection has not been established"; |
|||
} |
|||
// We use encodeURIComponent() here, because FABridge doesn't work if
|
|||
// the argument includes some characters. We don't use escape() here
|
|||
// because of this:
|
|||
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Functions#escape_and_unescape_Functions
|
|||
// But it looks decodeURIComponent(encodeURIComponent(s)) doesn't
|
|||
// preserve all Unicode characters either e.g. "\uffff" in Firefox.
|
|||
// Note by wtritch: Hopefully this will not be necessary using ExternalInterface. Will require
|
|||
// additional testing.
|
|||
var result = WebSocket.__flash.send(this.__id, encodeURIComponent(data)); |
|||
if (result < 0) { // success
|
|||
return true; |
|||
} else { |
|||
this.bufferedAmount += result; |
|||
return false; |
|||
} |
|||
}; |
|||
|
|||
/** |
|||
* Close this web socket gracefully. |
|||
*/ |
|||
WebSocket.prototype.close = function() { |
|||
if (this.__createTask) { |
|||
clearTimeout(this.__createTask); |
|||
this.__createTask = null; |
|||
this.readyState = WebSocket.CLOSED; |
|||
return; |
|||
} |
|||
if (this.readyState == WebSocket.CLOSED || this.readyState == WebSocket.CLOSING) { |
|||
return; |
|||
} |
|||
this.readyState = WebSocket.CLOSING; |
|||
WebSocket.__flash.close(this.__id); |
|||
}; |
|||
|
|||
/** |
|||
* Implementation of {@link <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-registration">DOM 2 EventTarget Interface</a>} |
|||
* |
|||
* @param {string} type |
|||
* @param {function} listener |
|||
* @param {boolean} useCapture |
|||
* @return void |
|||
*/ |
|||
WebSocket.prototype.addEventListener = function(type, listener, useCapture) { |
|||
if (!(type in this.__events)) { |
|||
this.__events[type] = []; |
|||
} |
|||
this.__events[type].push(listener); |
|||
}; |
|||
|
|||
/** |
|||
* Implementation of {@link <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-registration">DOM 2 EventTarget Interface</a>} |
|||
* |
|||
* @param {string} type |
|||
* @param {function} listener |
|||
* @param {boolean} useCapture |
|||
* @return void |
|||
*/ |
|||
WebSocket.prototype.removeEventListener = function(type, listener, useCapture) { |
|||
if (!(type in this.__events)) return; |
|||
var events = this.__events[type]; |
|||
for (var i = events.length - 1; i >= 0; --i) { |
|||
if (events[i] === listener) { |
|||
events.splice(i, 1); |
|||
break; |
|||
} |
|||
} |
|||
}; |
|||
|
|||
/** |
|||
* Implementation of {@link <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-registration">DOM 2 EventTarget Interface</a>} |
|||
* |
|||
* @param {Event} event |
|||
* @return void |
|||
*/ |
|||
WebSocket.prototype.dispatchEvent = function(event) { |
|||
var events = this.__events[event.type] || []; |
|||
for (var i = 0; i < events.length; ++i) { |
|||
events[i](event); |
|||
} |
|||
var handler = this["on" + event.type]; |
|||
if (handler) handler.apply(this, [event]); |
|||
}; |
|||
|
|||
/** |
|||
* Handles an event from Flash. |
|||
* @param {Object} flashEvent |
|||
*/ |
|||
WebSocket.prototype.__handleEvent = function(flashEvent) { |
|||
|
|||
if ("readyState" in flashEvent) { |
|||
this.readyState = flashEvent.readyState; |
|||
} |
|||
if ("protocol" in flashEvent) { |
|||
this.protocol = flashEvent.protocol; |
|||
} |
|||
|
|||
var jsEvent; |
|||
if (flashEvent.type == "open" || flashEvent.type == "error") { |
|||
jsEvent = this.__createSimpleEvent(flashEvent.type); |
|||
} else if (flashEvent.type == "close") { |
|||
jsEvent = this.__createSimpleEvent("close"); |
|||
jsEvent.wasClean = flashEvent.wasClean ? true : false; |
|||
jsEvent.code = flashEvent.code; |
|||
jsEvent.reason = flashEvent.reason; |
|||
} else if (flashEvent.type == "message") { |
|||
var data = decodeURIComponent(flashEvent.message); |
|||
jsEvent = this.__createMessageEvent("message", data); |
|||
} else { |
|||
throw "unknown event type: " + flashEvent.type; |
|||
} |
|||
|
|||
this.dispatchEvent(jsEvent); |
|||
|
|||
}; |
|||
|
|||
WebSocket.prototype.__createSimpleEvent = function(type) { |
|||
if (document.createEvent && window.Event) { |
|||
var event = document.createEvent("Event"); |
|||
event.initEvent(type, false, false); |
|||
return event; |
|||
} else { |
|||
return {type: type, bubbles: false, cancelable: false}; |
|||
} |
|||
}; |
|||
|
|||
WebSocket.prototype.__createMessageEvent = function(type, data) { |
|||
if (window.MessageEvent && typeof(MessageEvent) == "function" && !window.opera) { |
|||
return new MessageEvent("message", { |
|||
"view": window, |
|||
"bubbles": false, |
|||
"cancelable": false, |
|||
"data": data |
|||
}); |
|||
} else if (document.createEvent && window.MessageEvent && !window.opera) { |
|||
var event = document.createEvent("MessageEvent"); |
|||
event.initMessageEvent("message", false, false, data, null, null, window, null); |
|||
return event; |
|||
} else { |
|||
// Old IE and Opera, the latter one truncates the data parameter after any 0x00 bytes.
|
|||
return {type: type, data: data, bubbles: false, cancelable: false}; |
|||
} |
|||
}; |
|||
|
|||
/** |
|||
* Define the WebSocket readyState enumeration. |
|||
*/ |
|||
WebSocket.CONNECTING = 0; |
|||
WebSocket.OPEN = 1; |
|||
WebSocket.CLOSING = 2; |
|||
WebSocket.CLOSED = 3; |
|||
|
|||
// Field to check implementation of WebSocket.
|
|||
WebSocket.__isFlashImplementation = true; |
|||
WebSocket.__initialized = false; |
|||
WebSocket.__flash = null; |
|||
WebSocket.__instances = {}; |
|||
WebSocket.__tasks = []; |
|||
WebSocket.__nextId = 0; |
|||
|
|||
/** |
|||
* Load a new flash security policy file. |
|||
* @param {string} url |
|||
*/ |
|||
WebSocket.loadFlashPolicyFile = function(url){ |
|||
WebSocket.__addTask(function() { |
|||
WebSocket.__flash.loadManualPolicyFile(url); |
|||
}); |
|||
}; |
|||
|
|||
/** |
|||
* Loads WebSocketMain.swf and creates WebSocketMain object in Flash. |
|||
*/ |
|||
WebSocket.__initialize = function() { |
|||
|
|||
if (WebSocket.__initialized) return; |
|||
WebSocket.__initialized = true; |
|||
|
|||
if (WebSocket.__swfLocation) { |
|||
// For backword compatibility.
|
|||
window.WEB_SOCKET_SWF_LOCATION = WebSocket.__swfLocation; |
|||
} |
|||
if (!window.WEB_SOCKET_SWF_LOCATION) { |
|||
logger.error("[WebSocket] set WEB_SOCKET_SWF_LOCATION to location of WebSocketMain.swf"); |
|||
return; |
|||
} |
|||
if (!window.WEB_SOCKET_SUPPRESS_CROSS_DOMAIN_SWF_ERROR && |
|||
!WEB_SOCKET_SWF_LOCATION.match(/(^|\/)WebSocketMainInsecure\.swf(\?.*)?$/) && |
|||
WEB_SOCKET_SWF_LOCATION.match(/^\w+:\/\/([^\/]+)/)) { |
|||
var swfHost = RegExp.$1; |
|||
if (location.host != swfHost) { |
|||
logger.error( |
|||
"[WebSocket] You must host HTML and WebSocketMain.swf in the same host " + |
|||
"('" + location.host + "' != '" + swfHost + "'). " + |
|||
"See also 'How to host HTML file and SWF file in different domains' section " + |
|||
"in README.md. If you use WebSocketMainInsecure.swf, you can suppress this message " + |
|||
"by WEB_SOCKET_SUPPRESS_CROSS_DOMAIN_SWF_ERROR = true;"); |
|||
} |
|||
} |
|||
var container = document.createElement("div"); |
|||
container.id = "webSocketContainer"; |
|||
// Hides Flash box. We cannot use display: none or visibility: hidden because it prevents
|
|||
// Flash from loading at least in IE. So we move it out of the screen at (-100, -100).
|
|||
// But this even doesn't work with Flash Lite (e.g. in Droid Incredible). So with Flash
|
|||
// Lite, we put it at (0, 0). This shows 1x1 box visible at left-top corner but this is
|
|||
// the best we can do as far as we know now.
|
|||
container.style.position = "absolute"; |
|||
if (WebSocket.__isFlashLite()) { |
|||
container.style.left = "0px"; |
|||
container.style.top = "0px"; |
|||
} else { |
|||
container.style.left = "-100px"; |
|||
container.style.top = "-100px"; |
|||
} |
|||
var holder = document.createElement("div"); |
|||
holder.id = "webSocketFlash"; |
|||
container.appendChild(holder); |
|||
document.body.appendChild(container); |
|||
// See this article for hasPriority:
|
|||
// http://help.adobe.com/en_US/as3/mobile/WS4bebcd66a74275c36cfb8137124318eebc6-7ffd.html
|
|||
swfobject.embedSWF( |
|||
WEB_SOCKET_SWF_LOCATION, |
|||
"webSocketFlash", |
|||
"1" /* width */, |
|||
"1" /* height */, |
|||
"10.0.0" /* SWF version */, |
|||
null, |
|||
null, |
|||
{hasPriority: true, swliveconnect : true, allowScriptAccess: "always"}, |
|||
null, |
|||
function(e) { |
|||
if (!e.success) { |
|||
logger.error("[WebSocket] swfobject.embedSWF failed"); |
|||
} |
|||
} |
|||
); |
|||
|
|||
}; |
|||
|
|||
/** |
|||
* Called by Flash to notify JS that it's fully loaded and ready |
|||
* for communication. |
|||
*/ |
|||
WebSocket.__onFlashInitialized = function() { |
|||
// We need to set a timeout here to avoid round-trip calls
|
|||
// to flash during the initialization process.
|
|||
setTimeout(function() { |
|||
WebSocket.__flash = document.getElementById("webSocketFlash"); |
|||
WebSocket.__flash.setCallerUrl(location.href); |
|||
WebSocket.__flash.setDebug(!!window.WEB_SOCKET_DEBUG); |
|||
for (var i = 0; i < WebSocket.__tasks.length; ++i) { |
|||
WebSocket.__tasks[i](); |
|||
} |
|||
WebSocket.__tasks = []; |
|||
}, 0); |
|||
}; |
|||
|
|||
/** |
|||
* Called by Flash to notify WebSockets events are fired. |
|||
*/ |
|||
WebSocket.__onFlashEvent = function() { |
|||
setTimeout(function() { |
|||
try { |
|||
// Gets events using receiveEvents() instead of getting it from event object
|
|||
// of Flash event. This is to make sure to keep message order.
|
|||
// It seems sometimes Flash events don't arrive in the same order as they are sent.
|
|||
var events = WebSocket.__flash.receiveEvents(); |
|||
for (var i = 0; i < events.length; ++i) { |
|||
WebSocket.__instances[events[i].webSocketId].__handleEvent(events[i]); |
|||
} |
|||
} catch (e) { |
|||
logger.error(e); |
|||
} |
|||
}, 0); |
|||
return true; |
|||
}; |
|||
|
|||
// Called by Flash.
|
|||
WebSocket.__log = function(message) { |
|||
logger.log(decodeURIComponent(message)); |
|||
}; |
|||
|
|||
// Called by Flash.
|
|||
WebSocket.__error = function(message) { |
|||
logger.error(decodeURIComponent(message)); |
|||
}; |
|||
|
|||
WebSocket.__addTask = function(task) { |
|||
if (WebSocket.__flash) { |
|||
task(); |
|||
} else { |
|||
WebSocket.__tasks.push(task); |
|||
} |
|||
}; |
|||
|
|||
/** |
|||
* Test if the browser is running flash lite. |
|||
* @return {boolean} True if flash lite is running, false otherwise. |
|||
*/ |
|||
WebSocket.__isFlashLite = function() { |
|||
if (!window.navigator || !window.navigator.mimeTypes) { |
|||
return false; |
|||
} |
|||
var mimeType = window.navigator.mimeTypes["application/x-shockwave-flash"]; |
|||
if (!mimeType || !mimeType.enabledPlugin || !mimeType.enabledPlugin.filename) { |
|||
return false; |
|||
} |
|||
return mimeType.enabledPlugin.filename.match(/flashlite/i) ? true : false; |
|||
}; |
|||
|
|||
if (!window.WEB_SOCKET_DISABLE_AUTO_INITIALIZATION) { |
|||
// NOTE:
|
|||
// This fires immediately if web_socket.js is dynamically loaded after
|
|||
// the document is loaded.
|
|||
swfobject.addDomLoadEvent(function() { |
|||
WebSocket.__initialize(); |
|||
}); |
|||
} |
|||
|
|||
})(); |
|||
Binary file not shown.
Loading…
Reference in new issue