├── 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 | ![](https://github.com/kinkk/green-chat/blob/master/image/component.png) 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($('' + emotions[category][i].name + '')); 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='"+af+"";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 | }); --------------------------------------------------------------------------------