├── image
├── user
│ ├── 1.jpg
│ ├── 2.jpg
│ ├── 3.jpg
│ ├── 4.jpg
│ ├── 5.jpg
│ ├── 6.jpg
│ ├── 7.jpg
│ ├── 8.jpg
│ └── 9.jpg
├── component.png
├── form-input.png
├── loading-cir.gif
├── send-loading.gif
├── im-unread-dot.png
├── im-cloud-arrow-me.png
└── im-cloud-arrow-you.png
├── css
├── font
│ ├── FontAwesome.otf
│ ├── fontawesome-webfont.eot
│ ├── fontawesome-webfont.ttf
│ └── fontawesome-webfont.woff
├── expression.css
├── im.css
└── font-awesome.min.css
├── script
├── flash
│ ├── WebSocketMain.swf
│ ├── WebSocketMainInsecure.swf
│ ├── swfobject.js
│ └── web_socket.js
├── promise-1.0.0.min.js
├── expression.js
├── jquery.nanoscroller.min.js
├── json2.js
├── av-chat-min.js
└── av-chat.js
├── rosters.php
├── README.md
├── Im.html
├── conversation.php
└── signature.php
/image/user/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/konukk/green-chat/HEAD/image/user/1.jpg
--------------------------------------------------------------------------------
/image/user/2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/konukk/green-chat/HEAD/image/user/2.jpg
--------------------------------------------------------------------------------
/image/user/3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/konukk/green-chat/HEAD/image/user/3.jpg
--------------------------------------------------------------------------------
/image/user/4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/konukk/green-chat/HEAD/image/user/4.jpg
--------------------------------------------------------------------------------
/image/user/5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/konukk/green-chat/HEAD/image/user/5.jpg
--------------------------------------------------------------------------------
/image/user/6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/konukk/green-chat/HEAD/image/user/6.jpg
--------------------------------------------------------------------------------
/image/user/7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/konukk/green-chat/HEAD/image/user/7.jpg
--------------------------------------------------------------------------------
/image/user/8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/konukk/green-chat/HEAD/image/user/8.jpg
--------------------------------------------------------------------------------
/image/user/9.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/konukk/green-chat/HEAD/image/user/9.jpg
--------------------------------------------------------------------------------
/image/component.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/konukk/green-chat/HEAD/image/component.png
--------------------------------------------------------------------------------
/image/form-input.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/konukk/green-chat/HEAD/image/form-input.png
--------------------------------------------------------------------------------
/image/loading-cir.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/konukk/green-chat/HEAD/image/loading-cir.gif
--------------------------------------------------------------------------------
/image/send-loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/konukk/green-chat/HEAD/image/send-loading.gif
--------------------------------------------------------------------------------
/css/font/FontAwesome.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/konukk/green-chat/HEAD/css/font/FontAwesome.otf
--------------------------------------------------------------------------------
/image/im-unread-dot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/konukk/green-chat/HEAD/image/im-unread-dot.png
--------------------------------------------------------------------------------
/image/im-cloud-arrow-me.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/konukk/green-chat/HEAD/image/im-cloud-arrow-me.png
--------------------------------------------------------------------------------
/image/im-cloud-arrow-you.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/konukk/green-chat/HEAD/image/im-cloud-arrow-you.png
--------------------------------------------------------------------------------
/script/flash/WebSocketMain.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/konukk/green-chat/HEAD/script/flash/WebSocketMain.swf
--------------------------------------------------------------------------------
/css/font/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/konukk/green-chat/HEAD/css/font/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/css/font/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/konukk/green-chat/HEAD/css/font/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/css/font/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/konukk/green-chat/HEAD/css/font/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/script/flash/WebSocketMainInsecure.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/konukk/green-chat/HEAD/script/flash/WebSocketMainInsecure.swf
--------------------------------------------------------------------------------
/rosters.php:
--------------------------------------------------------------------------------
1 | array('id'=>1, 'image'=>'./image/user/1.jpg', 'name'=>'艾伦', 'watch'=>'2,3,4,5,6,7,8,9'),
7 | '2' => array('id'=>2, 'image'=>'./image/user/2.jpg', 'name'=>'毕维斯', 'watch'=>'1,4,7,8'),
8 | '3' => array('id'=>3, 'image'=>'./image/user/3.jpg', 'name'=>'拜伦', 'watch'=>'1,2,6,5'),
9 | '4' => array('id'=>4, 'image'=>'./image/user/4.jpg', 'name'=>'道格拉斯', 'watch'=>'7,8,9'),
10 | '5' => array('id'=>5, 'image'=>'./image/user/5.jpg', 'name'=>'爱德华', 'watch'=>'4,6,8,9'),
11 | '6' => array('id'=>6, 'image'=>'./image/user/6.jpg', 'name'=>'加布力尔', 'watch'=>'1,3,5,7,9'),
12 | '7' => array('id'=>7, 'image'=>'./image/user/7.jpg', 'name'=>'雨果', 'watch'=>'2,4,5,8'),
13 | '8' => array('id'=>8, 'image'=>'./image/user/8.jpg', 'name'=>'里斯特', 'watch'=>'1,4,6,7,9'),
14 | '9' => array('id'=>9, 'image'=>'./image/user/9.jpg', 'name'=>'玛希', 'watch'=>'2,3,4,5,6,7,8')
15 | );
16 |
17 | $len = $id;
18 |
19 | $res = array();
20 | $res['me'] = $rosters[$id];
21 |
22 | $ids = explode(',', $rosters[$id]['watch']);
23 | foreach( $ids as $k=>$v ) {
24 | $res['rosters'][] = $rosters[$v];
25 | }
26 |
27 | echo json_encode($res);
--------------------------------------------------------------------------------
/css/expression.css:
--------------------------------------------------------------------------------
1 | @charset "utf-8";
2 | /* emotions */
3 | #emotions{left:0;width:395px;font-size:12px;z-index:1000;background:#fff;position:absolute;border:1px solid #E8E8E8;}
4 | #emotions a{color:#9ABBC8;padding:2px 7px;text-decoration:none;}
5 | #emotions img{border:0;}
6 | #emotions div{margin:5px 10px;padding:1px;overflow:hidden;}
7 | #emotions #prev,#emotions #next{margin-left:3px;background:#eee;}
8 | #emotions .categorys{color:#ccc;height:23px;color:#9ABBC8;overflow:hidden;}
9 | #emotions .categorys a{display:inline-block;}
10 | #emotions .categorys a:hover{text-decoration:underline;}
11 | #emotions .categorys a.current{cursor:default;background:#F0F0F0;-moz-border-radius:3px;-webkit-border-radius:3px;}
12 | #emotions .container{padding:1px;overflow:hidden;}
13 | #emotions .container a{float:left;width:26px;height:22px;text-align:center;padding:4px 2px;margin:-1px 0 0 -1px;border:1px solid #e8e8e8;}
14 | #emotions .container a:hover{z-index:2;position:relative;border:1px solid #0095cd;}
15 | #emotions .page{text-align:right;}
16 | #emotions .page a.current{color:#666;background-color:#fff;}
17 | #emotions .page a{margin-left:3px;color:#0078B6;background-color:#f3f3f3;}
18 | #emotions .page a:hover{background-color:#e7e7e7;}
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # green-chat
2 | A simply web im, javascript chat ui component. javascript即时聊天组件
3 |
4 | ## 功能
5 | - 单人聊天
6 | - 在线、下线状态
7 | - 信息发送状态
8 | - 聊天历史记录
9 | - 兼容IE8+(IE7未测试)、chrome等主流浏览器
10 |
11 | ## CHANGE LOGS
12 | - 添加发送表情功能
13 |
14 | ## TODO
15 | - 群聊
16 | - 移动端适配
17 |
18 | ## 项目说明
19 | - 如何运行例子
20 | 1. 项目需在服务器环境下运行
21 | 2. 同时打开 http://xxxx/im.html#1, http://xxxx/im.html#2 即可开始测试。改变#后面的数字可切换用户身份
22 |
23 | - 组件说明
24 |
25 | 
26 |
27 | - 组件间通过事件驱动,详见代码
28 |
29 | - 组件依赖(jquery, EventEmitter, nanoScroller, avchat.js, web_socket.js等)
30 |
31 | - 项目基于[LeanCloud](https://www.avoscloud.com) Javascript Chat实现
32 | 1. 实现了 获取聊天记录-conversation.php, 签名认证-signature.php
33 | 2. 如使用本项目代码需申请LeanCloud账号,将im.html, conversation.php, signature.php中的appId, appKey, masterKey做相应替换
34 |
35 | 得说下签名认证(signature.php)的实现,略坑...
36 | 具体要求可见[权限和认证](https://cn.avoscloud.com/docs/realtime.html),说下注意的点
37 | ```
38 | 1. peerid 是“字符“,是字符不是数字
39 | 2. 要实现Hmac-sha1算法,跟Base64什么的可没有关系。。。详见程序
40 | 3. 最容易忽视的是:watch_peer_id这个变量,需要按照”字符“升序排序的,字符升序!
41 | ```
42 |
43 | ## 如何集成
44 | 1. 加载相关依赖(详见例子im.html)
45 |
46 | 2. 实现“获取联系人列表”接口(本例中的rosters.php)
47 |
48 | 3. 初始化组件
49 |
50 | ```javascript
51 | Green.init({
52 | rostersUrl : 'rosters.php', // 联系人列表接口
53 | conversationUrl : 'conversation.php',// 聊天记录接口
54 | authUrl : 'signature.php'// 可选,签名认证接口
55 | });
56 | ```
57 |
--------------------------------------------------------------------------------
/Im.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Green Chat Example
5 |
6 |
7 |
10 |
11 |
12 |
13 |
16 |
20 |
23 |
26 |
27 |
28 |
29 |
30 |
37 |
38 |
--------------------------------------------------------------------------------
/conversation.php:
--------------------------------------------------------------------------------
1 | $v){
43 | $str .= $k.'='.$v.'&';
44 | }
45 | $str = substr($str,0,-1);
46 | $url .= $str; //$url=$url.$str;
47 |
48 | curl_setopt($curl, CURLOPT_URL, $url);
49 |
50 | break;
51 |
52 | case 'post':
53 | curl_setopt($curl, CURLOPT_URL, $url);
54 | curl_setopt($curl, CURLOPT_POST, 1);
55 | curl_setopt($curl, CURLOPT_POSTFIELDS, $params);
56 |
57 | break;
58 |
59 | default:
60 | $result = '';
61 |
62 | break;
63 | }
64 |
65 |
66 | $result = curl_exec($curl);
67 |
68 | curl_close($curl);
69 |
70 | return $result;
71 | }
72 |
--------------------------------------------------------------------------------
/signature.php:
--------------------------------------------------------------------------------
1 | $nonce, "timestamp" => $ts, "signature" => $sig, "watchIds" => $watchIds, "sp" => $superPeer);
27 |
28 | echo json_encode($res);
29 |
30 |
31 | function sign($str, $key) {
32 | $signature = "";
33 | if (function_exists('hash_hmac')) {
34 | $hmac = hash_hmac("sha1", $str, $key, true);
35 | $signature = bin2hex($hmac);
36 | } else {
37 | $blocksize = 64;
38 | $hashfunc = 'sha1';
39 | if (strlen($key) > $blocksize) {
40 | $key = pack('H*', $hashfunc($key));
41 | }
42 | $key = str_pad($key, $blocksize, chr(0x00));
43 | $ipad = str_repeat(chr(0x36), $blocksize);
44 | $opad = str_repeat(chr(0x5c), $blocksize);
45 | $hmac = pack(
46 | 'H*', $hashfunc(
47 | ($key ^ $opad) . pack(
48 | 'H*', $hashfunc(
49 | ($key ^ $ipad) . $str
50 | )
51 | )
52 | )
53 | );
54 | $signature = bin2hex($hmac);
55 | }
56 | return $signature;
57 | }
58 |
59 | function randomString( $length = 8 ) {
60 | $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
61 | $ret = "";
62 | for ( $i = 0; $i < $length; $i++ )
63 | {
64 | $ret .= $chars[ mt_rand(0, strlen($chars) - 1) ];
65 | }
66 | return $ret;
67 | }
68 |
--------------------------------------------------------------------------------
/script/promise-1.0.0.min.js:
--------------------------------------------------------------------------------
1 | !function(){var a,b,c,d;!function(){var e={},f={};a=function(a,b,c){e[a]={deps:b,callback:c}},d=c=b=function(a){function c(b){if("."!==b.charAt(0))return b;for(var c=b.split("/"),d=a.split("/").slice(0,-1),e=0,f=c.length;f>e;e++){var g=c[e];if(".."===g)d.pop();else{if("."===g)continue;d.push(g)}}return d.join("/")}if(d._eak_seen=e,f[a])return f[a];if(f[a]={},!e[a])throw new Error("Could not find module "+a);for(var g,h=e[a],i=h.deps,j=h.callback,k=[],l=0,m=i.length;m>l;l++)"exports"===i[l]?k.push(g={}):k.push(b(c(i[l])));var n=j.apply(this,k);return f[a]=g||n}}(),a("promise/all",["./utils","exports"],function(a,b){"use strict";function c(a){var b=this;if(!d(a))throw new TypeError("You must pass an array to all.");return new b(function(b,c){function d(a){return function(b){f(a,b)}}function f(a,c){h[a]=c,0===--i&&b(h)}var g,h=[],i=a.length;0===i&&b([]);for(var j=0;j";
62 | s = s.replace(sArr[i], reStr);
63 | }
64 | }
65 | }
66 | return s;
67 | }
68 |
69 | (function($){
70 | $.fn.SinaEmotion = function(target){
71 | var cat_current;
72 | var cat_page;
73 | $(this).click(function(event){
74 | event.stopPropagation();
75 |
76 | var eBottom = target.outerHeight();
77 | var eLeft = target.parent().offset().left - 1;
78 |
79 | if($('#emotions .categorys')[0]){
80 | $('#emotions').css({bottom: eBottom, left: eLeft});
81 | $('#emotions').toggle();
82 | return;
83 | }
84 | $('body').append('');
85 | $('#emotions').css({bottom: eBottom, left: eLeft});
86 | $('#emotions').html('正在加载,请稍候...
');
87 | $('#emotions').click(function(event){
88 | event.stopPropagation();
89 | });
90 |
91 | $('#emotions').html('');
92 | $('#emotions #prev').click(function(){
93 | showCategorys(cat_page - 1);
94 | });
95 | $('#emotions #next').click(function(){
96 | showCategorys(cat_page + 1);
97 | });
98 | showCategorys();
99 | showEmotions();
100 |
101 | });
102 | $('body').click(function(){
103 | $('#emotions').remove();
104 | });
105 | $.fn.insertText = function(text){
106 | this.each(function() {
107 | if(this.tagName !== 'INPUT' && this.tagName !== 'TEXTAREA') {return;}
108 | if (document.selection) {
109 | this.focus();
110 | var cr = document.selection.createRange();
111 | cr.text = text;
112 | cr.collapse();
113 | cr.select();
114 | }else if (this.selectionStart || this.selectionStart == '0') {
115 | var
116 | start = this.selectionStart,
117 | end = this.selectionEnd;
118 | this.value = this.value.substring(0, start)+ text+ this.value.substring(end, this.value.length);
119 | this.selectionStart = this.selectionEnd = start+text.length;
120 | }else {
121 | this.value += text;
122 | }
123 | });
124 | return this;
125 | }
126 | function showCategorys(){
127 | var page = arguments[0]?arguments[0]:0;
128 | if(page < 0 || page >= categorys.length / 5){
129 | return;
130 | }
131 | $('#emotions .categorys').html('');
132 | cat_page = page;
133 | for(var i = page * 5; i < (page + 1) * 5 && i < categorys.length; ++i){
134 | $('#emotions .categorys').append($('' + categorys[i] + ''));
135 | }
136 | $('#emotions .categorys a').click(function(){
137 | showEmotions($(this).text());
138 | });
139 | $('#emotions .categorys a').each(function(){
140 | if($(this).text() == cat_current){
141 | $(this).addClass('current');
142 | }
143 | });
144 | }
145 | function showEmotions(){
146 | var category = arguments[0]?arguments[0]:'默认';
147 | var page = arguments[1]?arguments[1] - 1:0;
148 | $('#emotions .container').html('');
149 | $('#emotions .page').html('');
150 | cat_current = category;
151 | for(var i = page * 72; i < (page + 1) * 72 && i < emotions[category].length; ++i){
152 | $('#emotions .container').append($('
'));
153 | }
154 | $('#emotions .container a').click(function(){
155 | target.insertText($(this).attr('title'));
156 | $('#emotions').remove();
157 | });
158 | for(var i = 1; i < emotions[category].length / 72 + 1; ++i){
159 | $('#emotions .page').append($('' + i + ''));
160 | }
161 | $('#emotions .page a').click(function(){
162 | showEmotions(category, $(this).text());
163 | });
164 | $('#emotions .categorys a.current').removeClass('current');
165 | $('#emotions .categorys a').each(function(){
166 | if($(this).text() == category){
167 | $(this).addClass('current');
168 | }
169 | });
170 | }
171 | }
172 | })(jQuery);
173 |
--------------------------------------------------------------------------------
/script/jquery.nanoscroller.min.js:
--------------------------------------------------------------------------------
1 | /*! nanoScrollerJS - v0.8.0 - (c) 2014 James Florentino; Licensed MIT */
2 |
3 | !function(a,b,c){"use strict";var d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F;x={paneClass:"nano-pane",sliderClass:"nano-slider",contentClass:"nano-content",iOSNativeScrolling:!1,preventPageScrolling:!1,disableResize:!1,alwaysVisible:!1,flashDelay:1500,sliderMinHeight:20,sliderMaxHeight:null,documentContext:null,windowContext:null},s="scrollbar",r="scroll",k="mousedown",l="mousemove",n="mousewheel",m="mouseup",q="resize",h="drag",u="up",p="panedown",f="DOMMouseScroll",g="down",v="wheel",i="keydown",j="keyup",t="touchmove",d="Microsoft Internet Explorer"===b.navigator.appName&&/msie 7./i.test(b.navigator.appVersion)&&b.ActiveXObject,e=null,B=b.requestAnimationFrame,w=b.cancelAnimationFrame,D=c.createElement("div").style,F=function(){var a,b,c,d,e,f;for(d=["t","webkitT","MozT","msT","OT"],a=e=0,f=d.length;f>e;a=++e)if(c=d[a],b=d[a]+"ransform",b in D)return d[a].substr(0,d[a].length-1);return!1}(),E=function(a){return F===!1?!1:""===F?a:F+a.charAt(0).toUpperCase()+a.substr(1)},C=E("transform"),z=C!==!1,y=function(){var a,b,d;return a=c.createElement("div"),b=a.style,b.position="absolute",b.width="100px",b.height="100px",b.overflow=r,b.top="-9999px",c.body.appendChild(a),d=a.offsetWidth-a.clientWidth,c.body.removeChild(a),d},A=function(){var a,c,d;return c=b.navigator.userAgent,(a=/(?=.+Mac OS X)(?=.+Firefox)/.test(c))?(d=/Firefox\/\d{2}\./.exec(c),d&&(d=d[0].replace(/\D+/g,"")),a&&+d>23):!1},o=function(){function i(d,f){this.el=d,this.options=f,e||(e=y()),this.$el=a(this.el),this.doc=a(this.options.documentContext||c),this.win=a(this.options.windowContext||b),this.$content=this.$el.children("."+f.contentClass),this.$content.attr("tabindex",this.options.tabIndex||0),this.content=this.$content[0],this.previousPosition=0,this.options.iOSNativeScrolling&&null!=this.el.style.WebkitOverflowScrolling?this.nativeScrolling():this.generate(),this.createEvents(),this.addEvents(),this.reset()}return i.prototype.preventScrolling=function(a,b){if(this.isActive)if(a.type===f)(b===g&&a.originalEvent.detail>0||b===u&&a.originalEvent.detail<0)&&a.preventDefault();else if(a.type===n){if(!a.originalEvent||!a.originalEvent.wheelDelta)return;(b===g&&a.originalEvent.wheelDelta<0||b===u&&a.originalEvent.wheelDelta>0)&&a.preventDefault()}},i.prototype.nativeScrolling=function(){this.$content.css({WebkitOverflowScrolling:"touch"}),this.iOSNativeScrolling=!0,this.isActive=!0},i.prototype.updateScrollValues=function(){var a,b;a=this.content,this.maxScrollTop=a.scrollHeight-a.clientHeight,this.prevScrollTop=this.contentScrollTop||0,this.contentScrollTop=a.scrollTop,b=this.contentScrollTop>this.previousPosition?"down":this.contentScrollTop=a.maxScrollTop&&a.prevScrollTop!==a.maxScrollTop?a.$el.trigger("scrollend"):0===a.contentScrollTop&&0!==a.prevScrollTop&&a.$el.trigger("scrolltop"),!1}}(this),up:function(a){return function(){return a.isBeingDragged=!1,a.pane.removeClass("active"),a.doc.unbind(l,a.events[h]).unbind(m,a.events[u]),!1}}(this),resize:function(a){return function(){a.reset()}}(this),panedown:function(a){return function(b){return a.sliderY=(b.offsetY||b.originalEvent.layerY)-.5*a.sliderHeight,a.scroll(),a.events.down(b),!1}}(this),scroll:function(a){return function(b){a.updateScrollValues(),a.isBeingDragged||(a.iOSNativeScrolling||(a.sliderY=a.sliderTop,a.setOnScrollStyles()),null!=b&&(a.contentScrollTop>=a.maxScrollTop?(a.options.preventPageScrolling&&a.preventScrolling(b,g),a.prevScrollTop!==a.maxScrollTop&&a.$el.trigger("scrollend")):0===a.contentScrollTop&&(a.options.preventPageScrolling&&a.preventScrolling(b,u),0!==a.prevScrollTop&&a.$el.trigger("scrolltop"))))}}(this),wheel:function(a){return function(b){var c;if(null!=b)return c=b.delta||b.wheelDelta||b.originalEvent&&b.originalEvent.wheelDelta||-b.detail||b.originalEvent&&-b.originalEvent.detail,c&&(a.sliderY+=-c/3),a.scroll(),!1}}(this)}},i.prototype.addEvents=function(){var a;this.removeEvents(),a=this.events,this.options.disableResize||this.win.bind(q,a[q]),this.iOSNativeScrolling||(this.slider.bind(k,a[g]),this.pane.bind(k,a[p]).bind(""+n+" "+f,a[v])),this.$content.bind(""+r+" "+n+" "+f+" "+t,a[r])},i.prototype.removeEvents=function(){var a;a=this.events,this.win.unbind(q,a[q]),this.iOSNativeScrolling||(this.slider.unbind(),this.pane.unbind()),this.$content.unbind(""+r+" "+n+" "+f+" "+t,a[r])},i.prototype.generate=function(){var a,c,d,f,g,h;return f=this.options,g=f.paneClass,h=f.sliderClass,a=f.contentClass,this.$el.find("."+g).length||this.$el.find("."+h).length||this.$el.append(''),this.pane=this.$el.children("."+g),this.slider=this.pane.find("."+h),0===e&&A()?(d=b.getComputedStyle(this.content,null).getPropertyValue("padding-right").replace(/\D+/g,""),c={right:-14,paddingRight:+d+14}):e&&(c={right:-e},this.$el.addClass("has-scrollbar")),null!=c&&this.$content.css(c),this},i.prototype.restore=function(){this.stopped=!1,this.iOSNativeScrolling||this.pane.show(),this.addEvents()},i.prototype.reset=function(){var a,b,c,f,g,h,i,j,k,l,m,n;return this.iOSNativeScrolling?void(this.contentHeight=this.content.scrollHeight):(this.$el.find("."+this.options.paneClass).length||this.generate().stop(),this.stopped&&this.restore(),a=this.content,f=a.style,g=f.overflowY,d&&this.$content.css({height:this.$content.height()}),b=a.scrollHeight+e,l=parseInt(this.$el.css("max-height"),10),l>0&&(this.$el.height(""),this.$el.height(a.scrollHeight>l?l:a.scrollHeight)),i=this.pane.outerHeight(!1),k=parseInt(this.pane.css("top"),10),h=parseInt(this.pane.css("bottom"),10),j=i+k+h,n=Math.round(j/b*j),nthis.options.sliderMaxHeight&&(n=this.options.sliderMaxHeight),g===r&&f.overflowX!==r&&(n+=e),this.maxSliderTop=j-n,this.contentHeight=b,this.paneHeight=i,this.paneOuterHeight=j,this.sliderHeight=n,this.slider.height(n),this.events.scroll(),this.pane.show(),this.isActive=!0,a.scrollHeight===a.clientHeight||this.pane.outerHeight(!0)>=a.scrollHeight&&g!==r?(this.pane.hide(),this.isActive=!1):this.el.clientHeight===a.scrollHeight&&g===r?this.slider.hide():this.slider.show(),this.pane.css({opacity:this.options.alwaysVisible?1:"",visibility:this.options.alwaysVisible?"visible":""}),c=this.$content.css("position"),("static"===c||"relative"===c)&&(m=parseInt(this.$content.css("right"),10),m&&this.$content.css({right:"",marginRight:m})),this)},i.prototype.scroll=function(){return this.isActive?(this.sliderY=Math.max(0,this.sliderY),this.sliderY=Math.min(this.maxSliderTop,this.sliderY),this.$content.scrollTop((this.paneHeight-this.contentHeight+e)*this.sliderY/this.maxSliderTop*-1),this.iOSNativeScrolling||(this.updateScrollValues(),this.setOnScrollStyles()),this):void 0},i.prototype.scrollBottom=function(a){return this.isActive?(this.$content.scrollTop(this.contentHeight-this.$content.height()-a).trigger(n),this.stop().restore(),this):void 0},i.prototype.scrollTop=function(a){return this.isActive?(this.$content.scrollTop(+a).trigger(n),this.stop().restore(),this):void 0},i.prototype.scrollTo=function(a){return this.isActive?(this.scrollTop(this.$el.find(a).get(0).offsetTop),this):void 0},i.prototype.stop=function(){return w&&this.scrollRAF&&(w(this.scrollRAF),this.scrollRAF=null),this.stopped=!0,this.removeEvents(),this.iOSNativeScrolling||this.pane.hide(),this},i.prototype.destroy=function(){return this.stopped||this.stop(),!this.iOSNativeScrolling&&this.pane.length&&this.pane.remove(),d&&this.$content.height(""),this.$content.removeAttr("tabindex"),this.$el.hasClass("has-scrollbar")&&(this.$el.removeClass("has-scrollbar"),this.$content.css({right:""})),this},i.prototype.flash=function(){return!this.iOSNativeScrolling&&this.isActive?(this.reset(),this.pane.addClass("flashed"),setTimeout(function(a){return function(){a.pane.removeClass("flashed")}}(this),this.options.flashDelay),this):void 0},i}(),a.fn.nanoScroller=function(b){return this.each(function(){var c,d;if((d=this.nanoscroller)||(c=a.extend({},x,b),this.nanoscroller=d=new o(this,c)),b&&"object"==typeof b){if(a.extend(d.options,b),null!=b.scrollBottom)return d.scrollBottom(b.scrollBottom);if(null!=b.scrollTop)return d.scrollTop(b.scrollTop);if(b.scrollTo)return d.scrollTo(b.scrollTo);if("bottom"===b.scroll)return d.scrollBottom(0);if("top"===b.scroll)return d.scrollTop(0);if(b.scroll&&b.scroll instanceof a)return d.scrollTo(b.scroll);if(b.stop)return d.stop();if(b.destroy)return d.destroy();if(b.flash)return d.flash()}return d.reset()})},a.fn.nanoScroller.Constructor=o}(jQuery,window,document);
4 |
--------------------------------------------------------------------------------
/script/flash/swfobject.js:
--------------------------------------------------------------------------------
1 | /* SWFObject v2.2
2 | is released under the MIT License
3 | */
4 | var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="ShockwaveFlash.ShockwaveFlash",q="application/x-shockwave-flash",R="SWFObjectExprInst",x="onreadystatechange",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,X=!+"\v1",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\s+(\S+\s+\S+$)/,"$1");ag[0]=parseInt(ab.replace(/^(.*)\..*$/,"$1"),10);ag[1]=parseInt(ab.replace(/^.*\.(.*)\s.*$/,"$1"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else{if(typeof O.ActiveXObject!=D){try{var ad=new ActiveXObject(W);if(ad){ab=ad.GetVariable("$version");if(ab){X=true;ab=ab.split(" ")[1].split(",");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState=="complete")||(typeof j.readyState==D&&(j.getElementsByTagName("body")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener("DOMContentLoaded",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState=="complete"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll("left")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName("body")[0].appendChild(C("span"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y0){for(var af=0;af0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute("width")||"0";ai.height=ae.getAttribute("height")||"0";if(ae.getAttribute("class")){ai.styleclass=ae.getAttribute("class")}if(ae.getAttribute("align")){ai.align=ae.getAttribute("align")}var ah={};var X=ae.getElementsByTagName("param");var ac=X.length;for(var ad=0;ad'}}aa.outerHTML='";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute("type",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()=="styleclass"){Z.setAttribute("class",ai[ac])}else{if(ac.toLowerCase()!="classid"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!="movie"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C("param");aa.setAttribute("name",X);aa.setAttribute("value",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName=="OBJECT"){if(M.ie&&M.win){X.style.display="none";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]=="function"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(".");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName("head")[0];if(!aa){return}var X=(ad&&typeof ad=="string")?ad:"screen";if(ab){n=null;G=null}if(!n||G!=X){var Z=C("style");Z.setAttribute("type","text/css");Z.setAttribute("media",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+" {"+Y+"}"))}}}function w(Z,X){if(!m){return}var Y=X?"visible":"hidden";if(J&&c(Z)){c(Z).style.visibility=Y}else{v("#"+Z,"visibility:"+Y)}}function L(Y){var Z=/[\\\"<>\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent("onunload",function(){var ac=I.length;for(var ab=0;ab
2 | // License: New BSD License
3 | // Reference: http://dev.w3.org/html5/websockets/
4 | // Reference: http://tools.ietf.org/html/rfc6455
5 |
6 | (function() {
7 |
8 | if (window.WEB_SOCKET_FORCE_FLASH) {
9 | // Keeps going.
10 | } else if (window.WebSocket) {
11 | return;
12 | } else if (window.MozWebSocket) {
13 | // Firefox.
14 | window.WebSocket = MozWebSocket;
15 | return;
16 | }
17 |
18 | var logger;
19 | if (window.WEB_SOCKET_LOGGER) {
20 | logger = WEB_SOCKET_LOGGER;
21 | } else if (window.console && window.console.log && window.console.error) {
22 | // In some environment, console is defined but console.log or console.error is missing.
23 | logger = window.console;
24 | } else {
25 | logger = {log: function(){ }, error: function(){ }};
26 | }
27 |
28 | // swfobject.hasFlashPlayerVersion("10.0.0") doesn't work with Gnash.
29 | if (swfobject.getFlashPlayerVersion().major < 10) {
30 | logger.error("Flash Player >= 10.0.0 is required.");
31 | return;
32 | }
33 | if (location.protocol == "file:") {
34 | logger.error(
35 | "WARNING: web-socket-js doesn't work in file:///... URL " +
36 | "unless you set Flash Security Settings properly. " +
37 | "Open the page via Web server i.e. http://...");
38 | }
39 |
40 | /**
41 | * Our own implementation of WebSocket class using Flash.
42 | * @param {string} url
43 | * @param {array or string} protocols
44 | * @param {string} proxyHost
45 | * @param {int} proxyPort
46 | * @param {string} headers
47 | */
48 | window.WebSocket = function(url, protocols, proxyHost, proxyPort, headers) {
49 | var self = this;
50 | self.__id = WebSocket.__nextId++;
51 | WebSocket.__instances[self.__id] = self;
52 | self.readyState = WebSocket.CONNECTING;
53 | self.bufferedAmount = 0;
54 | self.__events = {};
55 | if (!protocols) {
56 | protocols = [];
57 | } else if (typeof protocols == "string") {
58 | protocols = [protocols];
59 | }
60 | // Uses setTimeout() to make sure __createFlash() runs after the caller sets ws.onopen etc.
61 | // Otherwise, when onopen fires immediately, onopen is called before it is set.
62 | self.__createTask = setTimeout(function() {
63 | WebSocket.__addTask(function() {
64 | self.__createTask = null;
65 | WebSocket.__flash.create(
66 | self.__id, url, protocols, proxyHost || null, proxyPort || 0, headers || null);
67 | });
68 | }, 0);
69 | };
70 |
71 | /**
72 | * Send data to the web socket.
73 | * @param {string} data The data to send to the socket.
74 | * @return {boolean} True for success, false for failure.
75 | */
76 | WebSocket.prototype.send = function(data) {
77 | if (this.readyState == WebSocket.CONNECTING) {
78 | throw "INVALID_STATE_ERR: Web Socket connection has not been established";
79 | }
80 | // We use encodeURIComponent() here, because FABridge doesn't work if
81 | // the argument includes some characters. We don't use escape() here
82 | // because of this:
83 | // https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Functions#escape_and_unescape_Functions
84 | // But it looks decodeURIComponent(encodeURIComponent(s)) doesn't
85 | // preserve all Unicode characters either e.g. "\uffff" in Firefox.
86 | // Note by wtritch: Hopefully this will not be necessary using ExternalInterface. Will require
87 | // additional testing.
88 | var result = WebSocket.__flash.send(this.__id, encodeURIComponent(data));
89 | if (result < 0) { // success
90 | return true;
91 | } else {
92 | this.bufferedAmount += result;
93 | return false;
94 | }
95 | };
96 |
97 | /**
98 | * Close this web socket gracefully.
99 | */
100 | WebSocket.prototype.close = function() {
101 | if (this.__createTask) {
102 | clearTimeout(this.__createTask);
103 | this.__createTask = null;
104 | this.readyState = WebSocket.CLOSED;
105 | return;
106 | }
107 | if (this.readyState == WebSocket.CLOSED || this.readyState == WebSocket.CLOSING) {
108 | return;
109 | }
110 | this.readyState = WebSocket.CLOSING;
111 | WebSocket.__flash.close(this.__id);
112 | };
113 |
114 | /**
115 | * Implementation of {@link DOM 2 EventTarget Interface}
116 | *
117 | * @param {string} type
118 | * @param {function} listener
119 | * @param {boolean} useCapture
120 | * @return void
121 | */
122 | WebSocket.prototype.addEventListener = function(type, listener, useCapture) {
123 | if (!(type in this.__events)) {
124 | this.__events[type] = [];
125 | }
126 | this.__events[type].push(listener);
127 | };
128 |
129 | /**
130 | * Implementation of {@link DOM 2 EventTarget Interface}
131 | *
132 | * @param {string} type
133 | * @param {function} listener
134 | * @param {boolean} useCapture
135 | * @return void
136 | */
137 | WebSocket.prototype.removeEventListener = function(type, listener, useCapture) {
138 | if (!(type in this.__events)) return;
139 | var events = this.__events[type];
140 | for (var i = events.length - 1; i >= 0; --i) {
141 | if (events[i] === listener) {
142 | events.splice(i, 1);
143 | break;
144 | }
145 | }
146 | };
147 |
148 | /**
149 | * Implementation of {@link DOM 2 EventTarget Interface}
150 | *
151 | * @param {Event} event
152 | * @return void
153 | */
154 | WebSocket.prototype.dispatchEvent = function(event) {
155 | var events = this.__events[event.type] || [];
156 | for (var i = 0; i < events.length; ++i) {
157 | events[i](event);
158 | }
159 | var handler = this["on" + event.type];
160 | if (handler) handler.apply(this, [event]);
161 | };
162 |
163 | /**
164 | * Handles an event from Flash.
165 | * @param {Object} flashEvent
166 | */
167 | WebSocket.prototype.__handleEvent = function(flashEvent) {
168 |
169 | if ("readyState" in flashEvent) {
170 | this.readyState = flashEvent.readyState;
171 | }
172 | if ("protocol" in flashEvent) {
173 | this.protocol = flashEvent.protocol;
174 | }
175 |
176 | var jsEvent;
177 | if (flashEvent.type == "open" || flashEvent.type == "error") {
178 | jsEvent = this.__createSimpleEvent(flashEvent.type);
179 | } else if (flashEvent.type == "close") {
180 | jsEvent = this.__createSimpleEvent("close");
181 | jsEvent.wasClean = flashEvent.wasClean ? true : false;
182 | jsEvent.code = flashEvent.code;
183 | jsEvent.reason = flashEvent.reason;
184 | } else if (flashEvent.type == "message") {
185 | var data = decodeURIComponent(flashEvent.message);
186 | jsEvent = this.__createMessageEvent("message", data);
187 | } else {
188 | throw "unknown event type: " + flashEvent.type;
189 | }
190 |
191 | this.dispatchEvent(jsEvent);
192 |
193 | };
194 |
195 | WebSocket.prototype.__createSimpleEvent = function(type) {
196 | if (document.createEvent && window.Event) {
197 | var event = document.createEvent("Event");
198 | event.initEvent(type, false, false);
199 | return event;
200 | } else {
201 | return {type: type, bubbles: false, cancelable: false};
202 | }
203 | };
204 |
205 | WebSocket.prototype.__createMessageEvent = function(type, data) {
206 | if (window.MessageEvent && typeof(MessageEvent) == "function" && !window.opera) {
207 | return new MessageEvent("message", {
208 | "view": window,
209 | "bubbles": false,
210 | "cancelable": false,
211 | "data": data
212 | });
213 | } else if (document.createEvent && window.MessageEvent && !window.opera) {
214 | var event = document.createEvent("MessageEvent");
215 | event.initMessageEvent("message", false, false, data, null, null, window, null);
216 | return event;
217 | } else {
218 | // Old IE and Opera, the latter one truncates the data parameter after any 0x00 bytes.
219 | return {type: type, data: data, bubbles: false, cancelable: false};
220 | }
221 | };
222 |
223 | /**
224 | * Define the WebSocket readyState enumeration.
225 | */
226 | WebSocket.CONNECTING = 0;
227 | WebSocket.OPEN = 1;
228 | WebSocket.CLOSING = 2;
229 | WebSocket.CLOSED = 3;
230 |
231 | // Field to check implementation of WebSocket.
232 | WebSocket.__isFlashImplementation = true;
233 | WebSocket.__initialized = false;
234 | WebSocket.__flash = null;
235 | WebSocket.__instances = {};
236 | WebSocket.__tasks = [];
237 | WebSocket.__nextId = 0;
238 |
239 | /**
240 | * Load a new flash security policy file.
241 | * @param {string} url
242 | */
243 | WebSocket.loadFlashPolicyFile = function(url){
244 | WebSocket.__addTask(function() {
245 | WebSocket.__flash.loadManualPolicyFile(url);
246 | });
247 | };
248 |
249 | /**
250 | * Loads WebSocketMain.swf and creates WebSocketMain object in Flash.
251 | */
252 | WebSocket.__initialize = function() {
253 |
254 | if (WebSocket.__initialized) return;
255 | WebSocket.__initialized = true;
256 |
257 | if (WebSocket.__swfLocation) {
258 | // For backword compatibility.
259 | window.WEB_SOCKET_SWF_LOCATION = WebSocket.__swfLocation;
260 | }
261 | if (!window.WEB_SOCKET_SWF_LOCATION) {
262 | logger.error("[WebSocket] set WEB_SOCKET_SWF_LOCATION to location of WebSocketMain.swf");
263 | return;
264 | }
265 | if (!window.WEB_SOCKET_SUPPRESS_CROSS_DOMAIN_SWF_ERROR &&
266 | !WEB_SOCKET_SWF_LOCATION.match(/(^|\/)WebSocketMainInsecure\.swf(\?.*)?$/) &&
267 | WEB_SOCKET_SWF_LOCATION.match(/^\w+:\/\/([^\/]+)/)) {
268 | var swfHost = RegExp.$1;
269 | if (location.host != swfHost) {
270 | logger.error(
271 | "[WebSocket] You must host HTML and WebSocketMain.swf in the same host " +
272 | "('" + location.host + "' != '" + swfHost + "'). " +
273 | "See also 'How to host HTML file and SWF file in different domains' section " +
274 | "in README.md. If you use WebSocketMainInsecure.swf, you can suppress this message " +
275 | "by WEB_SOCKET_SUPPRESS_CROSS_DOMAIN_SWF_ERROR = true;");
276 | }
277 | }
278 | var container = document.createElement("div");
279 | container.id = "webSocketContainer";
280 | // Hides Flash box. We cannot use display: none or visibility: hidden because it prevents
281 | // Flash from loading at least in IE. So we move it out of the screen at (-100, -100).
282 | // But this even doesn't work with Flash Lite (e.g. in Droid Incredible). So with Flash
283 | // Lite, we put it at (0, 0). This shows 1x1 box visible at left-top corner but this is
284 | // the best we can do as far as we know now.
285 | container.style.position = "absolute";
286 | if (WebSocket.__isFlashLite()) {
287 | container.style.left = "0px";
288 | container.style.top = "0px";
289 | } else {
290 | container.style.left = "-100px";
291 | container.style.top = "-100px";
292 | }
293 | var holder = document.createElement("div");
294 | holder.id = "webSocketFlash";
295 | container.appendChild(holder);
296 | document.body.appendChild(container);
297 | // See this article for hasPriority:
298 | // http://help.adobe.com/en_US/as3/mobile/WS4bebcd66a74275c36cfb8137124318eebc6-7ffd.html
299 | swfobject.embedSWF(
300 | WEB_SOCKET_SWF_LOCATION,
301 | "webSocketFlash",
302 | "1" /* width */,
303 | "1" /* height */,
304 | "10.0.0" /* SWF version */,
305 | null,
306 | null,
307 | {hasPriority: true, swliveconnect : true, allowScriptAccess: "always"},
308 | null,
309 | function(e) {
310 | if (!e.success) {
311 | logger.error("[WebSocket] swfobject.embedSWF failed");
312 | }
313 | }
314 | );
315 |
316 | };
317 |
318 | /**
319 | * Called by Flash to notify JS that it's fully loaded and ready
320 | * for communication.
321 | */
322 | WebSocket.__onFlashInitialized = function() {
323 | // We need to set a timeout here to avoid round-trip calls
324 | // to flash during the initialization process.
325 | setTimeout(function() {
326 | WebSocket.__flash = document.getElementById("webSocketFlash");
327 | WebSocket.__flash.setCallerUrl(location.href);
328 | WebSocket.__flash.setDebug(!!window.WEB_SOCKET_DEBUG);
329 | for (var i = 0; i < WebSocket.__tasks.length; ++i) {
330 | WebSocket.__tasks[i]();
331 | }
332 | WebSocket.__tasks = [];
333 | }, 0);
334 | };
335 |
336 | /**
337 | * Called by Flash to notify WebSockets events are fired.
338 | */
339 | WebSocket.__onFlashEvent = function() {
340 | setTimeout(function() {
341 | try {
342 | // Gets events using receiveEvents() instead of getting it from event object
343 | // of Flash event. This is to make sure to keep message order.
344 | // It seems sometimes Flash events don't arrive in the same order as they are sent.
345 | var events = WebSocket.__flash.receiveEvents();
346 | for (var i = 0; i < events.length; ++i) {
347 | WebSocket.__instances[events[i].webSocketId].__handleEvent(events[i]);
348 | }
349 | } catch (e) {
350 | logger.error(e);
351 | }
352 | }, 0);
353 | return true;
354 | };
355 |
356 | // Called by Flash.
357 | WebSocket.__log = function(message) {
358 | logger.log(decodeURIComponent(message));
359 | };
360 |
361 | // Called by Flash.
362 | WebSocket.__error = function(message) {
363 | logger.error(decodeURIComponent(message));
364 | };
365 |
366 | WebSocket.__addTask = function(task) {
367 | if (WebSocket.__flash) {
368 | task();
369 | } else {
370 | WebSocket.__tasks.push(task);
371 | }
372 | };
373 |
374 | /**
375 | * Test if the browser is running flash lite.
376 | * @return {boolean} True if flash lite is running, false otherwise.
377 | */
378 | WebSocket.__isFlashLite = function() {
379 | if (!window.navigator || !window.navigator.mimeTypes) {
380 | return false;
381 | }
382 | var mimeType = window.navigator.mimeTypes["application/x-shockwave-flash"];
383 | if (!mimeType || !mimeType.enabledPlugin || !mimeType.enabledPlugin.filename) {
384 | return false;
385 | }
386 | return mimeType.enabledPlugin.filename.match(/flashlite/i) ? true : false;
387 | };
388 |
389 | if (!window.WEB_SOCKET_DISABLE_AUTO_INITIALIZATION) {
390 | // NOTE:
391 | // This fires immediately if web_socket.js is dynamically loaded after
392 | // the document is loaded.
393 | swfobject.addDomLoadEvent(function() {
394 | WebSocket.__initialize();
395 | });
396 | }
397 |
398 | })();
399 |
--------------------------------------------------------------------------------
/css/im.css:
--------------------------------------------------------------------------------
1 | html,body,div,span,h1,h2,h3,h4,h5,h6,p,pre,a,code,em,img,small,strong,sub,sup,u,i,center,dl,dt,dd,ol,ul,li,label,textarea,table,td,tr,tbody{margin:0;padding:0;list-style:none;border:0;}
2 | b, strong{font-weight:normal;}
3 | :focus{outline:0}
4 | a{text-decoration:none}
5 | a:hover{text-decoration:underline}
6 | body{font:12px/1.5 tahoma,arial,宋体b8b\4f53,sans-serif;color:#333}
7 | .clear{clear:both;overflow:hidden;height:0;}
8 | .cf:before, .cf:after{content:"";display:table}
9 | .cf:after{clear:both}
10 | .cf{*zoom:1}
11 |
12 | .nano {position:relative;width:100%;height:100%;overflow:hidden;}
13 | .nano > .nano-content{position:absolute;overflow-x:hidden;top:0;right:0;bottom:0;left:0;}
14 | .nano > .nano-content:focus{outline:none}
15 | .nano > .nano-content::-webkit-scrollbar{visibility:hidden}
16 | .has-scrollbar > .nano-content::-webkit-scrollbar{visibility:visible}
17 | .nano > .nano-pane{background:rgba(0,0,0,.25);position:absolute;width:10px;right:0;top:0;bottom:0;visibility:hidden\9;opacity:.01;-webkit-transition:.2s;-moz-transition:.2s;-o-transition:.2s;transition:.2s;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;}
18 | .nano > .nano-pane > .nano-slider{background:#444;background:rgba(0,0,0,.5);position:relative;margin:0 1px;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}
19 | .nano:hover > .nano-pane, .nano-pane.active, .nano-pane.flashed{visibility:visible\9;opacity:0.99}
20 |
21 | .greenchat{position:fixed;right:0;bottom:0;z-index:1000}
22 | .greenchat-inner{position:relative;}
23 | .greenchat .chat-status{display:inline-block;width:7px;height:7px;border-width:1px;border-style:solid;border-radius:2px;overflow:hidden;}
24 | .greenchat .offline{background-color:#D4D4D4;border-color:#B8B8B8;}
25 | .greenchat .online{background-color:#8FDC00;border-color:#48C000}
26 |
27 | .greenchat .status-view{position:absolute;right:0;bottom:0;width:200px;height:100%;line-height:100%;text-align:center;z-index:105;background:#fff;opacity:0.8;color:#29422D;font-size:15px}
28 | /*.contacts-minus .status-view{width:67px;}*/
29 |
30 | .contacts{position:absolute;right:0;bottom:0;width:200px;z-index:103;background:#fff;border:1px solid #bbb;box-shadow:0 0 5px rgba(0, 0, 75, 0.2);-moz-transition:opacity .4s ease;-webkit-transition opacity .4s ease;transition:opacity .4s ease 0s;}
31 | .contacts .title{position:relative;cursor:pointer;background:#F6F6F6;height:39px;line-height:39px;font-size:13px;text-align:center;border-bottom:1px solid #969696;box-shadow:0 2px 2px rgba(0, 0, 0, 0.1);}
32 | .contacts .title b{font-weight:normal;padding-left:5px;}
33 | .contacts .im-log{display:none;position:absolute;bottom:31px;left:0;width:200px;overflow:hidden;height:38px;line-height:38px;font-size:12px;color:#c00;text-align:center;color:#EF672F;background:#FFFFF3;border-top:1px solid #ddd;opacity:0.95;filter:alpha(opacity=95);z-index:9999}
34 | .contacts .im-log img{vertical-align:-4px;margin-right:5px}
35 | .contacts .nano{width:100%;height:500px}
36 | .contacts .nano .nano-content{padding:10px 0;}
37 | .contacts .roster{cursor:pointer;height:36px;overflow:hidden;position:relative;padding:10px 15px;text-align:left}
38 | .contacts .roster .unread-dot{position:absolute;background:url(../image/im-unread-dot.png) no-repeat -5px -980px;width:28px;height:24px;left:36px;top:0;text-align:center;line-height:25px;font-size:12px;color:#FFF}
39 | .contacts .roster .unread-dots{border:5px solid red;position:absolute;left:53px;top:5px;border-radius:10px}
40 | .contacts .roster .avatar-wrap{line-height:0;float:left;margin-right:13px;}
41 | .contacts .roster .avatar{width:36px;height:36px;border-radius:0;/*box-shadow:0px 1px 2px #919191;border-top:1px solid #aaa;border:1px solid #fff*/}
42 | .contacts .roster .info{overflow:hidden;text-shadow:none}
43 | .contacts .roster .nick-name{color:#343434;font-size:13px;width:130px;line-height:36px;white-space:nowrap;text-overflow:ellipsis;-o-text-overflow:ellipsis;overflow:hidden}
44 | .contacts .roster .nick-name .name{white-space:nowrap;max-width:121px;overflow:hidden;word-wrap:normal;text-overflow:ellipsis;-o-text-overflow:ellipsis;font-size:12px}
45 | .contacts .roster:hover{opacity:0.7}
46 | .contacts .roster .chat-status{position:absolute;bottom:9px;left:43px;}
47 | .contacts .bottom{cursor:pointer;text-align:center;line-height:30px;background:#F2F4F8;border-top:solid 1px #C9D0DA;box-shadow:0 -1px 1px rgba(0, 0, 0, 0.1);}
48 | .contacts .bottom .online-status{display:none;position:relative;width:67px;height:30px;float:left;border-right:solid 1px #C9D0DA;}
49 | .contacts .bottom .online-status span{float:left;margin:12px 0 0 17px;margin:10px\9 0 0 17px;}
50 | .contacts .bottom .toggle-btn{height:30px;font-size:12px}
51 | .contacts .bottom .toggle-btn i{color:#888;}
52 | .contacts .bottom .toggle-btn b{font-weight:normal;padding-left:10px;}
53 | .contacts .bottom .toggle-btn .forward{display:block}
54 | .contacts .bottom .toggle-btn .backward{display:none}
55 |
56 | .contacts-minus{width:67px;}
57 | .contacts-minus .roster .info, .contacts-minus .roster .extend{display:none;}
58 | .contacts-minus .title b{display:none;}
59 | .contacts-minus .title i{font-size:16px;}
60 | .contacts-minus .bottom .online-status{height:50px;background:#f7f7f7;border-bottom:solid 1px #C9D0DA;}
61 | .contacts-minus .bottom .online-status span{float:none;margin:10px 0 0;}
62 | .contacts-minus .bottom .online-status .status-text{line-height:30px}
63 | .contacts-minus .bottom .toggle-btn{clear:both;}
64 | .contacts-minus .bottom .toggle-btn b{display:none;}
65 | .contacts-minus .bottom .toggle-btn .forward{display:none}
66 | .contacts-minus .bottom .toggle-btn .backward{display:block}
67 |
68 | .chatbox-wrap{display:none;position:absolute;right:230px;bottom:0;width:530px;overflow:hidden}
69 |
70 | .chatbox-wrap-contacts-minus{right:95px;}
71 |
72 | .chatbox-wrap .pannel{display:none;float:left;width:130px;height:467px;}
73 | .chatbox-wrap .pannel .usr-list{width:130px;padding:10px 0 20px;background:#deE1E3;border-left:1px solid #ccc;}
74 | .chatbox-wrap .pannel .usr-list .nano{width:100%;height:399px;}
75 | .chatbox-wrap .pannel .usr-list .nano-content{height:399px}
76 | .chatbox-wrap .pannel .usr-list .chat-with{position:relative;cursor:pointer;padding:4px 15px;}
77 | .chatbox-wrap .pannel .usr-list .chat-with .list-head-status{float:left;margin:11px 10px 0 0;margin:9px\9 10px 0 0;}
78 | .chatbox-wrap .pannel .usr-list .chat-with .chat-with-name{float:left;height:30px;width:70px;line-height:30px;overflow:hidden;}
79 | .chatbox-wrap .pannel .usr-list .chat-with .chat-close{display:none;color:#aaa;width:12px;height:12px;position:absolute;top:13px;right:15px;}
80 | .chatbox-wrap .pannel .usr-list .chat-with .chat-close:hover{color:#ffa200;text-decoration:none}
81 | .chatbox-wrap .pannel .usr-list .chat-with .msg-unread{display:none;color:#aaa;width:12px;height:12px;position:absolute;top:13px;right:2px;}
82 | .chatbox-wrap .pannel .usr-list .chat-with .msg-unread i{color:#C00;font-size:10px;}
83 | .chatbox-wrap .pannel .usr-list .active{background:#3D71C0;color:#fff;border-top:1px solid #c7c7c7;border-bottom:1px solid #c7c7c7}
84 | .chatbox-wrap .pannel .usr-list .active .chat-with-name{font-weight:bold;}
85 | .chatbox-wrap .pannel .usr-list .chat-with:hover .chat-close{display:block}
86 |
87 | .chatbox-wrap .chatbox{float:right;width:400px;height:467px;position:relative;box-shadow: 0 3px 5px -1px #CCC;}
88 | .chatbox-wrap .c-tit{height:30px;line-height:30px;padding:8px 5px 8px 13px;color:#fff;text-align:center;border:1px solid;border-color:#ddd #ddd #c0c0c0 #ddd;background-color:#EAECEE;background:-webkit-gradient(linear, 0 0, 0 100%, from(#F8F9FA), to(#DADDDF));background:-moz-linear-gradient(top, #F8F9FA, #DADDDF);border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;-webkit-border-radius:4px 4px 0 0;color:#383E45}
89 | .chatbox-wrap .c-tit .chat-with{float:left;font-size:15px;letter-spacing:1.5px}
90 | .chatbox-wrap .c-tit .chat-with img{width:30px;height:30px;vertical-align:middle;margin-right:7px}
91 | .chatbox-wrap .c-tit .chat-opt{width:60px;height:30px;float:right;font-size:15px;}
92 | .chatbox-wrap .c-tit .chat-opt i{margin-left:7px;cursor:pointer;font-size:18px;}
93 |
94 | .chatbox-wrap .send{position:absolute;left:0;bottom:0;z-index:101;padding:10px 10px 10px 11px;text-align:left;border:1px solid;border-color:#ccc #e2e2e2 #DDD #e2e2e2;background-color:#EAECEE;background:-webkit-gradient(linear, 0 0, 0 100%, from(#F8F9FA), to(#DADDDF));background:-moz-linear-gradient(top, #F8F9FA, #DADDDF);border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;-webkit-border-radius:0 0 4px 4px;color:#383E45}
95 | .chatbox-wrap .send i{float:left;padding:8px 0 0;font-size:20px;color:#888;letter-spacing:10px;text-shadow: 0px 0px 2px #fff;}
96 | .chatbox-wrap .send textarea{float:left;resize:none;width:272px;height:19px;line-height:19px;padding:8px 5px;border:1px solid #c7c7c7;background:url(../image/form-input.png) left top no-repeat white;border-radius:3px}
97 | .chatbox-wrap .send .btn{float:left;display:block;width:60px;height:36px;margin:0 0 0 5px;line-height:36px;text-align:center;font-size:14px;font-family:黑体;letter-spacing:2px;color:#fff;text-decoration:none;background:#389D44;border-radius:4px;cursor:pointer;border:none}
98 |
99 | .chatbox-wrap .convers .nano{position:absolute;left:0;top:48px;width:398px;height:360px;background-color:#fff;border:1px solid #ccc;border-top:none;border-bottom:none;}
100 | .chatbox-wrap .convers .messages{padding:10px 25px 5px 15px;*padding:10px 35px 5px 15px;}
101 |
102 | .chatbox-wrap .convers .you{float:left}
103 | .chatbox-wrap .convers .you .time{margin:0 0 5px 55px}
104 | .chatbox-wrap .convers .you .avatar{float:left}
105 | .chatbox-wrap .convers .you .cloud{float:left;min-width:50px;max-width:285px;margin:0 0 0 15px}
106 | .chatbox-wrap .convers .you .cloud-body{-moz-border-top-colors:none;-moz-border-right-colors:none;-moz-border-bottom-colors:none;-moz-border-left-colors:none;border-color:transparent;border:1px solid #7AA23F;border-radius:5px;-moz-border-radius:5px;-webkit-border-radius:5px;box-shadow:0px 1px 0px #DBDBDB;border:1px solid #73972a;border-radius: 6px;background-color:#B2CF73;background:-webkit-gradient(linear, left top,left bottom, from(#C4DE94),to(#A4C363), color-stop(0.1,#B4D174),color-stop(0.2,#B2CF73), color-stop(0.3,#B2CF73), color-stop(0.4,#B2CF73), color-stop(0.5,#B2CF73),color-stop(0.6,#AFCC74), color-stop(0.7,#ABCA6C),color-stop(0.8,#AECA72), color-stop(0.9,#A9C572),color-stop(1.0,#A4C363));background-image:-moz-linear-gradient(top, #B4D174 10%, #B2CF7320%, #B2CF73 30%, #B2CF73 40%, #B2CF73 50%, #AFCC74 60%, #ABCA6C70%, #A9C572 80%, #AECA72 90%, #A4C363 100%);}
107 | .chatbox-wrap .convers .you .cloud-content{padding:5px 13px;border-radius:13px;border-radius:5px;-moz-border-radius:5px;-webkit-border-radius:5px;padding:7px 10px;text-shadow:none;color:#030303;border-top:1px solid #DCE6C8;border-bottom:1px solid #B9CF8B;border-right:1px solid #CCDEA3;background-color:#C0DC85}
108 | .chatbox-wrap .convers .you .cloud-arrow{position:absolute;left:-6px;top:11px;width:13px;height:24px;background:url(../image/im-cloud-arrow-you.png) no-repeat}
109 |
110 | .chatbox-wrap .convers .me{}
111 | .chatbox-wrap .convers .me .avatar{float:right}
112 | .chatbox-wrap .convers .me .time{text-align:right;margin:0 57px 5px 0}
113 | .chatbox-wrap .convers .me .cloud{float:right;min-width:50px;max-width:290px;margin:0 15px 0 0}
114 | .chatbox-wrap .convers .me .cloud-body{-moz-border-top-colors:none;-moz-border-right-colors:none;-moz-border-bottom-colors:none;-moz-border-left-colors:none;border-color:transparent;border:1px solid #AFAFAF;border-radius:5px;-moz-border-radius:5px;-webkit-border-radius:5px;box-shadow:0px 1px 0px #D5D5D5;border:1px solid #9f9f9f;background:#ECECEC;border-radius:6px;margin-left:8px}
115 | .chatbox-wrap .convers .me .cloud-content{vertical-align:top;padding:7px 10px;border:1px solid #eee;border-top:1px solid #FFF;border-bottom:1px solid #F2F2F2;border-radius:13px;border-radius:4px;-moz-border-radius:4px;-webkit-border-radius:4px;overflow:hidden;color:#000;text-shadow:none;background-color:#ECECEC;background:-webkit-gradient(linear, left top,left bottom, from(#F4F4F4),to(#E5E5E5), color-stop(0.1,#F3F3F3),color-stop(0.3,#F1F1F1),color-stop(0.5,#ECECEC),color-stop(0.7,#E9E9E9),color-stop(0.9,#E6E6E6),color-stop(1.0,#E5E5E5));background-image:-moz-linear-gradient(top, #F3F3F3 10%, #F1F1F1 30%, #ECECEC 50%, #E9E9E9 70%, #E6E6E6 90%, #E5E5E5 100%);}
116 | .chatbox-wrap .convers .me .cloud-arrow{position:absolute;right:-10px;top:11px;width:13px;height:24px;background:url(../image/im-cloud-arrow-me.png) no-repeat}
117 | .chatbox-wrap .convers .me .send-status{float:right;}
118 | .chatbox-wrap .convers .me .send-status img{margin-top:4px;}
119 | .chatbox-wrap .convers .me .send-status b{display:none;color:red;line-height: 39px;}
120 |
121 | .chatbox-wrap .convers .chat-item{width:100%;}
122 | .chatbox-wrap .convers .chat-item .time{font-size:12px;padding:2px 0;border-radius:20px;color:#999;text-shadow:0 1px 0 #fff}
123 | .chatbox-wrap .convers .chat-item{padding:4px 0px 10px 0px}
124 | .chatbox-wrap .convers .chat-item .avatar{width:38px;height:38px;border:1px solid #ccc;border:1px solid #FFF;box-shadow:0px 1px 0px #B3B6BA}
125 | .chatbox-wrap .convers .chat-item .cloud-pannel{position:relative}
126 | .chatbox-wrap .convers .chat-item .cloud-content{text-align:left;font-weight:normal;font-size:14px;min-height:20px;word-wrap:break-word}
127 | .chatbox-wrap .convers .chat-item pre{margin:0;font:14px/21px Helvetica,微软雅黑,黑体,Arial,Tahoma;}
128 | .chatbox-wrap .convers .loadmore{cursor:pointer;height:20px;margin:0 0 5px;text-align:center;color:#A2C7EF}
129 | .chatbox-wrap .convers .loadmore .lloading{display:none;}
130 | .chatbox-wrap .convers .loadmore i{margin-right:7px}
131 | .chatbox-wrap .convers .loadmore b{font-weight:normal}
132 | .chatbox-wrap .convers .loadmore-loading{cursor:default;}
133 | .chatbox-wrap .convers .loadmore-loading .linit{display:none}
134 | .chatbox-wrap .convers .loadmore-loading .lloading{display:block}
135 | .chatbox-wrap .convers .loadmore-loading .lloading img{vertical-align:-4px;margin-right:5px;}
136 | .chatbox-wrap .convers .no-more-history{display:none;height:20px;margin:0 0 5px;text-align:center;color:#ccc}
137 | .chatbox-wrap .convers .no-more-history i{margin-right:7px}
138 | .chatbox-wrap .convers .no-more-history b{font-weight:normal}
139 |
140 | .chatbox-wrap .convers .send-success .send-status{display:none;}
141 | .chatbox-wrap .convers .send-failed .send-status img{display:none;}
142 | .chatbox-wrap .convers .send-failed .send-status b{display:block;}
143 |
144 | .multi-chatbox .c-tit{border-left:1px solid #ccc;border-radius:0 4px 0 0;-moz-border-radius:0 4px 0 0;-webkit-border-radius:0 4px 0 0}
145 | .multi-chatbox .convers .nano{border:1px solid #c3c3c3;border-top:none;border-bottom:none}
146 | .multi-chatbox .send{border-left:1px solid #c3c3c3;}
147 | .multi-chatbox .pannel{display:block}
148 | .multi-chatbox .chatusr-tit{padding:8px 0;font-size:12px;color:#999;border-left:1px solid #ddd;border-right:none;border-bottom:1px solid #d1d1d1;border-radius:4px 0 0 0;-moz-border-radius:4px 0 0 0;-webkit-border-radius:4px 0 0 0}
149 | .multi-chatbox .chatusr-tit i{color:#999;margin:0 8px 0 0}
150 |
151 | .chatbox-wrap .minus-pannel{display:none;width:182px;height:30px;border:solid 1px #CCC;text-align:center;line-height:30px;line-height:26px\9;box-shadow:0 0 5px rgba(0, 0, 75, 0.2);border-radius:1px 1px 0 0;cursor:pointer;background-color:#EAECEE;background:-webkit-gradient(linear, 0 0, 0 100%, from(#F8F9FA), to(#DADDDF));background:-moz-linear-gradient(top, #F8F9FA, #DADDDF);}
152 | .chatbox-wrap .minus-pannel b{font-weight:normal;}
153 | .chatbox-wrap .minus-pannel i{margin-right:10px;color:#aaa;}
154 |
155 | .chatbox-minus .nano, .chatbox-minus .send{display:none}
156 | .chatbox-minus{width:200px;}
157 | .chatbox-minus .pannel, .chatbox-minus .chatbox{display:none;}
158 | .chatbox-minus .new-msg{background:green;}
159 | .chatbox-minus .minus-pannel{display:block}
160 |
161 | .chat-new-message .minus-pannel{background:#09a92b;color:#fff;}
162 | .chat-new-message .minus-pannel i{color:#ddd;}
163 |
164 | #emotions{left:0;font-size:12px;z-index:1000;background:#fff;position:absolute;border:1px solid #E8E8E8;}
165 | #emotions a{color:#9ABBC8;padding:2px 7px;text-decoration:none;}
166 | #emotions img{border:0;}
167 | #emotions div{margin:5px 10px;padding:1px;overflow:hidden;}
168 | #emotions #prev,#emotions #next{margin-left:3px;background:#eee;}
169 | #emotions .categorys{color:#ccc;height:23px;color:#9ABBC8;overflow:hidden;}
170 | #emotions .categorys a{display:inline-block;}
171 | #emotions .categorys a:hover{text-decoration:underline;}
172 | #emotions .categorys a.current{cursor:default;background:#F0F0F0;-moz-border-radius:3px;-webkit-border-radius:3px;}
173 | #emotions .container{padding:1px;overflow:hidden;}
174 | #emotions .container a{float:left;width:26px;height:22px;text-align:center;padding:4px 2px;margin:-1px 0 0 -1px;border:1px solid #e8e8e8;}
175 | #emotions .container a:hover{z-index:2;position:relative;border:1px solid #0095cd;}
176 | #emotions .page{text-align:right;}
177 | #emotions .page a.current{color:#666;background-color:#fff;}
178 | #emotions .page a{margin-left:3px;color:#0078B6;background-color:#f3f3f3;}
179 | #emotions .page a:hover{background-color:#e7e7e7;}
180 |
181 |
--------------------------------------------------------------------------------
/script/json2.js:
--------------------------------------------------------------------------------
1 | /*
2 | json2.js
3 | 2014-02-04
4 |
5 | Public Domain.
6 |
7 | NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
8 |
9 | See http://www.JSON.org/js.html
10 |
11 |
12 | This code should be minified before deployment.
13 | See http://javascript.crockford.com/jsmin.html
14 |
15 | USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
16 | NOT CONTROL.
17 |
18 |
19 | This file creates a global JSON object containing two methods: stringify
20 | and parse.
21 |
22 | JSON.stringify(value, replacer, space)
23 | value any JavaScript value, usually an object or array.
24 |
25 | replacer an optional parameter that determines how object
26 | values are stringified for objects. It can be a
27 | function or an array of strings.
28 |
29 | space an optional parameter that specifies the indentation
30 | of nested structures. If it is omitted, the text will
31 | be packed without extra whitespace. If it is a number,
32 | it will specify the number of spaces to indent at each
33 | level. If it is a string (such as '\t' or ' '),
34 | it contains the characters used to indent at each level.
35 |
36 | This method produces a JSON text from a JavaScript value.
37 |
38 | When an object value is found, if the object contains a toJSON
39 | method, its toJSON method will be called and the result will be
40 | stringified. A toJSON method does not serialize: it returns the
41 | value represented by the name/value pair that should be serialized,
42 | or undefined if nothing should be serialized. The toJSON method
43 | will be passed the key associated with the value, and this will be
44 | bound to the value
45 |
46 | For example, this would serialize Dates as ISO strings.
47 |
48 | Date.prototype.toJSON = function (key) {
49 | function f(n) {
50 | // Format integers to have at least two digits.
51 | return n < 10 ? '0' + n : n;
52 | }
53 |
54 | return this.getUTCFullYear() + '-' +
55 | f(this.getUTCMonth() + 1) + '-' +
56 | f(this.getUTCDate()) + 'T' +
57 | f(this.getUTCHours()) + ':' +
58 | f(this.getUTCMinutes()) + ':' +
59 | f(this.getUTCSeconds()) + 'Z';
60 | };
61 |
62 | You can provide an optional replacer method. It will be passed the
63 | key and value of each member, with this bound to the containing
64 | object. The value that is returned from your method will be
65 | serialized. If your method returns undefined, then the member will
66 | be excluded from the serialization.
67 |
68 | If the replacer parameter is an array of strings, then it will be
69 | used to select the members to be serialized. It filters the results
70 | such that only members with keys listed in the replacer array are
71 | stringified.
72 |
73 | Values that do not have JSON representations, such as undefined or
74 | functions, will not be serialized. Such values in objects will be
75 | dropped; in arrays they will be replaced with null. You can use
76 | a replacer function to replace those with JSON values.
77 | JSON.stringify(undefined) returns undefined.
78 |
79 | The optional space parameter produces a stringification of the
80 | value that is filled with line breaks and indentation to make it
81 | easier to read.
82 |
83 | If the space parameter is a non-empty string, then that string will
84 | be used for indentation. If the space parameter is a number, then
85 | the indentation will be that many spaces.
86 |
87 | Example:
88 |
89 | text = JSON.stringify(['e', {pluribus: 'unum'}]);
90 | // text is '["e",{"pluribus":"unum"}]'
91 |
92 |
93 | text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
94 | // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
95 |
96 | text = JSON.stringify([new Date()], function (key, value) {
97 | return this[key] instanceof Date ?
98 | 'Date(' + this[key] + ')' : value;
99 | });
100 | // text is '["Date(---current time---)"]'
101 |
102 |
103 | JSON.parse(text, reviver)
104 | This method parses a JSON text to produce an object or array.
105 | It can throw a SyntaxError exception.
106 |
107 | The optional reviver parameter is a function that can filter and
108 | transform the results. It receives each of the keys and values,
109 | and its return value is used instead of the original value.
110 | If it returns what it received, then the structure is not modified.
111 | If it returns undefined then the member is deleted.
112 |
113 | Example:
114 |
115 | // Parse the text. Values that look like ISO date strings will
116 | // be converted to Date objects.
117 |
118 | myData = JSON.parse(text, function (key, value) {
119 | var a;
120 | if (typeof value === 'string') {
121 | a =
122 | /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
123 | if (a) {
124 | return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
125 | +a[5], +a[6]));
126 | }
127 | }
128 | return value;
129 | });
130 |
131 | myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
132 | var d;
133 | if (typeof value === 'string' &&
134 | value.slice(0, 5) === 'Date(' &&
135 | value.slice(-1) === ')') {
136 | d = new Date(value.slice(5, -1));
137 | if (d) {
138 | return d;
139 | }
140 | }
141 | return value;
142 | });
143 |
144 |
145 | This is a reference implementation. You are free to copy, modify, or
146 | redistribute.
147 | */
148 |
149 | /*jslint evil: true, regexp: true */
150 |
151 | /*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
152 | call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
153 | getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
154 | lastIndex, length, parse, prototype, push, replace, slice, stringify,
155 | test, toJSON, toString, valueOf
156 | */
157 |
158 |
159 | // Create a JSON object only if one does not already exist. We create the
160 | // methods in a closure to avoid creating global variables.
161 |
162 | if (typeof JSON !== 'object') {
163 | JSON = {};
164 | }
165 |
166 | (function () {
167 | 'use strict';
168 |
169 | function f(n) {
170 | // Format integers to have at least two digits.
171 | return n < 10 ? '0' + n : n;
172 | }
173 |
174 | if (typeof Date.prototype.toJSON !== 'function') {
175 |
176 | Date.prototype.toJSON = function () {
177 |
178 | return isFinite(this.valueOf())
179 | ? this.getUTCFullYear() + '-' +
180 | f(this.getUTCMonth() + 1) + '-' +
181 | f(this.getUTCDate()) + 'T' +
182 | f(this.getUTCHours()) + ':' +
183 | f(this.getUTCMinutes()) + ':' +
184 | f(this.getUTCSeconds()) + 'Z'
185 | : null;
186 | };
187 |
188 | String.prototype.toJSON =
189 | Number.prototype.toJSON =
190 | Boolean.prototype.toJSON = function () {
191 | return this.valueOf();
192 | };
193 | }
194 |
195 | var cx,
196 | escapable,
197 | gap,
198 | indent,
199 | meta,
200 | rep;
201 |
202 |
203 | function quote(string) {
204 |
205 | // If the string contains no control characters, no quote characters, and no
206 | // backslash characters, then we can safely slap some quotes around it.
207 | // Otherwise we must also replace the offending characters with safe escape
208 | // sequences.
209 |
210 | escapable.lastIndex = 0;
211 | return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
212 | var c = meta[a];
213 | return typeof c === 'string'
214 | ? c
215 | : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
216 | }) + '"' : '"' + string + '"';
217 | }
218 |
219 |
220 | function str(key, holder) {
221 |
222 | // Produce a string from holder[key].
223 |
224 | var i, // The loop counter.
225 | k, // The member key.
226 | v, // The member value.
227 | length,
228 | mind = gap,
229 | partial,
230 | value = holder[key];
231 |
232 | // If the value has a toJSON method, call it to obtain a replacement value.
233 |
234 | if (value && typeof value === 'object' &&
235 | typeof value.toJSON === 'function') {
236 | value = value.toJSON(key);
237 | }
238 |
239 | // If we were called with a replacer function, then call the replacer to
240 | // obtain a replacement value.
241 |
242 | if (typeof rep === 'function') {
243 | value = rep.call(holder, key, value);
244 | }
245 |
246 | // What happens next depends on the value's type.
247 |
248 | switch (typeof value) {
249 | case 'string':
250 | return quote(value);
251 |
252 | case 'number':
253 |
254 | // JSON numbers must be finite. Encode non-finite numbers as null.
255 |
256 | return isFinite(value) ? String(value) : 'null';
257 |
258 | case 'boolean':
259 | case 'null':
260 |
261 | // If the value is a boolean or null, convert it to a string. Note:
262 | // typeof null does not produce 'null'. The case is included here in
263 | // the remote chance that this gets fixed someday.
264 |
265 | return String(value);
266 |
267 | // If the type is 'object', we might be dealing with an object or an array or
268 | // null.
269 |
270 | case 'object':
271 |
272 | // Due to a specification blunder in ECMAScript, typeof null is 'object',
273 | // so watch out for that case.
274 |
275 | if (!value) {
276 | return 'null';
277 | }
278 |
279 | // Make an array to hold the partial results of stringifying this object value.
280 |
281 | gap += indent;
282 | partial = [];
283 |
284 | // Is the value an array?
285 |
286 | if (Object.prototype.toString.apply(value) === '[object Array]') {
287 |
288 | // The value is an array. Stringify every element. Use null as a placeholder
289 | // for non-JSON values.
290 |
291 | length = value.length;
292 | for (i = 0; i < length; i += 1) {
293 | partial[i] = str(i, value) || 'null';
294 | }
295 |
296 | // Join all of the elements together, separated with commas, and wrap them in
297 | // brackets.
298 |
299 | v = partial.length === 0
300 | ? '[]'
301 | : gap
302 | ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
303 | : '[' + partial.join(',') + ']';
304 | gap = mind;
305 | return v;
306 | }
307 |
308 | // If the replacer is an array, use it to select the members to be stringified.
309 |
310 | if (rep && typeof rep === 'object') {
311 | length = rep.length;
312 | for (i = 0; i < length; i += 1) {
313 | if (typeof rep[i] === 'string') {
314 | k = rep[i];
315 | v = str(k, value);
316 | if (v) {
317 | partial.push(quote(k) + (gap ? ': ' : ':') + v);
318 | }
319 | }
320 | }
321 | } else {
322 |
323 | // Otherwise, iterate through all of the keys in the object.
324 |
325 | for (k in value) {
326 | if (Object.prototype.hasOwnProperty.call(value, k)) {
327 | v = str(k, value);
328 | if (v) {
329 | partial.push(quote(k) + (gap ? ': ' : ':') + v);
330 | }
331 | }
332 | }
333 | }
334 |
335 | // Join all of the member texts together, separated with commas,
336 | // and wrap them in braces.
337 |
338 | v = partial.length === 0
339 | ? '{}'
340 | : gap
341 | ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
342 | : '{' + partial.join(',') + '}';
343 | gap = mind;
344 | return v;
345 | }
346 | }
347 |
348 | // If the JSON object does not yet have a stringify method, give it one.
349 |
350 | if (typeof JSON.stringify !== 'function') {
351 | escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
352 | meta = { // table of character substitutions
353 | '\b': '\\b',
354 | '\t': '\\t',
355 | '\n': '\\n',
356 | '\f': '\\f',
357 | '\r': '\\r',
358 | '"' : '\\"',
359 | '\\': '\\\\'
360 | };
361 | JSON.stringify = function (value, replacer, space) {
362 |
363 | // The stringify method takes a value and an optional replacer, and an optional
364 | // space parameter, and returns a JSON text. The replacer can be a function
365 | // that can replace values, or an array of strings that will select the keys.
366 | // A default replacer method can be provided. Use of the space parameter can
367 | // produce text that is more easily readable.
368 |
369 | var i;
370 | gap = '';
371 | indent = '';
372 |
373 | // If the space parameter is a number, make an indent string containing that
374 | // many spaces.
375 |
376 | if (typeof space === 'number') {
377 | for (i = 0; i < space; i += 1) {
378 | indent += ' ';
379 | }
380 |
381 | // If the space parameter is a string, it will be used as the indent string.
382 |
383 | } else if (typeof space === 'string') {
384 | indent = space;
385 | }
386 |
387 | // If there is a replacer, it must be a function or an array.
388 | // Otherwise, throw an error.
389 |
390 | rep = replacer;
391 | if (replacer && typeof replacer !== 'function' &&
392 | (typeof replacer !== 'object' ||
393 | typeof replacer.length !== 'number')) {
394 | throw new Error('JSON.stringify');
395 | }
396 |
397 | // Make a fake root object containing our value under the key of ''.
398 | // Return the result of stringifying the value.
399 |
400 | return str('', {'': value});
401 | };
402 | }
403 |
404 |
405 | // If the JSON object does not yet have a parse method, give it one.
406 |
407 | if (typeof JSON.parse !== 'function') {
408 | cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
409 | JSON.parse = function (text, reviver) {
410 |
411 | // The parse method takes a text and an optional reviver function, and returns
412 | // a JavaScript value if the text is a valid JSON text.
413 |
414 | var j;
415 |
416 | function walk(holder, key) {
417 |
418 | // The walk method is used to recursively walk the resulting structure so
419 | // that modifications can be made.
420 |
421 | var k, v, value = holder[key];
422 | if (value && typeof value === 'object') {
423 | for (k in value) {
424 | if (Object.prototype.hasOwnProperty.call(value, k)) {
425 | v = walk(value, k);
426 | if (v !== undefined) {
427 | value[k] = v;
428 | } else {
429 | delete value[k];
430 | }
431 | }
432 | }
433 | }
434 | return reviver.call(holder, key, value);
435 | }
436 |
437 |
438 | // Parsing happens in four stages. In the first stage, we replace certain
439 | // Unicode characters with escape sequences. JavaScript handles many characters
440 | // incorrectly, either silently deleting them, or treating them as line endings.
441 |
442 | text = String(text);
443 | cx.lastIndex = 0;
444 | if (cx.test(text)) {
445 | text = text.replace(cx, function (a) {
446 | return '\\u' +
447 | ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
448 | });
449 | }
450 |
451 | // In the second stage, we run the text against regular expressions that look
452 | // for non-JSON patterns. We are especially concerned with '()' and 'new'
453 | // because they can cause invocation, and '=' because it can cause mutation.
454 | // But just to be safe, we want to reject all unexpected forms.
455 |
456 | // We split the second stage into 4 regexp operations in order to work around
457 | // crippling inefficiencies in IE's and Safari's regexp engines. First we
458 | // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
459 | // replace all simple value tokens with ']' characters. Third, we delete all
460 | // open brackets that follow a colon or comma or that begin the text. Finally,
461 | // we look to see that the remaining characters are only whitespace or ']' or
462 | // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
463 |
464 | if (/^[\],:{}\s]*$/
465 | .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
466 | .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
467 | .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
468 |
469 | // In the third stage we use the eval function to compile the text into a
470 | // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
471 | // in JavaScript: it can begin a block or an object literal. We wrap the text
472 | // in parens to eliminate the ambiguity.
473 |
474 | j = eval('(' + text + ')');
475 |
476 | // In the optional fourth stage, we recursively walk the new structure, passing
477 | // each name/value pair to a reviver function for possible transformation.
478 |
479 | return typeof reviver === 'function'
480 | ? walk({'': j}, '')
481 | : j;
482 | }
483 |
484 | // If the text is not JSON parseable, then a SyntaxError is thrown.
485 |
486 | throw new SyntaxError('JSON.parse');
487 | };
488 | }
489 | }());
490 |
--------------------------------------------------------------------------------
/script/av-chat-min.js:
--------------------------------------------------------------------------------
1 | !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.AVChatClient=e()}}(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o0){clearTimeout(timers.shift()[1])}resolve(server)};ws.onclose=function(e){doClose();_emitter.emit("close",e)};ws.onmessage=function(message){var data=JSON.parse(message.data);var cmd=data.op?data.cmd+data.op:data.cmd;if(!cmd){cmd="{}"}if(_waitCommands.length>0&&_waitCommands[0][0]===cmd){_waitCommands.shift()[1](data)}if(timers.length>0&&timers[0][0]==cmd){clearTimeout(timers.shift()[1])}if(data.cmd=="session"){if(data.op=="opened"||data.op=="added"){_emitter.emit("online",data.onlineSessionPeerIds)}}else if(data.cmd=="presence"){if(data.status=="on"){_emitter.emit("online",data.sessionPeerIds)}else if(data.status=="off"){_emitter.emit("offline",data.sessionPeerIds)}}else if(data.cmd=="direct"){_emitter.emit("message",data);var msg={cmd:"ack",peerId:_settings.peerId,appId:_settings.appId,ids:[].concat(data.id)};var s=JSON.stringify(msg);ws.send(s)}else if(data.cmd=="room"){if(data.op=="members-joined"){_emitter.emit("membersJoined",data)}else if(data.op=="members-left"){_emitter.emit("membersLeft",data)}else if(data.op=="joined"){_emitter.emit("joined",data)}else if(data.op=="left"){_emitter.emit("left",data)}}}})}else{return _getServerInfo(_settings.appId,_settings.secure).then(function(result){server=result;server.expires=Date.now()+server.ttl*1e3;return _connect()})}}function _openSession(){return _settings.auth(_settings.peerId,_settings.watchingPeerIds,_settings.sp).then(function(data){_settings.watchingPeerIds=data.watchingPeerIds;return doCommand("session","open",{sessionPeerIds:data.watchingPeerIds,s:data.s,t:data.t,n:data.n,sp:data.sp})})}function _timeout(name,reject){timers.push([name,setTimeout(function(){if(reject){reject(name+"timeout")}doClose()},1e4)])}function _keepAlive(){clearTimeout(_keepAlive.handle);_keepAlive.handle=setTimeout(function(){if(ws.readyState==1){ws.send("{}");_timeout("{}");_keepAlive()}},keepAliveTimeout)}function doClose(){ws.close();clearTimeout(_keepAlive.handle);timers.forEach(function(v,i){clearTimeout(v[1])});_waitCommands.forEach(function(v){v[2]()});timers=[];_waitCommands=[]}function doCommand(cmd,op,props){_keepAlive();var msg={cmd:cmd,peerId:_settings.peerId,appId:_settings.appId};if(op){msg.op=op}if(props){for(k in props){msg[k]=props[k]}}if(!ws){return Promise.reject()}if(ws.readyState!=1){return Promise.reject(ws.readyState)}ws.send(JSON.stringify(msg));var c=typeof op=="undefined"?cmd:cmd+op;if(cmd=="direct"&&props.transient==true||["sessionremove","sessionclose"].indexOf(c)>-1){return Promise.resolve()}else{return new Promise(function(resolve,reject){_waitCommands.push([cmdMap[c]||c,resolve,reject]);_timeout(cmdMap[c]||c,reject)})}}this.open=function(){if(ws&&ws.readyState==0){return Promise.reject(0)}if(ws&&ws.readyState==1){return Promise.resolve()}timers.forEach(function(v,i){clearTimeout(v[1])});timers=[];return _connect().then(function(){return _openSession()})};this.close=function(){doCommand("session","close");doClose();return Promise.resolve()};this.send=function(msg,to,transient){var obj={msg:msg,toPeerIds:[].concat(to)};if(typeof transient!="undefined"&&transient==true){obj.transient=transient}return doCommand("direct",undefined,obj)};this.on=function(name,func){_emitter.on(name,func)};this.watch=function(peers){return _settings.auth(_settings.peerId,[].concat(peers)).then(function(data){var watch=[].concat(data.watchingPeerIds);watch.forEach(function(v,k){if(_settings.watchingPeerIds.indexOf(v)==-1){_settings.watchingPeerIds.push(v)}});return doCommand("session","add",{sessionPeerIds:[].concat(data.watchingPeerIds),s:data.s,t:data.t,n:data.n})})};this.unwatch=function(peers){peers.forEach(function(v,k){if(_settings.watchingPeerIds.indexOf(v)>-1){_settings.watchingPeerIds.splice(_settings.watchingPeerIds.indexOf(v),1)}});return doCommand("session","remove",{sessionPeerIds:[].concat(peers)})};this.getStatus=function(peers){return doCommand("session","query",{sessionPeerIds:[].concat(peers)})};this.joinGroup=function(groupId){return _settings.groupAuth(_settings.peerId,groupId,"join",[]).then(function(data){return doCommand("room","join",{roomId:groupId,s:data.s,t:data.t,n:data.n})})};this.sendToGroup=function(msg,groupId,transient){var obj={msg:msg,roomId:groupId};if(typeof transient!="undefined"&&transient==true){obj.transient=transient}return doCommand("direct",undefined,obj)};this.inviteToGroup=function(groupId,groupPeerIds){return _settings.groupAuth(_settings.peerId,groupId,"invite",[].concat(groupPeerIds)).then(function(data){return doCommand("room","invite",{roomId:groupId,roomPeerIds:[].concat(data.groupPeerIds),s:data.s,t:data.t,n:data.n})})};this.kickFromGroup=function(groupId,groupPeerIds){return _settings.groupAuth(_settings.peerId,groupId,"kick",[].concat(groupPeerIds)).then(function(data){return doCommand("room","kick",{roomId:groupId,roomPeerIds:[].concat(groupPeerIds),s:data.s,t:data.t,n:data.n})})};this.leaveGroup=function(groupId){return doCommand("room","leave",{roomId:groupId})}}function get(url){if(typeof jQuery!=="undefined"){return Promise.resolve(jQuery.getJSON.call(jQuery,url+="&cb=?"))}else{return new Promise(function(resolve,reject){var req=new XMLHttpRequest;req.open("GET",url);req.onload=function(){if(req.status==200){resolve(JSON.parse(req.responseText))}else{reject(Error(req.statusText))}};req.onerror=function(){reject(Error("Network Error"))};req.send()})}}},{"es6-promise":2,events:12,ws:undefined,xmlhttprequest:undefined}],2:[function(require,module,exports){"use strict";var Promise=require("./promise/promise").Promise;var polyfill=require("./promise/polyfill").polyfill;exports.Promise=Promise;exports.polyfill=polyfill},{"./promise/polyfill":6,"./promise/promise":7}],3:[function(require,module,exports){"use strict";var isArray=require("./utils").isArray;var isFunction=require("./utils").isFunction;function all(promises){var Promise=this;if(!isArray(promises)){throw new TypeError("You must pass an array to all.")}return new Promise(function(resolve,reject){var results=[],remaining=promises.length,promise;if(remaining===0){resolve([])}function resolver(index){return function(value){resolveAll(index,value)}}function resolveAll(index,value){results[index]=value;if(--remaining===0){resolve(results)}}for(var i=0;i0&&this._events[type].length>m){this._events[type].warned=true;console.error("(node) warning: possible EventEmitter memory "+"leak detected. %d listeners added. "+"Use emitter.setMaxListeners() to increase limit.",this._events[type].length);if(typeof console.trace==="function"){console.trace()}}}return this};EventEmitter.prototype.on=EventEmitter.prototype.addListener;EventEmitter.prototype.once=function(type,listener){if(!isFunction(listener))throw TypeError("listener must be a function");var fired=false;function g(){this.removeListener(type,g);if(!fired){fired=true;listener.apply(this,arguments)}}g.listener=listener;this.on(type,g);return this};EventEmitter.prototype.removeListener=function(type,listener){var list,position,length,i;if(!isFunction(listener))throw TypeError("listener must be a function");if(!this._events||!this._events[type])return this;list=this._events[type];length=list.length;position=-1;if(list===listener||isFunction(list.listener)&&list.listener===listener){delete this._events[type];if(this._events.removeListener)this.emit("removeListener",type,listener)}else if(isObject(list)){for(i=length;i-->0;){if(list[i]===listener||list[i].listener&&list[i].listener===listener){position=i;break}}if(position<0)return this;if(list.length===1){list.length=0;delete this._events[type]}else{list.splice(position,1)}if(this._events.removeListener)this.emit("removeListener",type,listener)}return this};EventEmitter.prototype.removeAllListeners=function(type){var key,listeners;if(!this._events)return this;if(!this._events.removeListener){if(arguments.length===0)this._events={};else if(this._events[type])delete this._events[type];return this}if(arguments.length===0){for(key in this._events){if(key==="removeListener")continue;this.removeAllListeners(key)}this.removeAllListeners("removeListener");this._events={};return this}listeners=this._events[type];if(isFunction(listeners)){this.removeListener(type,listeners)}else{while(listeners.length)this.removeListener(type,listeners[listeners.length-1])}delete this._events[type];return this};EventEmitter.prototype.listeners=function(type){var ret;if(!this._events||!this._events[type])ret=[];else if(isFunction(this._events[type]))ret=[this._events[type]];else ret=this._events[type].slice();return ret};EventEmitter.listenerCount=function(emitter,type){var ret;if(!emitter._events||!emitter._events[type])ret=0;else if(isFunction(emitter._events[type]))ret=1;else ret=emitter._events[type].length;return ret};function isFunction(arg){return typeof arg==="function"}function isNumber(arg){return typeof arg==="number"}function isObject(arg){return typeof arg==="object"&&arg!==null}function isUndefined(arg){return arg===void 0}},{}],13:[function(require,module,exports){var process=module.exports={};process.nextTick=function(){var canSetImmediate=typeof window!=="undefined"&&window.setImmediate;var canMutationObserver=typeof window!=="undefined"&&window.MutationObserver;var canPost=typeof window!=="undefined"&&window.postMessage&&window.addEventListener;if(canSetImmediate){return function(f){return window.setImmediate(f)}}var queue=[];if(canMutationObserver){var hiddenDiv=document.createElement("div");var observer=new MutationObserver(function(){var queueList=queue.slice();queue.length=0;queueList.forEach(function(fn){fn()})});observer.observe(hiddenDiv,{attributes:true});return function nextTick(fn){if(!queue.length){hiddenDiv.setAttribute("yes","no")}queue.push(fn)}}if(canPost){window.addEventListener("message",function(ev){var source=ev.source;if((source===window||source===null)&&ev.data==="process-tick"){ev.stopPropagation();if(queue.length>0){var fn=queue.shift();fn()}}},true);return function nextTick(fn){queue.push(fn);window.postMessage("process-tick","*")}}return function nextTick(fn){setTimeout(fn,0)}}();process.title="browser";process.browser=true;process.env={};process.argv=[];function noop(){}process.on=noop;process.addListener=noop;process.once=noop;process.off=noop;process.removeListener=noop;process.removeAllListeners=noop;process.emit=noop;process.binding=function(name){throw new Error("process.binding is not supported")};process.cwd=function(){return"/"};process.chdir=function(dir){throw new Error("process.chdir is not supported")}},{}]},{},[1])(1)});
--------------------------------------------------------------------------------
/css/font-awesome.min.css:
--------------------------------------------------------------------------------
1 | @font-face{font-family:'FontAwesome';src:url('./font/fontawesome-webfont.eot?v=3.2.1');src:url('./font/fontawesome-webfont.eot?#iefix&v=3.2.1') format('embedded-opentype'),url('./font/fontawesome-webfont.woff?v=3.2.1') format('woff'),url('./font/fontawesome-webfont.ttf?v=3.2.1') format('truetype'),url('./font/fontawesome-webfont.svg#fontawesomeregular?v=3.2.1') format('svg');font-weight:normal;font-style:normal;}[class^="icon-"],[class*=" icon-"]{font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em;}
2 | [class^="icon-"]:before,[class*=" icon-"]:before{text-decoration:inherit;display:inline-block;speak:none;}
3 | .icon-large:before{vertical-align:-10%;font-size:1.3333333333333333em;}
4 | a [class^="icon-"],a [class*=" icon-"]{display:inline;}
5 | [class^="icon-"].icon-fixed-width,[class*=" icon-"].icon-fixed-width{display:inline-block;width:1.1428571428571428em;text-align:right;padding-right:0.2857142857142857em;}[class^="icon-"].icon-fixed-width.icon-large,[class*=" icon-"].icon-fixed-width.icon-large{width:1.4285714285714286em;}
6 | .icons-ul{margin-left:2.142857142857143em;list-style-type:none;}.icons-ul>li{position:relative;}
7 | .icons-ul .icon-li{position:absolute;left:-2.142857142857143em;width:2.142857142857143em;text-align:center;line-height:inherit;}
8 | [class^="icon-"].hide,[class*=" icon-"].hide{display:none;}
9 | .icon-muted{color:#eeeeee;}
10 | .icon-light{color:#ffffff;}
11 | .icon-dark{color:#333333;}
12 | .icon-border{border:solid 1px #eeeeee;padding:.2em .25em .15em;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
13 | .icon-2x{font-size:2em;}.icon-2x.icon-border{border-width:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
14 | .icon-3x{font-size:3em;}.icon-3x.icon-border{border-width:3px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;}
15 | .icon-4x{font-size:4em;}.icon-4x.icon-border{border-width:4px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;}
16 | .icon-5x{font-size:5em;}.icon-5x.icon-border{border-width:5px;-webkit-border-radius:7px;-moz-border-radius:7px;border-radius:7px;}
17 | .pull-right{float:right;}
18 | .pull-left{float:left;}
19 | [class^="icon-"].pull-left,[class*=" icon-"].pull-left{margin-right:.3em;}
20 | [class^="icon-"].pull-right,[class*=" icon-"].pull-right{margin-left:.3em;}
21 | [class^="icon-"],[class*=" icon-"]{display:inline;width:auto;height:auto;line-height:normal;vertical-align:baseline;background-image:none;background-position:0% 0%;background-repeat:repeat;margin-top:0;}
22 | .icon-white,.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"]{background-image:none;}
23 | .btn [class^="icon-"].icon-large,.nav [class^="icon-"].icon-large,.btn [class*=" icon-"].icon-large,.nav [class*=" icon-"].icon-large{line-height:.9em;}
24 | .btn [class^="icon-"].icon-spin,.nav [class^="icon-"].icon-spin,.btn [class*=" icon-"].icon-spin,.nav [class*=" icon-"].icon-spin{display:inline-block;}
25 | .nav-tabs [class^="icon-"],.nav-pills [class^="icon-"],.nav-tabs [class*=" icon-"],.nav-pills [class*=" icon-"],.nav-tabs [class^="icon-"].icon-large,.nav-pills [class^="icon-"].icon-large,.nav-tabs [class*=" icon-"].icon-large,.nav-pills [class*=" icon-"].icon-large{line-height:.9em;}
26 | .btn [class^="icon-"].pull-left.icon-2x,.btn [class*=" icon-"].pull-left.icon-2x,.btn [class^="icon-"].pull-right.icon-2x,.btn [class*=" icon-"].pull-right.icon-2x{margin-top:.18em;}
27 | .btn [class^="icon-"].icon-spin.icon-large,.btn [class*=" icon-"].icon-spin.icon-large{line-height:.8em;}
28 | .btn.btn-small [class^="icon-"].pull-left.icon-2x,.btn.btn-small [class*=" icon-"].pull-left.icon-2x,.btn.btn-small [class^="icon-"].pull-right.icon-2x,.btn.btn-small [class*=" icon-"].pull-right.icon-2x{margin-top:.25em;}
29 | .btn.btn-large [class^="icon-"],.btn.btn-large [class*=" icon-"]{margin-top:0;}.btn.btn-large [class^="icon-"].pull-left.icon-2x,.btn.btn-large [class*=" icon-"].pull-left.icon-2x,.btn.btn-large [class^="icon-"].pull-right.icon-2x,.btn.btn-large [class*=" icon-"].pull-right.icon-2x{margin-top:.05em;}
30 | .btn.btn-large [class^="icon-"].pull-left.icon-2x,.btn.btn-large [class*=" icon-"].pull-left.icon-2x{margin-right:.2em;}
31 | .btn.btn-large [class^="icon-"].pull-right.icon-2x,.btn.btn-large [class*=" icon-"].pull-right.icon-2x{margin-left:.2em;}
32 | .nav-list [class^="icon-"],.nav-list [class*=" icon-"]{line-height:inherit;}
33 | .icon-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:-35%;}.icon-stack [class^="icon-"],.icon-stack [class*=" icon-"]{display:block;text-align:center;position:absolute;width:100%;height:100%;font-size:1em;line-height:inherit;*line-height:2em;}
34 | .icon-stack .icon-stack-base{font-size:2em;*line-height:1em;}
35 | .icon-spin{display:inline-block;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;-webkit-animation:spin 2s infinite linear;animation:spin 2s infinite linear;}
36 | a .icon-stack,a .icon-spin{display:inline-block;text-decoration:none;}
37 | @-moz-keyframes spin{0%{-moz-transform:rotate(0deg);} 100%{-moz-transform:rotate(359deg);}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg);} 100%{-webkit-transform:rotate(359deg);}}@-o-keyframes spin{0%{-o-transform:rotate(0deg);} 100%{-o-transform:rotate(359deg);}}@-ms-keyframes spin{0%{-ms-transform:rotate(0deg);} 100%{-ms-transform:rotate(359deg);}}@keyframes spin{0%{transform:rotate(0deg);} 100%{transform:rotate(359deg);}}.icon-rotate-90:before{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg);filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);}
38 | .icon-rotate-180:before{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg);filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);}
39 | .icon-rotate-270:before{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg);filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);}
40 | .icon-flip-horizontal:before{-webkit-transform:scale(-1, 1);-moz-transform:scale(-1, 1);-ms-transform:scale(-1, 1);-o-transform:scale(-1, 1);transform:scale(-1, 1);}
41 | .icon-flip-vertical:before{-webkit-transform:scale(1, -1);-moz-transform:scale(1, -1);-ms-transform:scale(1, -1);-o-transform:scale(1, -1);transform:scale(1, -1);}
42 | a .icon-rotate-90:before,a .icon-rotate-180:before,a .icon-rotate-270:before,a .icon-flip-horizontal:before,a .icon-flip-vertical:before{display:inline-block;}
43 | .icon-glass:before{content:"\f000";}
44 | .icon-music:before{content:"\f001";}
45 | .icon-search:before{content:"\f002";}
46 | .icon-envelope-alt:before{content:"\f003";}
47 | .icon-heart:before{content:"\f004";}
48 | .icon-star:before{content:"\f005";}
49 | .icon-star-empty:before{content:"\f006";}
50 | .icon-user:before{content:"\f007";}
51 | .icon-film:before{content:"\f008";}
52 | .icon-th-large:before{content:"\f009";}
53 | .icon-th:before{content:"\f00a";}
54 | .icon-th-list:before{content:"\f00b";}
55 | .icon-ok:before{content:"\f00c";}
56 | .icon-remove:before{content:"\f00d";}
57 | .icon-zoom-in:before{content:"\f00e";}
58 | .icon-zoom-out:before{content:"\f010";}
59 | .icon-power-off:before,.icon-off:before{content:"\f011";}
60 | .icon-signal:before{content:"\f012";}
61 | .icon-gear:before,.icon-cog:before{content:"\f013";}
62 | .icon-trash:before{content:"\f014";}
63 | .icon-home:before{content:"\f015";}
64 | .icon-file-alt:before{content:"\f016";}
65 | .icon-time:before{content:"\f017";}
66 | .icon-road:before{content:"\f018";}
67 | .icon-download-alt:before{content:"\f019";}
68 | .icon-download:before{content:"\f01a";}
69 | .icon-upload:before{content:"\f01b";}
70 | .icon-inbox:before{content:"\f01c";}
71 | .icon-play-circle:before{content:"\f01d";}
72 | .icon-rotate-right:before,.icon-repeat:before{content:"\f01e";}
73 | .icon-refresh:before{content:"\f021";}
74 | .icon-list-alt:before{content:"\f022";}
75 | .icon-lock:before{content:"\f023";}
76 | .icon-flag:before{content:"\f024";}
77 | .icon-headphones:before{content:"\f025";}
78 | .icon-volume-off:before{content:"\f026";}
79 | .icon-volume-down:before{content:"\f027";}
80 | .icon-volume-up:before{content:"\f028";}
81 | .icon-qrcode:before{content:"\f029";}
82 | .icon-barcode:before{content:"\f02a";}
83 | .icon-tag:before{content:"\f02b";}
84 | .icon-tags:before{content:"\f02c";}
85 | .icon-book:before{content:"\f02d";}
86 | .icon-bookmark:before{content:"\f02e";}
87 | .icon-print:before{content:"\f02f";}
88 | .icon-camera:before{content:"\f030";}
89 | .icon-font:before{content:"\f031";}
90 | .icon-bold:before{content:"\f032";}
91 | .icon-italic:before{content:"\f033";}
92 | .icon-text-height:before{content:"\f034";}
93 | .icon-text-width:before{content:"\f035";}
94 | .icon-align-left:before{content:"\f036";}
95 | .icon-align-center:before{content:"\f037";}
96 | .icon-align-right:before{content:"\f038";}
97 | .icon-align-justify:before{content:"\f039";}
98 | .icon-list:before{content:"\f03a";}
99 | .icon-indent-left:before{content:"\f03b";}
100 | .icon-indent-right:before{content:"\f03c";}
101 | .icon-facetime-video:before{content:"\f03d";}
102 | .icon-picture:before{content:"\f03e";}
103 | .icon-pencil:before{content:"\f040";}
104 | .icon-map-marker:before{content:"\f041";}
105 | .icon-adjust:before{content:"\f042";}
106 | .icon-tint:before{content:"\f043";}
107 | .icon-edit:before{content:"\f044";}
108 | .icon-share:before{content:"\f045";}
109 | .icon-check:before{content:"\f046";}
110 | .icon-move:before{content:"\f047";}
111 | .icon-step-backward:before{content:"\f048";}
112 | .icon-fast-backward:before{content:"\f049";}
113 | .icon-backward:before{content:"\f04a";}
114 | .icon-play:before{content:"\f04b";}
115 | .icon-pause:before{content:"\f04c";}
116 | .icon-stop:before{content:"\f04d";}
117 | .icon-forward:before{content:"\f04e";}
118 | .icon-fast-forward:before{content:"\f050";}
119 | .icon-step-forward:before{content:"\f051";}
120 | .icon-eject:before{content:"\f052";}
121 | .icon-chevron-left:before{content:"\f053";}
122 | .icon-chevron-right:before{content:"\f054";}
123 | .icon-plus-sign:before{content:"\f055";}
124 | .icon-minus-sign:before{content:"\f056";}
125 | .icon-remove-sign:before{content:"\f057";}
126 | .icon-ok-sign:before{content:"\f058";}
127 | .icon-question-sign:before{content:"\f059";}
128 | .icon-info-sign:before{content:"\f05a";}
129 | .icon-screenshot:before{content:"\f05b";}
130 | .icon-remove-circle:before{content:"\f05c";}
131 | .icon-ok-circle:before{content:"\f05d";}
132 | .icon-ban-circle:before{content:"\f05e";}
133 | .icon-arrow-left:before{content:"\f060";}
134 | .icon-arrow-right:before{content:"\f061";}
135 | .icon-arrow-up:before{content:"\f062";}
136 | .icon-arrow-down:before{content:"\f063";}
137 | .icon-mail-forward:before,.icon-share-alt:before{content:"\f064";}
138 | .icon-resize-full:before{content:"\f065";}
139 | .icon-resize-small:before{content:"\f066";}
140 | .icon-plus:before{content:"\f067";}
141 | .icon-minus:before{content:"\f068";}
142 | .icon-asterisk:before{content:"\f069";}
143 | .icon-exclamation-sign:before{content:"\f06a";}
144 | .icon-gift:before{content:"\f06b";}
145 | .icon-leaf:before{content:"\f06c";}
146 | .icon-fire:before{content:"\f06d";}
147 | .icon-eye-open:before{content:"\f06e";}
148 | .icon-eye-close:before{content:"\f070";}
149 | .icon-warning-sign:before{content:"\f071";}
150 | .icon-plane:before{content:"\f072";}
151 | .icon-calendar:before{content:"\f073";}
152 | .icon-random:before{content:"\f074";}
153 | .icon-comment:before{content:"\f075";}
154 | .icon-magnet:before{content:"\f076";}
155 | .icon-chevron-up:before{content:"\f077";}
156 | .icon-chevron-down:before{content:"\f078";}
157 | .icon-retweet:before{content:"\f079";}
158 | .icon-shopping-cart:before{content:"\f07a";}
159 | .icon-folder-close:before{content:"\f07b";}
160 | .icon-folder-open:before{content:"\f07c";}
161 | .icon-resize-vertical:before{content:"\f07d";}
162 | .icon-resize-horizontal:before{content:"\f07e";}
163 | .icon-bar-chart:before{content:"\f080";}
164 | .icon-twitter-sign:before{content:"\f081";}
165 | .icon-facebook-sign:before{content:"\f082";}
166 | .icon-camera-retro:before{content:"\f083";}
167 | .icon-key:before{content:"\f084";}
168 | .icon-gears:before,.icon-cogs:before{content:"\f085";}
169 | .icon-comments:before{content:"\f086";}
170 | .icon-thumbs-up-alt:before{content:"\f087";}
171 | .icon-thumbs-down-alt:before{content:"\f088";}
172 | .icon-star-half:before{content:"\f089";}
173 | .icon-heart-empty:before{content:"\f08a";}
174 | .icon-signout:before{content:"\f08b";}
175 | .icon-linkedin-sign:before{content:"\f08c";}
176 | .icon-pushpin:before{content:"\f08d";}
177 | .icon-external-link:before{content:"\f08e";}
178 | .icon-signin:before{content:"\f090";}
179 | .icon-trophy:before{content:"\f091";}
180 | .icon-github-sign:before{content:"\f092";}
181 | .icon-upload-alt:before{content:"\f093";}
182 | .icon-lemon:before{content:"\f094";}
183 | .icon-phone:before{content:"\f095";}
184 | .icon-unchecked:before,.icon-check-empty:before{content:"\f096";}
185 | .icon-bookmark-empty:before{content:"\f097";}
186 | .icon-phone-sign:before{content:"\f098";}
187 | .icon-twitter:before{content:"\f099";}
188 | .icon-facebook:before{content:"\f09a";}
189 | .icon-github:before{content:"\f09b";}
190 | .icon-unlock:before{content:"\f09c";}
191 | .icon-credit-card:before{content:"\f09d";}
192 | .icon-rss:before{content:"\f09e";}
193 | .icon-hdd:before{content:"\f0a0";}
194 | .icon-bullhorn:before{content:"\f0a1";}
195 | .icon-bell:before{content:"\f0a2";}
196 | .icon-certificate:before{content:"\f0a3";}
197 | .icon-hand-right:before{content:"\f0a4";}
198 | .icon-hand-left:before{content:"\f0a5";}
199 | .icon-hand-up:before{content:"\f0a6";}
200 | .icon-hand-down:before{content:"\f0a7";}
201 | .icon-circle-arrow-left:before{content:"\f0a8";}
202 | .icon-circle-arrow-right:before{content:"\f0a9";}
203 | .icon-circle-arrow-up:before{content:"\f0aa";}
204 | .icon-circle-arrow-down:before{content:"\f0ab";}
205 | .icon-globe:before{content:"\f0ac";}
206 | .icon-wrench:before{content:"\f0ad";}
207 | .icon-tasks:before{content:"\f0ae";}
208 | .icon-filter:before{content:"\f0b0";}
209 | .icon-briefcase:before{content:"\f0b1";}
210 | .icon-fullscreen:before{content:"\f0b2";}
211 | .icon-group:before{content:"\f0c0";}
212 | .icon-link:before{content:"\f0c1";}
213 | .icon-cloud:before{content:"\f0c2";}
214 | .icon-beaker:before{content:"\f0c3";}
215 | .icon-cut:before{content:"\f0c4";}
216 | .icon-copy:before{content:"\f0c5";}
217 | .icon-paperclip:before,.icon-paper-clip:before{content:"\f0c6";}
218 | .icon-save:before{content:"\f0c7";}
219 | .icon-sign-blank:before{content:"\f0c8";}
220 | .icon-reorder:before{content:"\f0c9";}
221 | .icon-list-ul:before{content:"\f0ca";}
222 | .icon-list-ol:before{content:"\f0cb";}
223 | .icon-strikethrough:before{content:"\f0cc";}
224 | .icon-underline:before{content:"\f0cd";}
225 | .icon-table:before{content:"\f0ce";}
226 | .icon-magic:before{content:"\f0d0";}
227 | .icon-truck:before{content:"\f0d1";}
228 | .icon-pinterest:before{content:"\f0d2";}
229 | .icon-pinterest-sign:before{content:"\f0d3";}
230 | .icon-google-plus-sign:before{content:"\f0d4";}
231 | .icon-google-plus:before{content:"\f0d5";}
232 | .icon-money:before{content:"\f0d6";}
233 | .icon-caret-down:before{content:"\f0d7";}
234 | .icon-caret-up:before{content:"\f0d8";}
235 | .icon-caret-left:before{content:"\f0d9";}
236 | .icon-caret-right:before{content:"\f0da";}
237 | .icon-columns:before{content:"\f0db";}
238 | .icon-sort:before{content:"\f0dc";}
239 | .icon-sort-down:before{content:"\f0dd";}
240 | .icon-sort-up:before{content:"\f0de";}
241 | .icon-envelope:before{content:"\f0e0";}
242 | .icon-linkedin:before{content:"\f0e1";}
243 | .icon-rotate-left:before,.icon-undo:before{content:"\f0e2";}
244 | .icon-legal:before{content:"\f0e3";}
245 | .icon-dashboard:before{content:"\f0e4";}
246 | .icon-comment-alt:before{content:"\f0e5";}
247 | .icon-comments-alt:before{content:"\f0e6";}
248 | .icon-bolt:before{content:"\f0e7";}
249 | .icon-sitemap:before{content:"\f0e8";}
250 | .icon-umbrella:before{content:"\f0e9";}
251 | .icon-paste:before{content:"\f0ea";}
252 | .icon-lightbulb:before{content:"\f0eb";}
253 | .icon-exchange:before{content:"\f0ec";}
254 | .icon-cloud-download:before{content:"\f0ed";}
255 | .icon-cloud-upload:before{content:"\f0ee";}
256 | .icon-user-md:before{content:"\f0f0";}
257 | .icon-stethoscope:before{content:"\f0f1";}
258 | .icon-suitcase:before{content:"\f0f2";}
259 | .icon-bell-alt:before{content:"\f0f3";}
260 | .icon-coffee:before{content:"\f0f4";}
261 | .icon-food:before{content:"\f0f5";}
262 | .icon-file-text-alt:before{content:"\f0f6";}
263 | .icon-building:before{content:"\f0f7";}
264 | .icon-hospital:before{content:"\f0f8";}
265 | .icon-ambulance:before{content:"\f0f9";}
266 | .icon-medkit:before{content:"\f0fa";}
267 | .icon-fighter-jet:before{content:"\f0fb";}
268 | .icon-beer:before{content:"\f0fc";}
269 | .icon-h-sign:before{content:"\f0fd";}
270 | .icon-plus-sign-alt:before{content:"\f0fe";}
271 | .icon-double-angle-left:before{content:"\f100";}
272 | .icon-double-angle-right:before{content:"\f101";}
273 | .icon-double-angle-up:before{content:"\f102";}
274 | .icon-double-angle-down:before{content:"\f103";}
275 | .icon-angle-left:before{content:"\f104";}
276 | .icon-angle-right:before{content:"\f105";}
277 | .icon-angle-up:before{content:"\f106";}
278 | .icon-angle-down:before{content:"\f107";}
279 | .icon-desktop:before{content:"\f108";}
280 | .icon-laptop:before{content:"\f109";}
281 | .icon-tablet:before{content:"\f10a";}
282 | .icon-mobile-phone:before{content:"\f10b";}
283 | .icon-circle-blank:before{content:"\f10c";}
284 | .icon-quote-left:before{content:"\f10d";}
285 | .icon-quote-right:before{content:"\f10e";}
286 | .icon-spinner:before{content:"\f110";}
287 | .icon-circle:before{content:"\f111";}
288 | .icon-mail-reply:before,.icon-reply:before{content:"\f112";}
289 | .icon-github-alt:before{content:"\f113";}
290 | .icon-folder-close-alt:before{content:"\f114";}
291 | .icon-folder-open-alt:before{content:"\f115";}
292 | .icon-expand-alt:before{content:"\f116";}
293 | .icon-collapse-alt:before{content:"\f117";}
294 | .icon-smile:before{content:"\f118";}
295 | .icon-frown:before{content:"\f119";}
296 | .icon-meh:before{content:"\f11a";}
297 | .icon-gamepad:before{content:"\f11b";}
298 | .icon-keyboard:before{content:"\f11c";}
299 | .icon-flag-alt:before{content:"\f11d";}
300 | .icon-flag-checkered:before{content:"\f11e";}
301 | .icon-terminal:before{content:"\f120";}
302 | .icon-code:before{content:"\f121";}
303 | .icon-reply-all:before{content:"\f122";}
304 | .icon-mail-reply-all:before{content:"\f122";}
305 | .icon-star-half-full:before,.icon-star-half-empty:before{content:"\f123";}
306 | .icon-location-arrow:before{content:"\f124";}
307 | .icon-crop:before{content:"\f125";}
308 | .icon-code-fork:before{content:"\f126";}
309 | .icon-unlink:before{content:"\f127";}
310 | .icon-question:before{content:"\f128";}
311 | .icon-info:before{content:"\f129";}
312 | .icon-exclamation:before{content:"\f12a";}
313 | .icon-superscript:before{content:"\f12b";}
314 | .icon-subscript:before{content:"\f12c";}
315 | .icon-eraser:before{content:"\f12d";}
316 | .icon-puzzle-piece:before{content:"\f12e";}
317 | .icon-microphone:before{content:"\f130";}
318 | .icon-microphone-off:before{content:"\f131";}
319 | .icon-shield:before{content:"\f132";}
320 | .icon-calendar-empty:before{content:"\f133";}
321 | .icon-fire-extinguisher:before{content:"\f134";}
322 | .icon-rocket:before{content:"\f135";}
323 | .icon-maxcdn:before{content:"\f136";}
324 | .icon-chevron-sign-left:before{content:"\f137";}
325 | .icon-chevron-sign-right:before{content:"\f138";}
326 | .icon-chevron-sign-up:before{content:"\f139";}
327 | .icon-chevron-sign-down:before{content:"\f13a";}
328 | .icon-html5:before{content:"\f13b";}
329 | .icon-css3:before{content:"\f13c";}
330 | .icon-anchor:before{content:"\f13d";}
331 | .icon-unlock-alt:before{content:"\f13e";}
332 | .icon-bullseye:before{content:"\f140";}
333 | .icon-ellipsis-horizontal:before{content:"\f141";}
334 | .icon-ellipsis-vertical:before{content:"\f142";}
335 | .icon-rss-sign:before{content:"\f143";}
336 | .icon-play-sign:before{content:"\f144";}
337 | .icon-ticket:before{content:"\f145";}
338 | .icon-minus-sign-alt:before{content:"\f146";}
339 | .icon-check-minus:before{content:"\f147";}
340 | .icon-level-up:before{content:"\f148";}
341 | .icon-level-down:before{content:"\f149";}
342 | .icon-check-sign:before{content:"\f14a";}
343 | .icon-edit-sign:before{content:"\f14b";}
344 | .icon-external-link-sign:before{content:"\f14c";}
345 | .icon-share-sign:before{content:"\f14d";}
346 | .icon-compass:before{content:"\f14e";}
347 | .icon-collapse:before{content:"\f150";}
348 | .icon-collapse-top:before{content:"\f151";}
349 | .icon-expand:before{content:"\f152";}
350 | .icon-euro:before,.icon-eur:before{content:"\f153";}
351 | .icon-gbp:before{content:"\f154";}
352 | .icon-dollar:before,.icon-usd:before{content:"\f155";}
353 | .icon-rupee:before,.icon-inr:before{content:"\f156";}
354 | .icon-yen:before,.icon-jpy:before{content:"\f157";}
355 | .icon-renminbi:before,.icon-cny:before{content:"\f158";}
356 | .icon-won:before,.icon-krw:before{content:"\f159";}
357 | .icon-bitcoin:before,.icon-btc:before{content:"\f15a";}
358 | .icon-file:before{content:"\f15b";}
359 | .icon-file-text:before{content:"\f15c";}
360 | .icon-sort-by-alphabet:before{content:"\f15d";}
361 | .icon-sort-by-alphabet-alt:before{content:"\f15e";}
362 | .icon-sort-by-attributes:before{content:"\f160";}
363 | .icon-sort-by-attributes-alt:before{content:"\f161";}
364 | .icon-sort-by-order:before{content:"\f162";}
365 | .icon-sort-by-order-alt:before{content:"\f163";}
366 | .icon-thumbs-up:before{content:"\f164";}
367 | .icon-thumbs-down:before{content:"\f165";}
368 | .icon-youtube-sign:before{content:"\f166";}
369 | .icon-youtube:before{content:"\f167";}
370 | .icon-xing:before{content:"\f168";}
371 | .icon-xing-sign:before{content:"\f169";}
372 | .icon-youtube-play:before{content:"\f16a";}
373 | .icon-dropbox:before{content:"\f16b";}
374 | .icon-stackexchange:before{content:"\f16c";}
375 | .icon-instagram:before{content:"\f16d";}
376 | .icon-flickr:before{content:"\f16e";}
377 | .icon-adn:before{content:"\f170";}
378 | .icon-bitbucket:before{content:"\f171";}
379 | .icon-bitbucket-sign:before{content:"\f172";}
380 | .icon-tumblr:before{content:"\f173";}
381 | .icon-tumblr-sign:before{content:"\f174";}
382 | .icon-long-arrow-down:before{content:"\f175";}
383 | .icon-long-arrow-up:before{content:"\f176";}
384 | .icon-long-arrow-left:before{content:"\f177";}
385 | .icon-long-arrow-right:before{content:"\f178";}
386 | .icon-apple:before{content:"\f179";}
387 | .icon-windows:before{content:"\f17a";}
388 | .icon-android:before{content:"\f17b";}
389 | .icon-linux:before{content:"\f17c";}
390 | .icon-dribbble:before{content:"\f17d";}
391 | .icon-skype:before{content:"\f17e";}
392 | .icon-foursquare:before{content:"\f180";}
393 | .icon-trello:before{content:"\f181";}
394 | .icon-female:before{content:"\f182";}
395 | .icon-male:before{content:"\f183";}
396 | .icon-gittip:before{content:"\f184";}
397 | .icon-sun:before{content:"\f185";}
398 | .icon-moon:before{content:"\f186";}
399 | .icon-archive:before{content:"\f187";}
400 | .icon-bug:before{content:"\f188";}
401 | .icon-vk:before{content:"\f189";}
402 | .icon-weibo:before{content:"\f18a";}
403 | .icon-renren:before{content:"\f18b";}
404 |
--------------------------------------------------------------------------------
/script/av-chat.js:
--------------------------------------------------------------------------------
1 | !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.AVChatClient=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 60000){
57 | // keepAliveTimeout = 60000;
58 | // }
59 | // watchingPeer = [].concat(settings.watchingPeer);
60 | }
61 |
62 | initialize(settings);
63 |
64 | function _getServerInfo(appId, secure) {
65 | var protocol = "http://";
66 | if(typeof window !='undefined' && window.location&&window.location.protocol == 'https:'){
67 | protocol = "https://";
68 | }
69 | var url = protocol+'router-g0-push.avoscloud.com/v1/route?appId=' + appId ;
70 | if(_settings.server && _settings.server == 'us'){
71 | url =protocol+'router-a0-push.avoscloud.com/v1/route?appId=' + appId ;
72 | }
73 | if(secure){
74 | url+='&secure=1';
75 | }
76 | return get(url);
77 | }
78 |
79 | function _connect() {
80 | if (server && new Date() < server.expires) {
81 | return new Promise(function(resolve, reject) {
82 | ws = new WebSocket(server.server);
83 | _timeout('connectopen',function(){ reject();});
84 | ws.onopen = function() {
85 | if(timers.length > 0){
86 | clearTimeout(timers.shift()[1]);
87 | }
88 | resolve(server);
89 | };
90 | ws.onclose = function(e) {
91 | doClose();
92 | _emitter.emit('close', e);
93 | }
94 | ws.onmessage = function(message) {
95 | var data = JSON.parse(message.data);
96 |
97 | var cmd = data.op ? data.cmd + data.op : data.cmd;
98 | if(!cmd){
99 | cmd = '{}';
100 | }
101 | if (_waitCommands.length > 0 && _waitCommands[0][0] === cmd) {
102 | _waitCommands.shift()[1](data);
103 | }
104 | if(timers.length>0 && timers[0][0] == cmd){
105 | clearTimeout(timers.shift()[1]);
106 | }
107 |
108 | if (data.cmd == 'session') {
109 | if (data.op == 'opened'||data.op == 'added') {
110 | _emitter.emit('online', data.onlineSessionPeerIds);
111 | }
112 | } else if (data.cmd == 'presence') {
113 | if (data.status == 'on') {
114 | _emitter.emit('online', data.sessionPeerIds);
115 | } else if (data.status == 'off') {
116 | _emitter.emit('offline', data.sessionPeerIds);
117 | }
118 | } else if (data.cmd == 'direct') {
119 | _emitter.emit('message', data);
120 | var msg = {
121 | "cmd": "ack",
122 | "peerId": _settings.peerId,
123 | "appId": _settings.appId,
124 | 'ids': [].concat(data.id)
125 | }
126 | var s = JSON.stringify(msg)
127 | ws.send(s);
128 | } else if(data.cmd == 'room'){
129 | if(data.op == 'members-joined'){
130 | _emitter.emit('membersJoined', data);
131 | }else if(data.op == 'members-left'){
132 | _emitter.emit('membersLeft', data);
133 | }else if(data.op == 'joined'){
134 | _emitter.emit('joined',data)
135 | }else if(data.op == 'left'){
136 | _emitter.emit('left',data);
137 | }
138 | }
139 | };
140 | });
141 | } else {
142 | return _getServerInfo(_settings.appId,_settings.secure).then(function(result) {
143 | server = result;
144 | server.expires = Date.now() + server.ttl * 1000;
145 | return _connect();
146 | });
147 | }
148 | }
149 |
150 | function _openSession() {
151 |
152 | return _settings.auth(_settings.peerId,_settings.watchingPeerIds,_settings.sp).then(function(data){
153 | // console.log(data);
154 | _settings.watchingPeerIds = data.watchingPeerIds;
155 | return doCommand('session','open',{
156 | sessionPeerIds: data.watchingPeerIds,
157 | s: data.s,
158 | t: data.t,
159 | n: data.n,
160 | sp: data.sp
161 |
162 | });
163 | })
164 |
165 | }
166 |
167 |
168 | function _timeout(name,reject){
169 | timers.push([name,setTimeout(function(){
170 | if(reject){
171 | reject(name+'timeout');
172 | }
173 | doClose();
174 | // _emitter.emit('close');
175 | // if(name == '{}'){
176 | // doClose();
177 | // _emitter.emit('close');
178 | // }
179 | },10000)]);
180 | }
181 |
182 | function _keepAlive(){
183 | clearTimeout(_keepAlive.handle);
184 | _keepAlive.handle = setTimeout(function(){
185 | if(ws.readyState == 1){
186 | ws.send('{}');
187 | _timeout('{}');
188 | _keepAlive();
189 | }
190 | },keepAliveTimeout);
191 | }
192 |
193 | function doClose(){
194 | ws.close();
195 | clearTimeout(_keepAlive.handle);
196 | timers.forEach(function(v,i){
197 | clearTimeout(v[1]);
198 | });
199 | _waitCommands.forEach(function(v){
200 | v[2]();
201 | });
202 | timers = [];
203 | _waitCommands = [];
204 |
205 | }
206 |
207 | function doCommand(cmd, op, props){
208 | //send
209 | _keepAlive();
210 | var msg = {
211 | "cmd": cmd,
212 | "peerId": _settings.peerId,
213 | "appId": _settings.appId
214 | }
215 | if(op){
216 | msg.op = op;
217 | }
218 | if(props){
219 | for(k in props){
220 | msg[k] = props[k];
221 | }
222 | }
223 | if(!ws){
224 | return Promise.reject();
225 | }
226 | if(ws.readyState != 1){
227 | return Promise.reject(ws.readyState);
228 | }
229 | ws.send(JSON.stringify(msg));
230 | //wait
231 | var c = typeof op == 'undefined'?cmd : cmd+op;
232 | if((cmd == 'direct' && props.transient == true) || ['sessionremove','sessionclose'].indexOf(c) > -1 ){
233 | return Promise.resolve();
234 | }else{
235 | return new Promise(function(resolve, reject) {
236 |
237 | _waitCommands.push([cmdMap[c]||c, resolve, reject]);
238 | _timeout(cmdMap[c]||c ,reject);
239 | });
240 | }
241 | }
242 |
243 | this.open = function() {
244 | // console.log(ws.readyState)
245 | if(ws && ws.readyState == 0 ){
246 | return Promise.reject(0);
247 | }
248 | if(ws && ws.readyState == 1) {
249 | return Promise.resolve();
250 | }
251 | timers.forEach(function(v,i){
252 | clearTimeout(v[1]);
253 | });
254 | timers = [];
255 | return _connect().then(function() {
256 | return _openSession();
257 | });
258 | };
259 | this.close = function() {
260 | doCommand('session', 'close')
261 | doClose();
262 | return Promise.resolve();
263 | // return then;
264 | }
265 | this.send = function(msg, to, transient) {
266 | var obj = {
267 | 'msg': msg,
268 | 'toPeerIds': [].concat(to)
269 | }
270 | if(typeof transient != 'undefined' && transient == true){
271 | obj.transient = transient;
272 | }
273 | return doCommand('direct',undefined,obj);
274 | };
275 |
276 | this.on = function(name, func) {
277 | _emitter.on(name, func)
278 | };
279 | this.watch = function(peers) {
280 | return _settings.auth(_settings.peerId,[].concat(peers)).then(function(data){
281 | var watch = [].concat(data.watchingPeerIds);
282 | watch.forEach(function(v,k){
283 | if(_settings.watchingPeerIds.indexOf(v)==-1){
284 | _settings.watchingPeerIds.push(v);
285 | }
286 | });
287 | return doCommand('session', 'add', {
288 | 'sessionPeerIds': [].concat(data.watchingPeerIds),
289 | s: data.s,
290 | t: data.t,
291 | n: data.n
292 | });
293 | })
294 | }
295 | this.unwatch = function(peers) {
296 | peers.forEach(function(v,k){
297 | if(_settings.watchingPeerIds.indexOf(v)>-1){
298 | _settings.watchingPeerIds.splice(_settings.watchingPeerIds.indexOf(v),1);
299 | }
300 | });
301 | return doCommand('session', 'remove', {
302 | "sessionPeerIds": [].concat(peers)
303 | });
304 | }
305 | this.getStatus = function(peers) {
306 | return doCommand('session', 'query' ,{
307 | 'sessionPeerIds': [].concat(peers)
308 | });
309 | }
310 | this.joinGroup = function(groupId) {
311 | return _settings.groupAuth(_settings.peerId,groupId,'join',[]).then(function(data){
312 | return doCommand('room', 'join', {
313 | roomId: groupId,
314 | s: data.s,
315 | t: data.t,
316 | n: data.n
317 | });
318 | });
319 | }
320 | this.sendToGroup = function(msg, groupId, transient){
321 | var obj = {
322 | 'msg': msg,
323 | 'roomId': groupId
324 | }
325 | if(typeof transient != 'undefined' && transient == true){
326 | obj.transient = transient;
327 | }
328 | return doCommand('direct',undefined,obj);
329 | }
330 | this.inviteToGroup= function(groupId, groupPeerIds){
331 | return _settings.groupAuth(_settings.peerId,groupId,'invite',[].concat(groupPeerIds)).then(function(data){
332 | return doCommand('room', 'invite', {
333 | roomId: groupId,
334 | roomPeerIds: [].concat(data.groupPeerIds),
335 | s: data.s,
336 | t: data.t,
337 | n: data.n
338 | });
339 | });
340 | }
341 | this.kickFromGroup= function(groupId, groupPeerIds) {
342 | return _settings.groupAuth(_settings.peerId,groupId,'kick',[].concat(groupPeerIds)).then(function(data){
343 | return doCommand('room', 'kick', {
344 | roomId: groupId,
345 | roomPeerIds: [].concat(groupPeerIds),
346 | s: data.s,
347 | t: data.t,
348 | n: data.n
349 | });
350 | });
351 | }
352 | this.leaveGroup = function(groupId) {
353 | return doCommand('room', 'leave', {
354 | roomId: groupId
355 | });
356 | }
357 |
358 |
359 | };
360 |
361 |
362 | function get(url) {
363 | if (typeof jQuery !== 'undefined') {
364 | return Promise.resolve(jQuery.getJSON.call(jQuery, url+='&cb=?'));
365 | }else{
366 | // Return a new promise.
367 | return new Promise(function(resolve, reject) {
368 | // Do the usual XHR stuff
369 | var req = new XMLHttpRequest();
370 | req.open('GET', url);
371 | // req.withCredentials = false;
372 | req.onload = function() {
373 | // This is called even on 404 etc
374 | // so check the status
375 | if (req.status == 200) {
376 | // Resolve the promise with the response text
377 | resolve(JSON.parse(req.responseText));
378 | } else {
379 | // Otherwise reject with the status text
380 | // which will hopefully be a meaningful error
381 | reject(Error(req.statusText));
382 | }
383 | };
384 | // Handle network errors
385 | req.onerror = function() {
386 | reject(Error("Network Error"));
387 | };
388 |
389 | // Make the request
390 | req.send();
391 | });
392 | }
393 |
394 | }
395 |
396 | },{"es6-promise":2,"events":12,"ws":undefined,"xmlhttprequest":undefined}],2:[function(require,module,exports){
397 | "use strict";
398 | var Promise = require("./promise/promise").Promise;
399 | var polyfill = require("./promise/polyfill").polyfill;
400 | exports.Promise = Promise;
401 | exports.polyfill = polyfill;
402 | },{"./promise/polyfill":6,"./promise/promise":7}],3:[function(require,module,exports){
403 | "use strict";
404 | /* global toString */
405 |
406 | var isArray = require("./utils").isArray;
407 | var isFunction = require("./utils").isFunction;
408 |
409 | /**
410 | Returns a promise that is fulfilled when all the given promises have been
411 | fulfilled, or rejected if any of them become rejected. The return promise
412 | is fulfilled with an array that gives all the values in the order they were
413 | passed in the `promises` array argument.
414 |
415 | Example:
416 |
417 | ```javascript
418 | var promise1 = RSVP.resolve(1);
419 | var promise2 = RSVP.resolve(2);
420 | var promise3 = RSVP.resolve(3);
421 | var promises = [ promise1, promise2, promise3 ];
422 |
423 | RSVP.all(promises).then(function(array){
424 | // The array here would be [ 1, 2, 3 ];
425 | });
426 | ```
427 |
428 | If any of the `promises` given to `RSVP.all` are rejected, the first promise
429 | that is rejected will be given as an argument to the returned promises's
430 | rejection handler. For example:
431 |
432 | Example:
433 |
434 | ```javascript
435 | var promise1 = RSVP.resolve(1);
436 | var promise2 = RSVP.reject(new Error("2"));
437 | var promise3 = RSVP.reject(new Error("3"));
438 | var promises = [ promise1, promise2, promise3 ];
439 |
440 | RSVP.all(promises).then(function(array){
441 | // Code here never runs because there are rejected promises!
442 | }, function(error) {
443 | // error.message === "2"
444 | });
445 | ```
446 |
447 | @method all
448 | @for RSVP
449 | @param {Array} promises
450 | @param {String} label
451 | @return {Promise} promise that is fulfilled when all `promises` have been
452 | fulfilled, or rejected if any of them become rejected.
453 | */
454 | function all(promises) {
455 | /*jshint validthis:true */
456 | var Promise = this;
457 |
458 | if (!isArray(promises)) {
459 | throw new TypeError('You must pass an array to all.');
460 | }
461 |
462 | return new Promise(function(resolve, reject) {
463 | var results = [], remaining = promises.length,
464 | promise;
465 |
466 | if (remaining === 0) {
467 | resolve([]);
468 | }
469 |
470 | function resolver(index) {
471 | return function(value) {
472 | resolveAll(index, value);
473 | };
474 | }
475 |
476 | function resolveAll(index, value) {
477 | results[index] = value;
478 | if (--remaining === 0) {
479 | resolve(results);
480 | }
481 | }
482 |
483 | for (var i = 0; i < promises.length; i++) {
484 | promise = promises[i];
485 |
486 | if (promise && isFunction(promise.then)) {
487 | promise.then(resolver(i), reject);
488 | } else {
489 | resolveAll(i, promise);
490 | }
491 | }
492 | });
493 | }
494 |
495 | exports.all = all;
496 | },{"./utils":11}],4:[function(require,module,exports){
497 | (function (process,global){
498 | "use strict";
499 | var browserGlobal = (typeof window !== 'undefined') ? window : {};
500 | var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
501 | var local = (typeof global !== 'undefined') ? global : (this === undefined? window:this);
502 |
503 | // node
504 | function useNextTick() {
505 | return function() {
506 | process.nextTick(flush);
507 | };
508 | }
509 |
510 | function useMutationObserver() {
511 | var iterations = 0;
512 | var observer = new BrowserMutationObserver(flush);
513 | var node = document.createTextNode('');
514 | observer.observe(node, { characterData: true });
515 |
516 | return function() {
517 | node.data = (iterations = ++iterations % 2);
518 | };
519 | }
520 |
521 | function useSetTimeout() {
522 | return function() {
523 | local.setTimeout(flush, 1);
524 | };
525 | }
526 |
527 | var queue = [];
528 | function flush() {
529 | for (var i = 0; i < queue.length; i++) {
530 | var tuple = queue[i];
531 | var callback = tuple[0], arg = tuple[1];
532 | callback(arg);
533 | }
534 | queue = [];
535 | }
536 |
537 | var scheduleFlush;
538 |
539 | // Decide what async method to use to triggering processing of queued callbacks:
540 | if (typeof process !== 'undefined' && {}.toString.call(process) === '[object process]') {
541 | scheduleFlush = useNextTick();
542 | } else if (BrowserMutationObserver) {
543 | scheduleFlush = useMutationObserver();
544 | } else {
545 | scheduleFlush = useSetTimeout();
546 | }
547 |
548 | function asap(callback, arg) {
549 | var length = queue.push([callback, arg]);
550 | if (length === 1) {
551 | // If length is 1, that means that we need to schedule an async flush.
552 | // If additional callbacks are queued before the queue is flushed, they
553 | // will be processed by this flush that we are scheduling.
554 | scheduleFlush();
555 | }
556 | }
557 |
558 | exports.asap = asap;
559 | }).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
560 | },{"_process":13}],5:[function(require,module,exports){
561 | "use strict";
562 | var config = {
563 | instrument: false
564 | };
565 |
566 | function configure(name, value) {
567 | if (arguments.length === 2) {
568 | config[name] = value;
569 | } else {
570 | return config[name];
571 | }
572 | }
573 |
574 | exports.config = config;
575 | exports.configure = configure;
576 | },{}],6:[function(require,module,exports){
577 | (function (global){
578 | "use strict";
579 | /*global self*/
580 | var RSVPPromise = require("./promise").Promise;
581 | var isFunction = require("./utils").isFunction;
582 |
583 | function polyfill() {
584 | var local;
585 |
586 | if (typeof global !== 'undefined') {
587 | local = global;
588 | } else if (typeof window !== 'undefined' && window.document) {
589 | local = window;
590 | } else {
591 | local = self;
592 | }
593 |
594 | var es6PromiseSupport =
595 | "Promise" in local &&
596 | // Some of these methods are missing from
597 | // Firefox/Chrome experimental implementations
598 | "resolve" in local.Promise &&
599 | "reject" in local.Promise &&
600 | "all" in local.Promise &&
601 | "race" in local.Promise &&
602 | // Older version of the spec had a resolver object
603 | // as the arg rather than a function
604 | (function() {
605 | var resolve;
606 | new local.Promise(function(r) { resolve = r; });
607 | return isFunction(resolve);
608 | }());
609 |
610 | if (!es6PromiseSupport) {
611 | local.Promise = RSVPPromise;
612 | }
613 | }
614 |
615 | exports.polyfill = polyfill;
616 | }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
617 | },{"./promise":7,"./utils":11}],7:[function(require,module,exports){
618 | "use strict";
619 | var config = require("./config").config;
620 | var configure = require("./config").configure;
621 | var objectOrFunction = require("./utils").objectOrFunction;
622 | var isFunction = require("./utils").isFunction;
623 | var now = require("./utils").now;
624 | var all = require("./all").all;
625 | var race = require("./race").race;
626 | var staticResolve = require("./resolve").resolve;
627 | var staticReject = require("./reject").reject;
628 | var asap = require("./asap").asap;
629 |
630 | var counter = 0;
631 |
632 | config.async = asap; // default async is asap;
633 |
634 | function Promise(resolver) {
635 | if (!isFunction(resolver)) {
636 | throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');
637 | }
638 |
639 | if (!(this instanceof Promise)) {
640 | throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");
641 | }
642 |
643 | this._subscribers = [];
644 |
645 | invokeResolver(resolver, this);
646 | }
647 |
648 | function invokeResolver(resolver, promise) {
649 | function resolvePromise(value) {
650 | resolve(promise, value);
651 | }
652 |
653 | function rejectPromise(reason) {
654 | reject(promise, reason);
655 | }
656 |
657 | try {
658 | resolver(resolvePromise, rejectPromise);
659 | } catch(e) {
660 | rejectPromise(e);
661 | }
662 | }
663 |
664 | function invokeCallback(settled, promise, callback, detail) {
665 | var hasCallback = isFunction(callback),
666 | value, error, succeeded, failed;
667 |
668 | if (hasCallback) {
669 | try {
670 | value = callback(detail);
671 | succeeded = true;
672 | } catch(e) {
673 | failed = true;
674 | error = e;
675 | }
676 | } else {
677 | value = detail;
678 | succeeded = true;
679 | }
680 |
681 | if (handleThenable(promise, value)) {
682 | return;
683 | } else if (hasCallback && succeeded) {
684 | resolve(promise, value);
685 | } else if (failed) {
686 | reject(promise, error);
687 | } else if (settled === FULFILLED) {
688 | resolve(promise, value);
689 | } else if (settled === REJECTED) {
690 | reject(promise, value);
691 | }
692 | }
693 |
694 | var PENDING = void 0;
695 | var SEALED = 0;
696 | var FULFILLED = 1;
697 | var REJECTED = 2;
698 |
699 | function subscribe(parent, child, onFulfillment, onRejection) {
700 | var subscribers = parent._subscribers;
701 | var length = subscribers.length;
702 |
703 | subscribers[length] = child;
704 | subscribers[length + FULFILLED] = onFulfillment;
705 | subscribers[length + REJECTED] = onRejection;
706 | }
707 |
708 | function publish(promise, settled) {
709 | var child, callback, subscribers = promise._subscribers, detail = promise._detail;
710 |
711 | for (var i = 0; i < subscribers.length; i += 3) {
712 | child = subscribers[i];
713 | callback = subscribers[i + settled];
714 |
715 | invokeCallback(settled, child, callback, detail);
716 | }
717 |
718 | promise._subscribers = null;
719 | }
720 |
721 | Promise.prototype = {
722 | constructor: Promise,
723 |
724 | _state: undefined,
725 | _detail: undefined,
726 | _subscribers: undefined,
727 |
728 | then: function(onFulfillment, onRejection) {
729 | var promise = this;
730 |
731 | var thenPromise = new this.constructor(function() {});
732 |
733 | if (this._state) {
734 | var callbacks = arguments;
735 | config.async(function invokePromiseCallback() {
736 | invokeCallback(promise._state, thenPromise, callbacks[promise._state - 1], promise._detail);
737 | });
738 | } else {
739 | subscribe(this, thenPromise, onFulfillment, onRejection);
740 | }
741 |
742 | return thenPromise;
743 | },
744 |
745 | 'catch': function(onRejection) {
746 | return this.then(null, onRejection);
747 | }
748 | };
749 |
750 | Promise.all = all;
751 | Promise.race = race;
752 | Promise.resolve = staticResolve;
753 | Promise.reject = staticReject;
754 |
755 | function handleThenable(promise, value) {
756 | var then = null,
757 | resolved;
758 |
759 | try {
760 | if (promise === value) {
761 | throw new TypeError("A promises callback cannot return that same promise.");
762 | }
763 |
764 | if (objectOrFunction(value)) {
765 | then = value.then;
766 |
767 | if (isFunction(then)) {
768 | then.call(value, function(val) {
769 | if (resolved) { return true; }
770 | resolved = true;
771 |
772 | if (value !== val) {
773 | resolve(promise, val);
774 | } else {
775 | fulfill(promise, val);
776 | }
777 | }, function(val) {
778 | if (resolved) { return true; }
779 | resolved = true;
780 |
781 | reject(promise, val);
782 | });
783 |
784 | return true;
785 | }
786 | }
787 | } catch (error) {
788 | if (resolved) { return true; }
789 | reject(promise, error);
790 | return true;
791 | }
792 |
793 | return false;
794 | }
795 |
796 | function resolve(promise, value) {
797 | if (promise === value) {
798 | fulfill(promise, value);
799 | } else if (!handleThenable(promise, value)) {
800 | fulfill(promise, value);
801 | }
802 | }
803 |
804 | function fulfill(promise, value) {
805 | if (promise._state !== PENDING) { return; }
806 | promise._state = SEALED;
807 | promise._detail = value;
808 |
809 | config.async(publishFulfillment, promise);
810 | }
811 |
812 | function reject(promise, reason) {
813 | if (promise._state !== PENDING) { return; }
814 | promise._state = SEALED;
815 | promise._detail = reason;
816 |
817 | config.async(publishRejection, promise);
818 | }
819 |
820 | function publishFulfillment(promise) {
821 | publish(promise, promise._state = FULFILLED);
822 | }
823 |
824 | function publishRejection(promise) {
825 | publish(promise, promise._state = REJECTED);
826 | }
827 |
828 | exports.Promise = Promise;
829 | },{"./all":3,"./asap":4,"./config":5,"./race":8,"./reject":9,"./resolve":10,"./utils":11}],8:[function(require,module,exports){
830 | "use strict";
831 | /* global toString */
832 | var isArray = require("./utils").isArray;
833 |
834 | /**
835 | `RSVP.race` allows you to watch a series of promises and act as soon as the
836 | first promise given to the `promises` argument fulfills or rejects.
837 |
838 | Example:
839 |
840 | ```javascript
841 | var promise1 = new RSVP.Promise(function(resolve, reject){
842 | setTimeout(function(){
843 | resolve("promise 1");
844 | }, 200);
845 | });
846 |
847 | var promise2 = new RSVP.Promise(function(resolve, reject){
848 | setTimeout(function(){
849 | resolve("promise 2");
850 | }, 100);
851 | });
852 |
853 | RSVP.race([promise1, promise2]).then(function(result){
854 | // result === "promise 2" because it was resolved before promise1
855 | // was resolved.
856 | });
857 | ```
858 |
859 | `RSVP.race` is deterministic in that only the state of the first completed
860 | promise matters. For example, even if other promises given to the `promises`
861 | array argument are resolved, but the first completed promise has become
862 | rejected before the other promises became fulfilled, the returned promise
863 | will become rejected:
864 |
865 | ```javascript
866 | var promise1 = new RSVP.Promise(function(resolve, reject){
867 | setTimeout(function(){
868 | resolve("promise 1");
869 | }, 200);
870 | });
871 |
872 | var promise2 = new RSVP.Promise(function(resolve, reject){
873 | setTimeout(function(){
874 | reject(new Error("promise 2"));
875 | }, 100);
876 | });
877 |
878 | RSVP.race([promise1, promise2]).then(function(result){
879 | // Code here never runs because there are rejected promises!
880 | }, function(reason){
881 | // reason.message === "promise2" because promise 2 became rejected before
882 | // promise 1 became fulfilled
883 | });
884 | ```
885 |
886 | @method race
887 | @for RSVP
888 | @param {Array} promises array of promises to observe
889 | @param {String} label optional string for describing the promise returned.
890 | Useful for tooling.
891 | @return {Promise} a promise that becomes fulfilled with the value the first
892 | completed promises is resolved with if the first completed promise was
893 | fulfilled, or rejected with the reason that the first completed promise
894 | was rejected with.
895 | */
896 | function race(promises) {
897 | /*jshint validthis:true */
898 | var Promise = this;
899 |
900 | if (!isArray(promises)) {
901 | throw new TypeError('You must pass an array to race.');
902 | }
903 | return new Promise(function(resolve, reject) {
904 | var results = [], promise;
905 |
906 | for (var i = 0; i < promises.length; i++) {
907 | promise = promises[i];
908 |
909 | if (promise && typeof promise.then === 'function') {
910 | promise.then(resolve, reject);
911 | } else {
912 | resolve(promise);
913 | }
914 | }
915 | });
916 | }
917 |
918 | exports.race = race;
919 | },{"./utils":11}],9:[function(require,module,exports){
920 | "use strict";
921 | /**
922 | `RSVP.reject` returns a promise that will become rejected with the passed
923 | `reason`. `RSVP.reject` is essentially shorthand for the following:
924 |
925 | ```javascript
926 | var promise = new RSVP.Promise(function(resolve, reject){
927 | reject(new Error('WHOOPS'));
928 | });
929 |
930 | promise.then(function(value){
931 | // Code here doesn't run because the promise is rejected!
932 | }, function(reason){
933 | // reason.message === 'WHOOPS'
934 | });
935 | ```
936 |
937 | Instead of writing the above, your code now simply becomes the following:
938 |
939 | ```javascript
940 | var promise = RSVP.reject(new Error('WHOOPS'));
941 |
942 | promise.then(function(value){
943 | // Code here doesn't run because the promise is rejected!
944 | }, function(reason){
945 | // reason.message === 'WHOOPS'
946 | });
947 | ```
948 |
949 | @method reject
950 | @for RSVP
951 | @param {Any} reason value that the returned promise will be rejected with.
952 | @param {String} label optional string for identifying the returned promise.
953 | Useful for tooling.
954 | @return {Promise} a promise that will become rejected with the given
955 | `reason`.
956 | */
957 | function reject(reason) {
958 | /*jshint validthis:true */
959 | var Promise = this;
960 |
961 | return new Promise(function (resolve, reject) {
962 | reject(reason);
963 | });
964 | }
965 |
966 | exports.reject = reject;
967 | },{}],10:[function(require,module,exports){
968 | "use strict";
969 | function resolve(value) {
970 | /*jshint validthis:true */
971 | if (value && typeof value === 'object' && value.constructor === this) {
972 | return value;
973 | }
974 |
975 | var Promise = this;
976 |
977 | return new Promise(function(resolve) {
978 | resolve(value);
979 | });
980 | }
981 |
982 | exports.resolve = resolve;
983 | },{}],11:[function(require,module,exports){
984 | "use strict";
985 | function objectOrFunction(x) {
986 | return isFunction(x) || (typeof x === "object" && x !== null);
987 | }
988 |
989 | function isFunction(x) {
990 | return typeof x === "function";
991 | }
992 |
993 | function isArray(x) {
994 | return Object.prototype.toString.call(x) === "[object Array]";
995 | }
996 |
997 | // Date.now is not available in browsers < IE9
998 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now#Compatibility
999 | var now = Date.now || function() { return new Date().getTime(); };
1000 |
1001 |
1002 | exports.objectOrFunction = objectOrFunction;
1003 | exports.isFunction = isFunction;
1004 | exports.isArray = isArray;
1005 | exports.now = now;
1006 | },{}],12:[function(require,module,exports){
1007 | // Copyright Joyent, Inc. and other Node contributors.
1008 | //
1009 | // Permission is hereby granted, free of charge, to any person obtaining a
1010 | // copy of this software and associated documentation files (the
1011 | // "Software"), to deal in the Software without restriction, including
1012 | // without limitation the rights to use, copy, modify, merge, publish,
1013 | // distribute, sublicense, and/or sell copies of the Software, and to permit
1014 | // persons to whom the Software is furnished to do so, subject to the
1015 | // following conditions:
1016 | //
1017 | // The above copyright notice and this permission notice shall be included
1018 | // in all copies or substantial portions of the Software.
1019 | //
1020 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1021 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1022 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
1023 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
1024 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
1025 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
1026 | // USE OR OTHER DEALINGS IN THE SOFTWARE.
1027 |
1028 | function EventEmitter() {
1029 | this._events = this._events || {};
1030 | this._maxListeners = this._maxListeners || undefined;
1031 | }
1032 | module.exports = EventEmitter;
1033 |
1034 | // Backwards-compat with node 0.10.x
1035 | EventEmitter.EventEmitter = EventEmitter;
1036 |
1037 | EventEmitter.prototype._events = undefined;
1038 | EventEmitter.prototype._maxListeners = undefined;
1039 |
1040 | // By default EventEmitters will print a warning if more than 10 listeners are
1041 | // added to it. This is a useful default which helps finding memory leaks.
1042 | EventEmitter.defaultMaxListeners = 10;
1043 |
1044 | // Obviously not all Emitters should be limited to 10. This function allows
1045 | // that to be increased. Set to zero for unlimited.
1046 | EventEmitter.prototype.setMaxListeners = function(n) {
1047 | if (!isNumber(n) || n < 0 || isNaN(n))
1048 | throw TypeError('n must be a positive number');
1049 | this._maxListeners = n;
1050 | return this;
1051 | };
1052 |
1053 | EventEmitter.prototype.emit = function(type) {
1054 | var er, handler, len, args, i, listeners;
1055 |
1056 | if (!this._events)
1057 | this._events = {};
1058 |
1059 | // If there is no 'error' event listener then throw.
1060 | if (type === 'error') {
1061 | if (!this._events.error ||
1062 | (isObject(this._events.error) && !this._events.error.length)) {
1063 | er = arguments[1];
1064 | if (er instanceof Error) {
1065 | throw er; // Unhandled 'error' event
1066 | }
1067 | throw TypeError('Uncaught, unspecified "error" event.');
1068 | }
1069 | }
1070 |
1071 | handler = this._events[type];
1072 |
1073 | if (isUndefined(handler))
1074 | return false;
1075 |
1076 | if (isFunction(handler)) {
1077 | switch (arguments.length) {
1078 | // fast cases
1079 | case 1:
1080 | handler.call(this);
1081 | break;
1082 | case 2:
1083 | handler.call(this, arguments[1]);
1084 | break;
1085 | case 3:
1086 | handler.call(this, arguments[1], arguments[2]);
1087 | break;
1088 | // slower
1089 | default:
1090 | len = arguments.length;
1091 | args = new Array(len - 1);
1092 | for (i = 1; i < len; i++)
1093 | args[i - 1] = arguments[i];
1094 | handler.apply(this, args);
1095 | }
1096 | } else if (isObject(handler)) {
1097 | len = arguments.length;
1098 | args = new Array(len - 1);
1099 | for (i = 1; i < len; i++)
1100 | args[i - 1] = arguments[i];
1101 |
1102 | listeners = handler.slice();
1103 | len = listeners.length;
1104 | for (i = 0; i < len; i++)
1105 | listeners[i].apply(this, args);
1106 | }
1107 |
1108 | return true;
1109 | };
1110 |
1111 | EventEmitter.prototype.addListener = function(type, listener) {
1112 | var m;
1113 |
1114 | if (!isFunction(listener))
1115 | throw TypeError('listener must be a function');
1116 |
1117 | if (!this._events)
1118 | this._events = {};
1119 |
1120 | // To avoid recursion in the case that type === "newListener"! Before
1121 | // adding it to the listeners, first emit "newListener".
1122 | if (this._events.newListener)
1123 | this.emit('newListener', type,
1124 | isFunction(listener.listener) ?
1125 | listener.listener : listener);
1126 |
1127 | if (!this._events[type])
1128 | // Optimize the case of one listener. Don't need the extra array object.
1129 | this._events[type] = listener;
1130 | else if (isObject(this._events[type]))
1131 | // If we've already got an array, just append.
1132 | this._events[type].push(listener);
1133 | else
1134 | // Adding the second element, need to change to array.
1135 | this._events[type] = [this._events[type], listener];
1136 |
1137 | // Check for listener leak
1138 | if (isObject(this._events[type]) && !this._events[type].warned) {
1139 | var m;
1140 | if (!isUndefined(this._maxListeners)) {
1141 | m = this._maxListeners;
1142 | } else {
1143 | m = EventEmitter.defaultMaxListeners;
1144 | }
1145 |
1146 | if (m && m > 0 && this._events[type].length > m) {
1147 | this._events[type].warned = true;
1148 | console.error('(node) warning: possible EventEmitter memory ' +
1149 | 'leak detected. %d listeners added. ' +
1150 | 'Use emitter.setMaxListeners() to increase limit.',
1151 | this._events[type].length);
1152 | if (typeof console.trace === 'function') {
1153 | // not supported in IE 10
1154 | console.trace();
1155 | }
1156 | }
1157 | }
1158 |
1159 | return this;
1160 | };
1161 |
1162 | EventEmitter.prototype.on = EventEmitter.prototype.addListener;
1163 |
1164 | EventEmitter.prototype.once = function(type, listener) {
1165 | if (!isFunction(listener))
1166 | throw TypeError('listener must be a function');
1167 |
1168 | var fired = false;
1169 |
1170 | function g() {
1171 | this.removeListener(type, g);
1172 |
1173 | if (!fired) {
1174 | fired = true;
1175 | listener.apply(this, arguments);
1176 | }
1177 | }
1178 |
1179 | g.listener = listener;
1180 | this.on(type, g);
1181 |
1182 | return this;
1183 | };
1184 |
1185 | // emits a 'removeListener' event iff the listener was removed
1186 | EventEmitter.prototype.removeListener = function(type, listener) {
1187 | var list, position, length, i;
1188 |
1189 | if (!isFunction(listener))
1190 | throw TypeError('listener must be a function');
1191 |
1192 | if (!this._events || !this._events[type])
1193 | return this;
1194 |
1195 | list = this._events[type];
1196 | length = list.length;
1197 | position = -1;
1198 |
1199 | if (list === listener ||
1200 | (isFunction(list.listener) && list.listener === listener)) {
1201 | delete this._events[type];
1202 | if (this._events.removeListener)
1203 | this.emit('removeListener', type, listener);
1204 |
1205 | } else if (isObject(list)) {
1206 | for (i = length; i-- > 0;) {
1207 | if (list[i] === listener ||
1208 | (list[i].listener && list[i].listener === listener)) {
1209 | position = i;
1210 | break;
1211 | }
1212 | }
1213 |
1214 | if (position < 0)
1215 | return this;
1216 |
1217 | if (list.length === 1) {
1218 | list.length = 0;
1219 | delete this._events[type];
1220 | } else {
1221 | list.splice(position, 1);
1222 | }
1223 |
1224 | if (this._events.removeListener)
1225 | this.emit('removeListener', type, listener);
1226 | }
1227 |
1228 | return this;
1229 | };
1230 |
1231 | EventEmitter.prototype.removeAllListeners = function(type) {
1232 | var key, listeners;
1233 |
1234 | if (!this._events)
1235 | return this;
1236 |
1237 | // not listening for removeListener, no need to emit
1238 | if (!this._events.removeListener) {
1239 | if (arguments.length === 0)
1240 | this._events = {};
1241 | else if (this._events[type])
1242 | delete this._events[type];
1243 | return this;
1244 | }
1245 |
1246 | // emit removeListener for all listeners on all events
1247 | if (arguments.length === 0) {
1248 | for (key in this._events) {
1249 | if (key === 'removeListener') continue;
1250 | this.removeAllListeners(key);
1251 | }
1252 | this.removeAllListeners('removeListener');
1253 | this._events = {};
1254 | return this;
1255 | }
1256 |
1257 | listeners = this._events[type];
1258 |
1259 | if (isFunction(listeners)) {
1260 | this.removeListener(type, listeners);
1261 | } else {
1262 | // LIFO order
1263 | while (listeners.length)
1264 | this.removeListener(type, listeners[listeners.length - 1]);
1265 | }
1266 | delete this._events[type];
1267 |
1268 | return this;
1269 | };
1270 |
1271 | EventEmitter.prototype.listeners = function(type) {
1272 | var ret;
1273 | if (!this._events || !this._events[type])
1274 | ret = [];
1275 | else if (isFunction(this._events[type]))
1276 | ret = [this._events[type]];
1277 | else
1278 | ret = this._events[type].slice();
1279 | return ret;
1280 | };
1281 |
1282 | EventEmitter.listenerCount = function(emitter, type) {
1283 | var ret;
1284 | if (!emitter._events || !emitter._events[type])
1285 | ret = 0;
1286 | else if (isFunction(emitter._events[type]))
1287 | ret = 1;
1288 | else
1289 | ret = emitter._events[type].length;
1290 | return ret;
1291 | };
1292 |
1293 | function isFunction(arg) {
1294 | return typeof arg === 'function';
1295 | }
1296 |
1297 | function isNumber(arg) {
1298 | return typeof arg === 'number';
1299 | }
1300 |
1301 | function isObject(arg) {
1302 | return typeof arg === 'object' && arg !== null;
1303 | }
1304 |
1305 | function isUndefined(arg) {
1306 | return arg === void 0;
1307 | }
1308 |
1309 | },{}],13:[function(require,module,exports){
1310 | // shim for using process in browser
1311 |
1312 | var process = module.exports = {};
1313 |
1314 | process.nextTick = (function () {
1315 | var canSetImmediate = typeof window !== 'undefined'
1316 | && window.setImmediate;
1317 | var canMutationObserver = typeof window !== 'undefined'
1318 | && window.MutationObserver;
1319 | var canPost = typeof window !== 'undefined'
1320 | && window.postMessage && window.addEventListener
1321 | ;
1322 |
1323 | if (canSetImmediate) {
1324 | return function (f) { return window.setImmediate(f) };
1325 | }
1326 |
1327 | var queue = [];
1328 |
1329 | if (canMutationObserver) {
1330 | var hiddenDiv = document.createElement("div");
1331 | var observer = new MutationObserver(function () {
1332 | var queueList = queue.slice();
1333 | queue.length = 0;
1334 | queueList.forEach(function (fn) {
1335 | fn();
1336 | });
1337 | });
1338 |
1339 | observer.observe(hiddenDiv, { attributes: true });
1340 |
1341 | return function nextTick(fn) {
1342 | if (!queue.length) {
1343 | hiddenDiv.setAttribute('yes', 'no');
1344 | }
1345 | queue.push(fn);
1346 | };
1347 | }
1348 |
1349 | if (canPost) {
1350 | window.addEventListener('message', function (ev) {
1351 | var source = ev.source;
1352 | if ((source === window || source === null) && ev.data === 'process-tick') {
1353 | ev.stopPropagation();
1354 | if (queue.length > 0) {
1355 | var fn = queue.shift();
1356 | fn();
1357 | }
1358 | }
1359 | }, true);
1360 |
1361 | return function nextTick(fn) {
1362 | queue.push(fn);
1363 | window.postMessage('process-tick', '*');
1364 | };
1365 | }
1366 |
1367 | return function nextTick(fn) {
1368 | setTimeout(fn, 0);
1369 | };
1370 | })();
1371 |
1372 | process.title = 'browser';
1373 | process.browser = true;
1374 | process.env = {};
1375 | process.argv = [];
1376 |
1377 | function noop() {}
1378 |
1379 | process.on = noop;
1380 | process.addListener = noop;
1381 | process.once = noop;
1382 | process.off = noop;
1383 | process.removeListener = noop;
1384 | process.removeAllListeners = noop;
1385 | process.emit = noop;
1386 |
1387 | process.binding = function (name) {
1388 | throw new Error('process.binding is not supported');
1389 | };
1390 |
1391 | // TODO(shtylman)
1392 | process.cwd = function () { return '/' };
1393 | process.chdir = function (dir) {
1394 | throw new Error('process.chdir is not supported');
1395 | };
1396 |
1397 | },{}]},{},[1])(1)
1398 | });
--------------------------------------------------------------------------------