Created
September 15, 2014 19:47
-
-
Save timestep/1450ebbb228b7f34b001 to your computer and use it in GitHub Desktop.
sail.io.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*! Socket.IO.min.js build:0.9.16, production. Copyright(c) 2011 LearnBoost <[email protected]> MIT Licensed */ | |
var io="undefined"==typeof module?{}:module.exports;(function(){(function(a,b){var c=a;c.version="0.9.16",c.protocol=1,c.transports=[],c.j=[],c.sockets={},c.connect=function(a,d){var e=c.util.parseUri(a),f,g;b&&b.location&&(e.protocol=e.protocol||b.location.protocol.slice(0,-1),e.host=e.host||(b.document?b.document.domain:b.location.hostname),e.port=e.port||b.location.port),f=c.util.uniqueUri(e);var h={host:e.host,secure:"https"==e.protocol,port:e.port||("https"==e.protocol?443:80),query:e.query||""};c.util.merge(h,d);if(h["force new connection"]||!c.sockets[f])g=new c.Socket(h);return!h["force new connection"]&&g&&(c.sockets[f]=g),g=g||c.sockets[f],g.of(e.path.length>1?e.path:"")}})("object"==typeof module?module.exports:this.io={},this),function(a,b){var c=a.util={},d=/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/,e=["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"];c.parseUri=function(a){var b=d.exec(a||""),c={},f=14;while(f--)c[e[f]]=b[f]||"";return c},c.uniqueUri=function(a){var c=a.protocol,d=a.host,e=a.port;return"document"in b?(d=d||document.domain,e=e||(c=="https"&&document.location.protocol!=="https:"?443:document.location.port)):(d=d||"localhost",!e&&c=="https"&&(e=443)),(c||"http")+"://"+d+":"+(e||80)},c.query=function(a,b){var d=c.chunkQuery(a||""),e=[];c.merge(d,c.chunkQuery(b||""));for(var f in d)d.hasOwnProperty(f)&&e.push(f+"="+d[f]);return e.length?"?"+e.join("&"):""},c.chunkQuery=function(a){var b={},c=a.split("&"),d=0,e=c.length,f;for(;d<e;++d)f=c[d].split("="),f[0]&&(b[f[0]]=f[1]);return b};var f=!1;c.load=function(a){if("document"in b&&document.readyState==="complete"||f)return a();c.on(b,"load",a,!1)},c.on=function(a,b,c,d){a.attachEvent?a.attachEvent("on"+b,c):a.addEventListener&&a.addEventListener(b,c,d)},c.request=function(a){if(a&&"undefined"!=typeof XDomainRequest&&!c.ua.hasCORS)return new XDomainRequest;if("undefined"!=typeof XMLHttpRequest&&(!a||c.ua.hasCORS))return new XMLHttpRequest;if(!a)try{return new(window[["Active"].concat("Object").join("X")])("Microsoft.XMLHTTP")}catch(b){}return null},"undefined"!=typeof window&&c.load(function(){f=!0}),c.defer=function(a){if(!c.ua.webkit||"undefined"!=typeof importScripts)return a();c.load(function(){setTimeout(a,100)})},c.merge=function(b,d,e,f){var g=f||[],h=typeof e=="undefined"?2:e,i;for(i in d)d.hasOwnProperty(i)&&c.indexOf(g,i)<0&&(typeof b[i]!="object"||!h?(b[i]=d[i],g.push(d[i])):c.merge(b[i],d[i],h-1,g));return b},c.mixin=function(a,b){c.merge(a.prototype,b.prototype)},c.inherit=function(a,b){function c(){}c.prototype=b.prototype,a.prototype=new c},c.isArray=Array.isArray||function(a){return Object.prototype.toString.call(a)==="[object Array]"},c.intersect=function(a,b){var d=[],e=a.length>b.length?a:b,f=a.length>b.length?b:a;for(var g=0,h=f.length;g<h;g++)~c.indexOf(e,f[g])&&d.push(f[g]);return d},c.indexOf=function(a,b,c){for(var d=a.length,c=c<0?c+d<0?0:c+d:c||0;c<d&&a[c]!==b;c++);return d<=c?-1:c},c.toArray=function(a){var b=[];for(var c=0,d=a.length;c<d;c++)b.push(a[c]);return b},c.ua={},c.ua.hasCORS="undefined"!=typeof XMLHttpRequest&&function(){try{var a=new XMLHttpRequest}catch(b){return!1}return a.withCredentials!=undefined}(),c.ua.webkit="undefined"!=typeof navigator&&/webkit/i.test(navigator.userAgent),c.ua.iDevice="undefined"!=typeof navigator&&/iPad|iPhone|iPod/i.test(navigator.userAgent)}("undefined"!=typeof io?io:module.exports,this),function(a,b){function c(){}a.EventEmitter=c,c.prototype.on=function(a,c){return this.$events||(this.$events={}),this.$events[a]?b.util.isArray(this.$events[a])?this.$events[a].push(c):this.$events[a]=[this.$events[a],c]:this.$events[a]=c,this},c.prototype.addListener=c.prototype.on,c.prototype.once=function(a,b){function d(){c.removeListener(a,d),b.apply(this,arguments)}var c=this;return d.listener=b,this.on(a,d),this},c.prototype.removeListener=function(a,c){if(this.$events&&this.$events[a]){var d=this.$events[a];if(b.util.isArray(d)){var e=-1;for(var f=0,g=d.length;f<g;f++)if(d[f]===c||d[f].listener&&d[f].listener===c){e=f;break}if(e<0)return this;d.splice(e,1),d.length||delete this.$events[a]}else(d===c||d.listener&&d.listener===c)&&delete this.$events[a]}return this},c.prototype.removeAllListeners=function(a){return a===undefined?(this.$events={},this):(this.$events&&this.$events[a]&&(this.$events[a]=null),this)},c.prototype.listeners=function(a){return this.$events||(this.$events={}),this.$events[a]||(this.$events[a]=[]),b.util.isArray(this.$events[a])||(this.$events[a]=[this.$events[a]]),this.$events[a]},c.prototype.emit=function(a){if(!this.$events)return!1;var c=this.$events[a];if(!c)return!1;var d=Array.prototype.slice.call(arguments,1);if("function"==typeof c)c.apply(this,d);else{if(!b.util.isArray(c))return!1;var e=c.slice();for(var f=0,g=e.length;f<g;f++)e[f].apply(this,d)}return!0}}("undefined"!=typeof io?io:module.exports,"undefined"!=typeof io?io:module.parent.exports),function(exports,nativeJSON){function f(a){return a<10?"0"+a:a}function date(a,b){return isFinite(a.valueOf())?a.getUTCFullYear()+"-"+f(a.getUTCMonth()+1)+"-"+f(a.getUTCDate())+"T"+f(a.getUTCHours())+":"+f(a.getUTCMinutes())+":"+f(a.getUTCSeconds())+"Z":null}function quote(a){return escapable.lastIndex=0,escapable.test(a)?'"'+a.replace(escapable,function(a){var b=meta[a];return typeof b=="string"?b:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+a+'"'}function str(a,b){var c,d,e,f,g=gap,h,i=b[a];i instanceof Date&&(i=date(a)),typeof rep=="function"&&(i=rep.call(b,a,i));switch(typeof i){case"string":return quote(i);case"number":return isFinite(i)?String(i):"null";case"boolean":case"null":return String(i);case"object":if(!i)return"null";gap+=indent,h=[];if(Object.prototype.toString.apply(i)==="[object Array]"){f=i.length;for(c=0;c<f;c+=1)h[c]=str(c,i)||"null";return e=h.length===0?"[]":gap?"[\n"+gap+h.join(",\n"+gap)+"\n"+g+"]":"["+h.join(",")+"]",gap=g,e}if(rep&&typeof rep=="object"){f=rep.length;for(c=0;c<f;c+=1)typeof rep[c]=="string"&&(d=rep[c],e=str(d,i),e&&h.push(quote(d)+(gap?": ":":")+e))}else for(d in i)Object.prototype.hasOwnProperty.call(i,d)&&(e=str(d,i),e&&h.push(quote(d)+(gap?": ":":")+e));return e=h.length===0?"{}":gap?"{\n"+gap+h.join(",\n"+gap)+"\n"+g+"}":"{"+h.join(",")+"}",gap=g,e}}"use strict";if(nativeJSON&&nativeJSON.parse)return exports.JSON={parse:nativeJSON.parse,stringify:nativeJSON.stringify};var JSON=exports.JSON={},cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;JSON.stringify=function(a,b,c){var d;gap="",indent="";if(typeof c=="number")for(d=0;d<c;d+=1)indent+=" ";else typeof c=="string"&&(indent=c);rep=b;if(!b||typeof b=="function"||typeof b=="object"&&typeof b.length=="number")return str("",{"":a});throw new Error("JSON.stringify")},JSON.parse=function(text,reviver){function walk(a,b){var c,d,e=a[b];if(e&&typeof e=="object")for(c in e)Object.prototype.hasOwnProperty.call(e,c)&&(d=walk(e,c),d!==undefined?e[c]=d:delete e[c]);return reviver.call(a,b,e)}var j;text=String(text),cx.lastIndex=0,cx.test(text)&&(text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)}));if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return j=eval("("+text+")"),typeof reviver=="function"?walk({"":j},""):j;throw new SyntaxError("JSON.parse")}}("undefined"!=typeof io?io:module.exports,typeof JSON!="undefined"?JSON:undefined),function(a,b){var c=a.parser={},d=c.packets=["disconnect","connect","heartbeat","message","json","event","ack","error","noop"],e=c.reasons=["transport not supported","client not handshaken","unauthorized"],f=c.advice=["reconnect"],g=b.JSON,h=b.util.indexOf;c.encodePacket=function(a){var b=h(d,a.type),c=a.id||"",i=a.endpoint||"",j=a.ack,k=null;switch(a.type){case"error":var l=a.reason?h(e,a.reason):"",m=a.advice?h(f,a.advice):"";if(l!==""||m!=="")k=l+(m!==""?"+"+m:"");break;case"message":a.data!==""&&(k=a.data);break;case"event":var n={name:a.name};a.args&&a.args.length&&(n.args=a.args),k=g.stringify(n);break;case"json":k=g.stringify(a.data);break;case"connect":a.qs&&(k=a.qs);break;case"ack":k=a.ackId+(a.args&&a.args.length?"+"+g.stringify(a.args):"")}var o=[b,c+(j=="data"?"+":""),i];return k!==null&&k!==undefined&&o.push(k),o.join(":")},c.encodePayload=function(a){var b="";if(a.length==1)return a[0];for(var c=0,d=a.length;c<d;c++){var e=a[c];b+="\ufffd"+e.length+"\ufffd"+a[c]}return b};var i=/([^:]+):([0-9]+)?(\+)?:([^:]+)?:?([\s\S]*)?/;c.decodePacket=function(a){var b=a.match(i);if(!b)return{};var c=b[2]||"",a=b[5]||"",h={type:d[b[1]],endpoint:b[4]||""};c&&(h.id=c,b[3]?h.ack="data":h.ack=!0);switch(h.type){case"error":var b=a.split("+");h.reason=e[b[0]]||"",h.advice=f[b[1]]||"";break;case"message":h.data=a||"";break;case"event":try{var j=g.parse(a);h.name=j.name,h.args=j.args}catch(k){}h.args=h.args||[];break;case"json":try{h.data=g.parse(a)}catch(k){}break;case"connect":h.qs=a||"";break;case"ack":var b=a.match(/^([0-9]+)(\+)?(.*)/);if(b){h.ackId=b[1],h.args=[];if(b[3])try{h.args=b[3]?g.parse(b[3]):[]}catch(k){}}break;case"disconnect":case"heartbeat":}return h},c.decodePayload=function(a){if(a.charAt(0)=="\ufffd"){var b=[];for(var d=1,e="";d<a.length;d++)a.charAt(d)=="\ufffd"?(b.push(c.decodePacket(a.substr(d+1).substr(0,e))),d+=Number(e)+1,e=""):e+=a.charAt(d);return b}return[c.decodePacket(a)]}}("undefined"!=typeof io?io:module.exports,"undefined"!=typeof io?io:module.parent.exports),function(a,b){function c(a,b){this.socket=a,this.sessid=b}a.Transport=c,b.util.mixin(c,b.EventEmitter),c.prototype.heartbeats=function(){return!0},c.prototype.onData=function(a){this.clearCloseTimeout(),(this.socket.connected||this.socket.connecting||this.socket.reconnecting)&&this.setCloseTimeout();if(a!==""){var c=b.parser.decodePayload(a);if(c&&c.length)for(var d=0,e=c.length;d<e;d++)this.onPacket(c[d])}return this},c.prototype.onPacket=function(a){return this.socket.setHeartbeatTimeout(),a.type=="heartbeat"?this.onHeartbeat():(a.type=="connect"&&a.endpoint==""&&this.onConnect(),a.type=="error"&&a.advice=="reconnect"&&(this.isOpen=!1),this.socket.onPacket(a),this)},c.prototype.setCloseTimeout=function(){if(!this.closeTimeout){var a=this;this.closeTimeout=setTimeout(function(){a.onDisconnect()},this.socket.closeTimeout)}},c.prototype.onDisconnect=function(){return this.isOpen&&this.close(),this.clearTimeouts(),this.socket.onDisconnect(),this},c.prototype.onConnect=function(){return this.socket.onConnect(),this},c.prototype.clearCloseTimeout=function(){this.closeTimeout&&(clearTimeout(this.closeTimeout),this.closeTimeout=null)},c.prototype.clearTimeouts=function(){this.clearCloseTimeout(),this.reopenTimeout&&clearTimeout(this.reopenTimeout)},c.prototype.packet=function(a){this.send(b.parser.encodePacket(a))},c.prototype.onHeartbeat=function(a){this.packet({type:"heartbeat"})},c.prototype.onOpen=function(){this.isOpen=!0,this.clearCloseTimeout(),this.socket.onOpen()},c.prototype.onClose=function(){var a=this;this.isOpen=!1,this.socket.onClose(),this.onDisconnect()},c.prototype.prepareUrl=function(){var a=this.socket.options;return this.scheme()+"://"+a.host+":"+a.port+"/"+a.resource+"/"+b.protocol+"/"+this.name+"/"+this.sessid},c.prototype.ready=function(a,b){b.call(this)}}("undefined"!=typeof io?io:module.exports,"undefined"!=typeof io?io:module.parent.exports),function(a,b,c){function d(a){this.options={port:80,secure:!1,document:"document"in c?document:!1,resource:"socket.io",transports:b.transports,"connect timeout":1e4,"try multiple transports":!0,reconnect:!0,"reconnection delay":500,"reconnection limit":Infinity,"reopen delay":3e3,"max reconnection attempts":10,"sync disconnect on unload":!1,"auto connect":!0,"flash policy port":10843,manualFlush:!1},b.util.merge(this.options,a),this.connected=!1,this.open=!1,this.connecting=!1,this.reconnecting=!1,this.namespaces={},this.buffer=[],this.doBuffer=!1;if(this.options["sync disconnect on unload"]&&(!this.isXDomain()||b.util.ua.hasCORS)){var d=this;b.util.on(c,"beforeunload",function(){d.disconnectSync()},!1)}this.options["auto connect"]&&this.connect()}function e(){}a.Socket=d,b.util.mixin(d,b.EventEmitter),d.prototype.of=function(a){return this.namespaces[a]||(this.namespaces[a]=new b.SocketNamespace(this,a),a!==""&&this.namespaces[a].packet({type:"connect"})),this.namespaces[a]},d.prototype.publish=function(){this.emit.apply(this,arguments);var a;for(var b in this.namespaces)this.namespaces.hasOwnProperty(b)&&(a=this.of(b),a.$emit.apply(a,arguments))},d.prototype.handshake=function(a){function f(b){b instanceof Error?(c.connecting=!1,c.onError(b.message)):a.apply(null,b.split(":"))}var c=this,d=this.options,g=["http"+(d.secure?"s":"")+":/",d.host+":"+d.port,d.resource,b.protocol,b.util.query(this.options.query,"t="+ +(new Date))].join("/");if(this.isXDomain()&&!b.util.ua.hasCORS){var h=document.getElementsByTagName("script")[0],i=document.createElement("script");i.src=g+"&jsonp="+b.j.length,h.parentNode.insertBefore(i,h),b.j.push(function(a){f(a),i.parentNode.removeChild(i)})}else{var j=b.util.request();j.open("GET",g,!0),this.isXDomain()&&(j.withCredentials=!0),j.onreadystatechange=function(){j.readyState==4&&(j.onreadystatechange=e,j.status==200?f(j.responseText):j.status==403?c.onError(j.responseText):(c.connecting=!1,!c.reconnecting&&c.onError(j.responseText)))},j.send(null)}},d.prototype.getTransport=function(a){var c=a||this.transports,d;for(var e=0,f;f=c[e];e++)if(b.Transport[f]&&b.Transport[f].check(this)&&(!this.isXDomain()||b.Transport[f].xdomainCheck(this)))return new b.Transport[f](this,this.sessionid);return null},d.prototype.connect=function(a){if(this.connecting)return this;var c=this;return c.connecting=!0,this.handshake(function(d,e,f,g){function h(a){c.transport&&c.transport.clearTimeouts(),c.transport=c.getTransport(a);if(!c.transport)return c.publish("connect_failed");c.transport.ready(c,function(){c.connecting=!0,c.publish("connecting",c.transport.name),c.transport.open(),c.options["connect timeout"]&&(c.connectTimeoutTimer=setTimeout(function(){if(!c.connected){c.connecting=!1;if(c.options["try multiple transports"]){var a=c.transports;while(a.length>0&&a.splice(0,1)[0]!=c.transport.name);a.length?h(a):c.publish("connect_failed")}}},c.options["connect timeout"]))})}c.sessionid=d,c.closeTimeout=f*1e3,c.heartbeatTimeout=e*1e3,c.transports||(c.transports=c.origTransports=g?b.util.intersect(g.split(","),c.options.transports):c.options.transports),c.setHeartbeatTimeout(),h(c.transports),c.once("connect",function(){clearTimeout(c.connectTimeoutTimer),a&&typeof a=="function"&&a()})}),this},d.prototype.setHeartbeatTimeout=function(){clearTimeout(this.heartbeatTimeoutTimer);if(this.transport&&!this.transport.heartbeats())return;var a=this;this.heartbeatTimeoutTimer=setTimeout(function(){a.transport.onClose()},this.heartbeatTimeout)},d.prototype.packet=function(a){return this.connected&&!this.doBuffer?this.transport.packet(a):this.buffer.push(a),this},d.prototype.setBuffer=function(a){this.doBuffer=a,!a&&this.connected&&this.buffer.length&&(this.options.manualFlush||this.flushBuffer())},d.prototype.flushBuffer=function(){this.transport.payload(this.buffer),this.buffer=[]},d.prototype.disconnect=function(){if(this.connected||this.connecting)this.open&&this.of("").packet({type:"disconnect"}),this.onDisconnect("booted");return this},d.prototype.disconnectSync=function(){var a=b.util.request(),c=["http"+(this.options.secure?"s":"")+":/",this.options.host+":"+this.options.port,this.options.resource,b.protocol,"",this.sessionid].join("/")+"/?disconnect=1";a.open("GET",c,!1),a.send(null),this.onDisconnect("booted")},d.prototype.isXDomain=function(){var a=c.location.port||("https:"==c.location.protocol?443:80);return this.options.host!==c.location.hostname||this.options.port!=a},d.prototype.onConnect=function(){this.connected||(this.connected=!0,this.connecting=!1,this.doBuffer||this.setBuffer(!1),this.emit("connect"))},d.prototype.onOpen=function(){this.open=!0},d.prototype.onClose=function(){this.open=!1,clearTimeout(this.heartbeatTimeoutTimer)},d.prototype.onPacket=function(a){this.of(a.endpoint).onPacket(a)},d.prototype.onError=function(a){a&&a.advice&&a.advice==="reconnect"&&(this.connected||this.connecting)&&(this.disconnect(),this.options.reconnect&&this.reconnect()),this.publish("error",a&&a.reason?a.reason:a)},d.prototype.onDisconnect=function(a){var b=this.connected,c=this.connecting;this.connected=!1,this.connecting=!1,this.open=!1;if(b||c)this.transport.close(),this.transport.clearTimeouts(),b&&(this.publish("disconnect",a),"booted"!=a&&this.options.reconnect&&!this.reconnecting&&this.reconnect())},d.prototype.reconnect=function(){function e(){if(a.connected){for(var b in a.namespaces)a.namespaces.hasOwnProperty(b)&&""!==b&&a.namespaces[b].packet({type:"connect"});a.publish("reconnect",a.transport.name,a.reconnectionAttempts)}clearTimeout(a.reconnectionTimer),a.removeListener("connect_failed",f),a.removeListener("connect",f),a.reconnecting=!1,delete a.reconnectionAttempts,delete a.reconnectionDelay,delete a.reconnectionTimer,delete a.redoTransports,a.options["try multiple transports"]=c}function f(){if(!a.reconnecting)return;if(a.connected)return e();if(a.connecting&&a.reconnecting)return a.reconnectionTimer=setTimeout(f,1e3);a.reconnectionAttempts++>=b?a.redoTransports?(a.publish("reconnect_failed"),e()):(a.on("connect_failed",f),a.options["try multiple transports"]=!0,a.transports=a.origTransports,a.transport=a.getTransport(),a.redoTransports=!0,a.connect()):(a.reconnectionDelay<d&&(a.reconnectionDelay*=2),a.connect(),a.publish("reconnecting",a.reconnectionDelay,a.reconnectionAttempts),a.reconnectionTimer=setTimeout(f,a.reconnectionDelay))}this.reconnecting=!0,this.reconnectionAttempts=0,this.reconnectionDelay=this.options["reconnection delay"];var a=this,b=this.options["max reconnection attempts"],c=this.options["try multiple transports"],d=this.options["reconnection limit"];this.options["try multiple transports"]=!1,this.reconnectionTimer=setTimeout(f,this.reconnectionDelay),this.on("connect",f)}}("undefined"!=typeof io?io:module.exports,"undefined"!=typeof io?io:module.parent.exports,this),function(a,b){function c(a,b){this.socket=a,this.name=b||"",this.flags={},this.json=new d(this,"json"),this.ackPackets=0,this.acks={}}function d(a,b){this.namespace=a,this.name=b}a.SocketNamespace=c,b.util.mixin(c,b.EventEmitter),c.prototype.$emit=b.EventEmitter.prototype.emit,c.prototype.of=function(){return this.socket.of.apply(this.socket,arguments)},c.prototype.packet=function(a){return a.endpoint=this.name,this.socket.packet(a),this.flags={},this},c.prototype.send=function(a,b){var c={type:this.flags.json?"json":"message",data:a};return"function"==typeof b&&(c.id=++this.ackPackets,c.ack=!0,this.acks[c.id]=b),this.packet(c)},c.prototype.emit=function(a){var b=Array.prototype.slice.call(arguments,1),c=b[b.length-1],d={type:"event",name:a};return"function"==typeof c&&(d.id=++this.ackPackets,d.ack="data",this.acks[d.id]=c,b=b.slice(0,b.length-1)),d.args=b,this.packet(d)},c.prototype.disconnect=function(){return this.name===""?this.socket.disconnect():(this.packet({type:"disconnect"}),this.$emit("disconnect")),this},c.prototype.onPacket=function(a){function d(){c.packet({type:"ack",args:b.util.toArray(arguments),ackId:a.id})}var c=this;switch(a.type){case"connect":this.$emit("connect");break;case"disconnect":this.name===""?this.socket.onDisconnect(a.reason||"booted"):this.$emit("disconnect",a.reason);break;case"message":case"json":var e=["message",a.data];a.ack=="data"?e.push(d):a.ack&&this.packet({type:"ack",ackId:a.id}),this.$emit.apply(this,e);break;case"event":var e=[a.name].concat(a.args);a.ack=="data"&&e.push(d),this.$emit.apply(this,e);break;case"ack":this.acks[a.ackId]&&(this.acks[a.ackId].apply(this,a.args),delete this.acks[a.ackId]);break;case"error":a.advice?this.socket.onError(a):a.reason=="unauthorized"?this.$emit("connect_failed",a.reason):this.$emit("error",a.reason)}},d.prototype.send=function(){this.namespace.flags[this.name]=!0,this.namespace.send.apply(this.namespace,arguments)},d.prototype.emit=function(){this.namespace.flags[this.name]=!0,this.namespace.emit.apply(this.namespace,arguments)}}("undefined"!=typeof io?io:module.exports,"undefined"!=typeof io?io:module.parent.exports),function(a,b,c){function d(a){b.Transport.apply(this,arguments)}a.websocket=d,b.util.inherit(d,b.Transport),d.prototype.name="websocket",d.prototype.open=function(){var a=b.util.query(this.socket.options.query),d=this,e;return e||(e=c.MozWebSocket||c.WebSocket),this.websocket=new e(this.prepareUrl()+a),this.websocket.onopen=function(){d.onOpen(),d.socket.setBuffer(!1)},this.websocket.onmessage=function(a){d.onData(a.data)},this.websocket.onclose=function(){d.onClose(),d.socket.setBuffer(!0)},this.websocket.onerror=function(a){d.onError(a)},this},b.util.ua.iDevice?d.prototype.send=function(a){var b=this;return setTimeout(function(){b.websocket.send(a)},0),this}:d.prototype.send=function(a){return this.websocket.send(a),this},d.prototype.payload=function(a){for(var b=0,c=a.length;b<c;b++)this.packet(a[b]);return this},d.prototype.close=function(){return this.websocket.close(),this},d.prototype.onError=function(a){this.socket.onError(a)},d.prototype.scheme=function(){return this.socket.options.secure?"wss":"ws"},d.check=function(){return"WebSocket"in c&&!("__addTask"in WebSocket)||"MozWebSocket"in c},d.xdomainCheck=function(){return!0},b.transports.push("websocket")}("undefined"!=typeof io?io.Transport:module.exports,"undefined"!=typeof io?io:module.parent.exports,this),function(a,b){function c(){b.Transport.websocket.apply(this,arguments)}a.flashsocket=c,b.util.inherit(c,b.Transport.websocket),c.prototype.name="flashsocket",c.prototype.open=function(){var a=this,c=arguments;return WebSocket.__addTask(function(){b.Transport.websocket.prototype.open.apply(a,c)}),this},c.prototype.send=function(){var a=this,c=arguments;return WebSocket.__addTask(function(){b.Transport.websocket.prototype.send.apply(a,c)}),this},c.prototype.close=function(){return WebSocket.__tasks.length=0,b.Transport.websocket.prototype.close.call(this),this},c.prototype.ready=function(a,d){function e(){var b=a.options,e=b["flash policy port"],g=["http"+(b.secure?"s":"")+":/",b.host+":"+b.port,b.resource,"static/flashsocket","WebSocketMain"+(a.isXDomain()?"Insecure":"")+".swf"];c.loaded||(typeof WEB_SOCKET_SWF_LOCATION=="undefined"&&(WEB_SOCKET_SWF_LOCATION=g.join("/")),e!==843&&WebSocket.loadFlashPolicyFile("xmlsocket://"+b.host+":"+e),WebSocket.__initialize(),c.loaded=!0),d.call(f)}var f=this;if(document.body)return e();b.util.load(e)},c.check=function(){return typeof WebSocket!="undefined"&&"__initialize"in WebSocket&&!!swfobject?swfobject.getFlashPlayerVersion().major>=10:!1},c.xdomainCheck=function(){return!0},typeof window!="undefined"&&(WEB_SOCKET_DISABLE_AUTO_INITIALIZATION=!0),b.transports.push("flashsocket")}("undefined"!=typeof io?io.Transport:module.exports,"undefined"!=typeof io?io:module.parent.exports);if("undefined"!=typeof window)var swfobject=function(){function A(){if(t)return;try{var a=i.getElementsByTagName("body")[0].appendChild(Q("span"));a.parentNode.removeChild(a)}catch(b){return}t=!0;var c=l.length;for(var d=0;d<c;d++)l[d]()}function B(a){t?a():l[l.length]=a}function C(b){if(typeof h.addEventListener!=a)h.addEventListener("load",b,!1);else if(typeof i.addEventListener!=a)i.addEventListener("load",b,!1);else if(typeof h.attachEvent!=a)R(h,"onload",b);else if(typeof h.onload=="function"){var c=h.onload;h.onload=function(){c(),b()}}else h.onload=b}function D(){k?E():F()}function E(){var c=i.getElementsByTagName("body")[0],d=Q(b);d.setAttribute("type",e);var f=c.appendChild(d);if(f){var g=0;(function(){if(typeof f.GetVariable!=a){var b=f.GetVariable("$version");b&&(b=b.split(" ")[1].split(","),y.pv=[parseInt(b[0],10),parseInt(b[1],10),parseInt(b[2],10)])}else if(g<10){g++,setTimeout(arguments.callee,10);return}c.removeChild(d),f=null,F()})()}else F()}function F(){var b=m.length;if(b>0)for(var c=0;c<b;c++){var d=m[c].id,e=m[c].callbackFn,f={success:!1,id:d};if(y.pv[0]>0){var g=P(d);if(g)if(S(m[c].swfVersion)&&!(y.wk&&y.wk<312))U(d,!0),e&&(f.success=!0,f.ref=G(d),e(f));else if(m[c].expressInstall&&H()){var h={};h.data=m[c].expressInstall,h.width=g.getAttribute("width")||"0",h.height=g.getAttribute("height")||"0",g.getAttribute("class")&&(h.styleclass=g.getAttribute("class")),g.getAttribute("align")&&(h.align=g.getAttribute("align"));var i={},j=g.getElementsByTagName("param"),k=j.length;for(var l=0;l<k;l++)j[l].getAttribute("name").toLowerCase()!="movie"&&(i[j[l].getAttribute("name")]=j[l].getAttribute("value"));I(h,i,d,e)}else J(g),e&&e(f)}else{U(d,!0);if(e){var n=G(d);n&&typeof n.SetVariable!=a&&(f.success=!0,f.ref=n),e(f)}}}}function G(c){var d=null,e=P(c);if(e&&e.nodeName=="OBJECT")if(typeof e.SetVariable!=a)d=e;else{var f=e.getElementsByTagName(b)[0];f&&(d=f)}return d}function H(){return!u&&S("6.0.65")&&(y.win||y.mac)&&!(y.wk&&y.wk<312)}function I(b,c,d,e){u=!0,r=e||null,s={success:!1,id:d};var g=P(d);if(g){g.nodeName=="OBJECT"?(p=K(g),q=null):(p=g,q=d),b.id=f;if(typeof b.width==a||!/%$/.test(b.width)&&parseInt(b.width,10)<310)b.width="310";if(typeof b.height==a||!/%$/.test(b.height)&&parseInt(b.height,10)<137)b.height="137";i.title=i.title.slice(0,47)+" - Flash Player Installation";var j=y.ie&&y.win?["Active"].concat("").join("X"):"PlugIn",k="MMredirectURL="+h.location.toString().replace(/&/g,"%26")+"&MMplayerType="+j+"&MMdoctitle="+i.title;typeof c.flashvars!=a?c.flashvars+="&"+k:c.flashvars=k;if(y.ie&&y.win&&g.readyState!=4){var l=Q("div");d+="SWFObjectNew",l.setAttribute("id",d),g.parentNode.insertBefore(l,g),g.style.display="none",function(){g.readyState==4?g.parentNode.removeChild(g):setTimeout(arguments.callee,10)}()}L(b,c,d)}}function J(a){if(y.ie&&y.win&&a.readyState!=4){var b=Q("div");a.parentNode.insertBefore(b,a),b.parentNode.replaceChild(K(a),b),a.style.display="none",function(){a.readyState==4?a.parentNode.removeChild(a):setTimeout(arguments.callee,10)}()}else a.parentNode.replaceChild(K(a),a)}function K(a){var c=Q("div");if(y.win&&y.ie)c.innerHTML=a.innerHTML;else{var d=a.getElementsByTagName(b)[0];if(d){var e=d.childNodes;if(e){var f=e.length;for(var g=0;g<f;g++)(e[g].nodeType!=1||e[g].nodeName!="PARAM")&&e[g].nodeType!=8&&c.appendChild(e[g].cloneNode(!0))}}}return c}function L(c,d,f){var g,h=P(f);if(y.wk&&y.wk<312)return g;if(h){typeof c.id==a&&(c.id=f);if(y.ie&&y.win){var i="";for(var j in c)c[j]!=Object.prototype[j]&&(j.toLowerCase()=="data"?d.movie=c[j]:j.toLowerCase()=="styleclass"?i+=' class="'+c[j]+'"':j.toLowerCase()!="classid"&&(i+=" "+j+'="'+c[j]+'"'));var k="";for(var l in d)d[l]!=Object.prototype[l]&&(k+='<param name="'+l+'" value="'+d[l]+'" />');h.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+i+">"+k+"</object>",n[n.length]=c.id,g=P(c.id)}else{var m=Q(b);m.setAttribute("type",e);for(var o in c)c[o]!=Object.prototype[o]&&(o.toLowerCase()=="styleclass"?m.setAttribute("class",c[o]):o.toLowerCase()!="classid"&&m.setAttribute(o,c[o]));for(var p in d)d[p]!=Object.prototype[p]&&p.toLowerCase()!="movie"&&M(m,p,d[p]);h.parentNode.replaceChild(m,h),g=m}}return g}function M(a,b,c){var d=Q("param");d.setAttribute("name",b),d.setAttribute("value",c),a.appendChild(d)}function N(a){var b=P(a);b&&b.nodeName=="OBJECT"&&(y.ie&&y.win?(b.style.display="none",function(){b.readyState==4?O(a):setTimeout(arguments.callee,10)}()):b.parentNode.removeChild(b))}function O(a){var b=P(a);if(b){for(var c in b)typeof b[c]=="function"&&(b[c]=null);b.parentNode.removeChild(b)}}function P(a){var b=null;try{b=i.getElementById(a)}catch(c){}return b}function Q(a){return i.createElement(a)}function R(a,b,c){a.attachEvent(b,c),o[o.length]=[a,b,c]}function S(a){var b=y.pv,c=a.split(".");return c[0]=parseInt(c[0],10),c[1]=parseInt(c[1],10)||0,c[2]=parseInt(c[2],10)||0,b[0]>c[0]||b[0]==c[0]&&b[1]>c[1]||b[0]==c[0]&&b[1]==c[1]&&b[2]>=c[2]?!0:!1}function T(c,d,e,f){if(y.ie&&y.mac)return;var g=i.getElementsByTagName("head")[0];if(!g)return;var h=e&&typeof e=="string"?e:"screen";f&&(v=null,w=null);if(!v||w!=h){var j=Q("style");j.setAttribute("type","text/css"),j.setAttribute("media",h),v=g.appendChild(j),y.ie&&y.win&&typeof i.styleSheets!=a&&i.styleSheets.length>0&&(v=i.styleSheets[i.styleSheets.length-1]),w=h}y.ie&&y.win?v&&typeof v.addRule==b&&v.addRule(c,d):v&&typeof i.createTextNode!=a&&v.appendChild(i.createTextNode(c+" {"+d+"}"))}function U(a,b){if(!x)return;var c=b?"visible":"hidden";t&&P(a)?P(a).style.visibility=c:T("#"+a,"visibility:"+c)}function V(b){var c=/[\\\"<>\.;]/,d=c.exec(b)!=null;return d&&typeof encodeURIComponent!=a?encodeURIComponent(b):b}var a="undefined",b="object",c="Shockwave Flash",d="ShockwaveFlash.ShockwaveFlash",e="application/x-shockwave-flash",f="SWFObjectExprInst",g="onreadystatechange",h=window,i=document,j=navigator,k=!1,l=[D],m=[],n=[],o=[],p,q,r,s,t=!1,u=!1,v,w,x=!0,y=function(){var f=typeof i.getElementById!=a&&typeof i.getElementsByTagName!=a&&typeof i.createElement!=a,g=j.userAgent.toLowerCase(),l=j.platform.toLowerCase(),m=l?/win/.test(l):/win/.test(g),n=l?/mac/.test(l):/mac/.test(g),o=/webkit/.test(g)?parseFloat(g.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):!1,p=!1,q=[0,0,0],r=null;if(typeof j.plugins!=a&&typeof j.plugins[c]==b)r=j.plugins[c].description,r&&(typeof j.mimeTypes==a||!j.mimeTypes[e]||!!j.mimeTypes[e].enabledPlugin)&&(k=!0,p=!1,r=r.replace(/^.*\s+(\S+\s+\S+$)/,"$1"),q[0]=parseInt(r.replace(/^(.*)\..*$/,"$1"),10),q[1]=parseInt(r.replace(/^.*\.(.*)\s.*$/,"$1"),10),q[2]=/[a-zA-Z]/.test(r)?parseInt(r.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0);else if(typeof h[["Active"].concat("Object").join("X")]!=a)try{var s=new(window[["Active"].concat("Object").join("X")])(d);s&&(r=s.GetVariable("$version"),r&&(p=!0,r=r.split(" ")[1].split(","),q=[parseInt(r[0],10),parseInt(r[1],10),parseInt(r[2],10)]))}catch(t){}return{w3:f,pv:q,wk:o,ie:p,win:m,mac:n}}(),z=function(){if(!y.w3)return;(typeof i.readyState!=a&&i.readyState=="complete"||typeof i.readyState==a&&(i.getElementsByTagName("body")[0]||i.body))&&A(),t||(typeof i.addEventListener!=a&&i.addEventListener("DOMContentLoaded",A,!1),y.ie&&y.win&&(i.attachEvent(g,function(){i.readyState=="complete"&&(i.detachEvent(g,arguments.callee),A())}),h==top&&function(){if(t)return;try{i.documentElement.doScroll("left")}catch(a){setTimeout(arguments.callee,0);return}A()}()),y.wk&&function(){if(t)return;if(!/loaded|complete/.test(i.readyState)){setTimeout(arguments.callee,0);return}A()}(),C(A))}(),W=function(){y.ie&&y.win&&window.attachEvent("onunload",function(){var a=o.length;for(var b=0;b<a;b++)o[b][0].detachEvent(o[b][1],o[b][2]);var c=n.length;for(var d=0;d<c;d++)N(n[d]);for(var e in y)y[e]=null;y=null;for(var f in swfobject)swfobject[f]=null;swfobject=null})}();return{registerObject:function(a,b,c,d){if(y.w3&&a&&b){var e={};e.id=a,e.swfVersion=b,e.expressInstall=c,e.callbackFn=d,m[m.length]=e,U(a,!1)}else d&&d({success:!1,id:a})},getObjectById:function(a){if(y.w3)return G(a)},embedSWF:function(c,d,e,f,g,h,i,j,k,l){var m={success:!1,id:d};y.w3&&!(y.wk&&y.wk<312)&&c&&d&&e&&f&&g?(U(d,!1),B(function(){e+="",f+="";var n={};if(k&&typeof k===b)for(var o in k)n[o]=k[o];n.data=c,n.width=e,n.height=f;var p={};if(j&&typeof j===b)for(var q in j)p[q]=j[q];if(i&&typeof i===b)for(var r in i)typeof p.flashvars!=a?p.flashvars+="&"+r+"="+i[r]:p.flashvars=r+"="+i[r];if(S(g)){var s=L(n,p,d);n.id==d&&U(d,!0),m.success=!0,m.ref=s}else{if(h&&H()){n.data=h,I(n,p,d,l);return}U(d,!0)}l&&l(m)})):l&&l(m)},switchOffAutoHideShow:function(){x=!1},ua:y,getFlashPlayerVersion:function(){return{major:y.pv[0],minor:y.pv[1],release:y.pv[2]}},hasFlashPlayerVersion:S,createSWF:function(a,b,c){return y.w3?L(a,b,c):undefined},showExpressInstall:function(a,b,c,d){y.w3&&H()&&I(a,b,c,d)},removeSWF:function(a){y.w3&&N(a)},createCSS:function(a,b,c,d){y.w3&&T(a,b,c,d)},addDomLoadEvent:B,addLoadEvent:C,getQueryParamValue:function(a){var b=i.location.search||i.location.hash;if(b){/\?/.test(b)&&(b=b.split("?")[1]);if(a==null)return V(b);var c=b.split("&");for(var d=0;d<c.length;d++)if(c[d].substring(0,c[d].indexOf("="))==a)return V(c[d].substring(c[d].indexOf("=")+1))}return""},expressInstallCallback:function(){if(u){var a=P(f);a&&p&&(a.parentNode.replaceChild(p,a),q&&(U(q,!0),y.ie&&y.win&&(p.style.display="block")),r&&r(s)),u=!1}}}}();(function(){if("undefined"==typeof window||window.WebSocket)return;var a=window.console;if(!a||!a.log||!a.error)a={log:function(){},error:function(){}};if(!swfobject.hasFlashPlayerVersion("10.0.0")){a.error("Flash Player >= 10.0.0 is required.");return}location.protocol=="file:"&&a.error("WARNING: web-socket-js doesn't work in file:///... URL unless you set Flash Security Settings properly. Open the page via Web server i.e. http://..."),WebSocket=function(a,b,c,d,e){var f=this;f.__id=WebSocket.__nextId++,WebSocket.__instances[f.__id]=f,f.readyState=WebSocket.CONNECTING,f.bufferedAmount=0,f.__events={},b?typeof b=="string"&&(b=[b]):b=[],setTimeout(function(){WebSocket.__addTask(function(){WebSocket.__flash.create(f.__id,a,b,c||null,d||0,e||null)})},0)},WebSocket.prototype.send=function(a){if(this.readyState==WebSocket.CONNECTING)throw"INVALID_STATE_ERR: Web Socket connection has not been established";var b=WebSocket.__flash.send(this.__id,encodeURIComponent(a));return b<0?!0:(this.bufferedAmount+=b,!1)},WebSocket.prototype.close=function(){if(this.readyState==WebSocket.CLOSED||this.readyState==WebSocket.CLOSING)return;this.readyState=WebSocket.CLOSING,WebSocket.__flash.close(this.__id)},WebSocket.prototype.addEventListener=function(a,b,c){a in this.__events||(this.__events[a]=[]),this.__events[a].push(b)},WebSocket.prototype.removeEventListener=function(a,b,c){if(!(a in this.__events))return;var d=this.__events[a];for(var e=d.length-1;e>=0;--e)if(d[e]===b){d.splice(e,1);break}},WebSocket.prototype.dispatchEvent=function(a){var b=this.__events[a.type]||[];for(var c=0;c<b.length;++c)b[c](a);var d=this["on"+a.type];d&&d(a)},WebSocket.prototype.__handleEvent=function(a){"readyState"in a&&(this.readyState=a.readyState),"protocol"in a&&(this.protocol=a.protocol);var b;if(a.type=="open"||a.type=="error")b=this.__createSimpleEvent(a.type);else if(a.type=="close")b=this.__createSimpleEvent("close");else{if(a.type!="message")throw"unknown event type: "+a.type;var c=decodeURIComponent(a.message);b=this.__createMessageEvent("message",c)}this.dispatchEvent(b)},WebSocket.prototype.__createSimpleEvent=function(a){if(document.createEvent&&window.Event){var b=document.createEvent("Event");return b.initEvent(a,!1,!1),b}return{type:a,bubbles:!1,cancelable:!1}},WebSocket.prototype.__createMessageEvent=function(a,b){if(document.createEvent&&window.MessageEvent&&!window.opera){var c=document.createEvent("MessageEvent");return c.initMessageEvent("message",!1,!1,b,null,null,window,null),c}return{type:a,data:b,bubbles:!1,cancelable:!1}},WebSocket.CONNECTING=0,WebSocket.OPEN=1,WebSocket.CLOSING=2,WebSocket.CLOSED=3,WebSocket.__flash=null,WebSocket.__instances={},WebSocket.__tasks=[],WebSocket.__nextId=0,WebSocket.loadFlashPolicyFile=function(a){WebSocket.__addTask(function(){WebSocket.__flash.loadManualPolicyFile(a)})},WebSocket.__initialize=function(){if(WebSocket.__flash)return;WebSocket.__swfLocation&&(window.WEB_SOCKET_SWF_LOCATION=WebSocket.__swfLocation);if(!window.WEB_SOCKET_SWF_LOCATION){a.error("[WebSocket] set WEB_SOCKET_SWF_LOCATION to location of WebSocketMain.swf");return}var b=document.createElement("div");b.id="webSocketContainer",b.style.position="absolute",WebSocket.__isFlashLite()?(b.style.left="0px",b.style.top="0px"):(b.style.left="-100px",b.style.top="-100px");var c=document.createElement("div");c.id="webSocketFlash",b.appendChild(c),document.body.appendChild(b),swfobject.embedSWF(WEB_SOCKET_SWF_LOCATION,"webSocketFlash","1","1","10.0.0",null,null,{hasPriority:!0,swliveconnect:!0,allowScriptAccess:"always"},null,function(b){b.success||a.error("[WebSocket] swfobject.embedSWF failed")})},WebSocket.__onFlashInitialized=function(){setTimeout(function(){WebSocket.__flash=document.getElementById("webSocketFlash"),WebSocket.__flash.setCallerUrl(location.href),WebSocket.__flash.setDebug(!!window.WEB_SOCKET_DEBUG);for(var a=0;a<WebSocket.__tasks.length;++a)WebSocket.__tasks[a]();WebSocket.__tasks=[]},0)},WebSocket.__onFlashEvent=function(){return setTimeout(function(){try{var b=WebSocket.__flash.receiveEvents();for(var c=0;c<b.length;++c)WebSocket.__instances[b[c].webSocketId].__handleEvent(b[c])}catch(d){a.error(d)}},0),!0},WebSocket.__log=function(b){a.log(decodeURIComponent(b))},WebSocket.__error=function(b){a.error(decodeURIComponent(b))},WebSocket.__addTask=function(a){WebSocket.__flash?a():WebSocket.__tasks.push(a)},WebSocket.__isFlashLite=function(){if(!window.navigator||!window.navigator.mimeTypes)return!1;var a=window.navigator.mimeTypes["application/x-shockwave-flash"];return!a||!a.enabledPlugin||!a.enabledPlugin.filename?!1:a.enabledPlugin.filename.match(/flashlite/i)?!0:!1},window.WEB_SOCKET_DISABLE_AUTO_INITIALIZATION||(window.addEventListener?window.addEventListener("load",function(){WebSocket.__initialize()},!1):window.attachEvent("onload",function(){WebSocket.__initialize()}))})(),function(a,b,c){function d(a){if(!a)return;b.Transport.apply(this,arguments),this.sendBuffer=[]}function e(){}a.XHR=d,b.util.inherit(d,b.Transport),d.prototype.open=function(){return this.socket.setBuffer(!1),this.onOpen(),this.get(),this.setCloseTimeout(),this},d.prototype.payload=function(a){var c=[];for(var d=0,e=a.length;d<e;d++)c.push(b.parser.encodePacket(a[d]));this.send(b.parser.encodePayload(c))},d.prototype.send=function(a){return this.post(a),this},d.prototype.post=function(a){function d(){this.readyState==4&&(this.onreadystatechange=e,b.posting=!1,this.status==200?b.socket.setBuffer(!1):b.onClose())}function f(){this.onload=e,b.socket.setBuffer(!1)}var b=this;this.socket.setBuffer(!0),this.sendXHR=this.request("POST"),c.XDomainRequest&&this.sendXHR instanceof XDomainRequest?this.sendXHR.onload=this.sendXHR.onerror=f:this.sendXHR.onreadystatechange=d,this.sendXHR.send(a)},d.prototype.close=function(){return this.onClose(),this},d.prototype.request=function(a){var c=b.util.request(this.socket.isXDomain()),d=b.util.query(this.socket.options.query,"t="+ +(new Date));c.open(a||"GET",this.prepareUrl()+d,!0);if(a=="POST")try{c.setRequestHeader?c.setRequestHeader("Content-type","text/plain;charset=UTF-8"):c.contentType="text/plain"}catch(e){}return c},d.prototype.scheme=function(){return this.socket.options.secure?"https":"http"},d.check=function(a,d){try{var e=b.util.request(d),f=c.XDomainRequest&&e instanceof XDomainRequest,g=a&&a.options&&a.options.secure?"https:":"http:",h=c.location&&g!=c.location.protocol;if(e&&(!f||!h))return!0}catch(i){}return!1},d.xdomainCheck=function(a){return d.check(a,!0)}}("undefined"!=typeof io?io.Transport:module.exports,"undefined"!=typeof io?io:module.parent.exports,this),function(a,b){function c(a){b.Transport.XHR.apply(this,arguments)}a.htmlfile=c,b.util.inherit(c,b.Transport.XHR),c.prototype.name="htmlfile",c.prototype.get=function(){this.doc=new(window[["Active"].concat("Object").join("X")])("htmlfile"),this.doc.open(),this.doc.write("<html></html>"),this.doc.close(),this.doc.parentWindow.s=this;var a=this.doc.createElement("div");a.className="socketio",this.doc.body.appendChild(a),this.iframe=this.doc.createElement("iframe"),a.appendChild(this.iframe);var c=this,d=b.util.query(this.socket.options.query,"t="+ +(new Date));this.iframe.src=this.prepareUrl()+d,b.util.on(window,"unload",function(){c.destroy()})},c.prototype._=function(a,b){a=a.replace(/\\\//g,"/"),this.onData(a);try{var c=b.getElementsByTagName("script")[0];c.parentNode.removeChild(c)}catch(d){}},c.prototype.destroy=function(){if(this.iframe){try{this.iframe.src="about:blank"}catch(a){}this.doc=null,this.iframe.parentNode.removeChild(this.iframe),this.iframe=null,CollectGarbage()}},c.prototype.close=function(){return this.destroy(),b.Transport.XHR.prototype.close.call(this)},c.check=function(a){if(typeof window!="undefined"&&["Active"].concat("Object").join("X")in window)try{var c=new(window[["Active"].concat("Object").join("X")])("htmlfile");return c&&b.Transport.XHR.check(a)}catch(d){}return!1},c.xdomainCheck=function(){return!1},b.transports.push("htmlfile")}("undefined"!=typeof io?io.Transport:module.exports,"undefined"!=typeof io?io:module.parent.exports),function(a,b,c){function d(){b.Transport.XHR.apply(this,arguments)}function e(){}a["xhr-polling"]=d,b.util.inherit(d,b.Transport.XHR),b.util.merge(d,b.Transport.XHR),d.prototype.name="xhr-polling",d.prototype.heartbeats=function(){return!1},d.prototype.open=function(){var a=this;return b.Transport.XHR.prototype.open.call(a),!1},d.prototype.get=function(){function b(){this.readyState==4&&(this.onreadystatechange=e,this.status==200?(a.onData(this.responseText),a.get()):a.onClose())}function d(){this.onload=e,this.onerror=e,a.retryCounter=1,a.onData(this.responseText),a.get()}function f(){a.retryCounter++,!a.retryCounter||a.retryCounter>3?a.onClose():a.get()}if(!this.isOpen)return;var a=this;this.xhr=this.request(),c.XDomainRequest&&this.xhr instanceof XDomainRequest?(this.xhr.onload=d,this.xhr.onerror=f):this.xhr.onreadystatechange=b,this.xhr.send(null)},d.prototype.onClose=function(){b.Transport.XHR.prototype.onClose.call(this);if(this.xhr){this.xhr.onreadystatechange=this.xhr.onload=this.xhr.onerror=e;try{this.xhr.abort()}catch(a){}this.xhr=null}},d.prototype.ready=function(a,c){var d=this;b.util.defer(function(){c.call(d)})},b.transports.push("xhr-polling")}("undefined"!=typeof io?io.Transport:module.exports,"undefined"!=typeof io?io:module.parent.exports,this),function(a,b,c){function e(a){b.Transport["xhr-polling"].apply(this,arguments),this.index=b.j.length;var c=this;b.j.push(function(a){c._(a)})}var d=c.document&&"MozAppearance"in c.document.documentElement.style;a["jsonp-polling"]=e,b.util.inherit(e,b.Transport["xhr-polling"]),e.prototype.name="jsonp-polling",e.prototype.post=function(a){function i(){j(),c.socket.setBuffer(!1)}function j(){c.iframe&&c.form.removeChild(c.iframe);try{h=document.createElement('<iframe name="'+c.iframeId+'">')}catch(a){h=document.createElement("iframe"),h.name=c.iframeId}h.id=c.iframeId,c.form.appendChild(h),c.iframe=h}var c=this,d=b.util.query(this.socket.options.query,"t="+ +(new Date)+"&i="+this.index);if(!this.form){var e=document.createElement("form"),f=document.createElement("textarea"),g=this.iframeId="socketio_iframe_"+this.index,h;e.className="socketio",e.style.position="absolute",e.style.top="0px",e.style.left="0px",e.style.display="none",e.target=g,e.method="POST",e.setAttribute("accept-charset","utf-8"),f.name="d",e.appendChild(f),document.body.appendChild(e),this.form=e,this.area=f}this.form.action=this.prepareUrl()+d,j(),this.area.value=b.JSON.stringify(a);try{this.form.submit()}catch(k){}this.iframe.attachEvent?h.onreadystatechange=function(){c.iframe.readyState=="complete"&&i()}:this.iframe.onload=i,this.socket.setBuffer(!0)},e.prototype.get=function(){var a=this,c=document.createElement("script"),e=b.util.query(this.socket.options.query,"t="+ +(new Date)+"&i="+this.index);this.script&&(this.script.parentNode.removeChild(this.script),this.script=null),c.async=!0,c.src=this.prepareUrl()+e,c.onerror=function(){a.onClose()};var f=document.getElementsByTagName("script")[0];f.parentNode.insertBefore(c,f),this.script=c,d&&setTimeout(function(){var a=document.createElement("iframe");document.body.appendChild(a),document.body.removeChild(a)},100)},e.prototype._=function(a){return this.onData(a),this.isOpen&&this.get(),this},e.prototype.ready=function(a,c){var e=this;if(!d)return c.call(this);b.util.load(function(){c.call(e)})},e.check=function(){return"document"in c},e.xdomainCheck=function(){return!0},b.transports.push("jsonp-polling")}("undefined"!=typeof io?io.Transport:module.exports,"undefined"!=typeof io?io:module.parent.exports,this),typeof define=="function"&&define.amd&&define([],function(){return io})})(); | |
/** | |
* sails.io.js | |
* ------------------------------------------------------------------------ | |
* JavaScript Client (SDK) for communicating with Sails. | |
* | |
* Note that this script is completely optional, but it is handy if you're | |
* using WebSockets from the browser to talk to your Sails server. | |
* | |
* For tips and documentation, visit: | |
* http://sailsjs.org/#!documentation/reference/BrowserSDK/BrowserSDK.html | |
* ------------------------------------------------------------------------ | |
* | |
* This file allows you to send and receive socket.io messages to & from Sails | |
* by simulating a REST client interface on top of socket.io. It models its API | |
* after the $.ajax pattern from jQuery you might already be familiar with. | |
* | |
* So if you're switching from using AJAX to sockets, instead of: | |
* `$.post( url, [data], [cb] )` | |
* | |
* You would use: | |
* `socket.post( url, [data], [cb] )` | |
*/ | |
var hostUrl = 'http://localhost:1337'; | |
(function() { | |
// Save the URL that this script was fetched from for use below. | |
// (skip this if this SDK is being used outside of the DOM, i.e. in a Node process) | |
var urlThisScriptWasFetchedFrom = (function() { | |
if ( | |
typeof window !== 'object' || | |
typeof window.document !== 'object' || | |
typeof window.document.getElementsByTagName !== 'function' | |
) { | |
return ''; | |
} | |
// Return the URL of the last script loaded (i.e. this one) | |
// (this must run before nextTick; see http://stackoverflow.com/a/2976714/486547) | |
var allScriptsCurrentlyInDOM = window.document.getElementsByTagName('script'); | |
var thisScript = allScriptsCurrentlyInDOM[allScriptsCurrentlyInDOM.length - 1]; | |
return thisScript.src; | |
})(); | |
// Constants | |
var CONNECTION_METADATA_PARAMS = { | |
version: '__sails_io_sdk_version', | |
platform: '__sails_io_sdk_platform', | |
language: '__sails_io_sdk_language' | |
}; | |
// Current version of this SDK (sailsDK?!?!) and other metadata | |
// that will be sent along w/ the initial connection request. | |
var SDK_INFO = { | |
version: '0.10.5', // TODO: pull this automatically from package.json during build. | |
platform: typeof module === 'undefined' ? 'browser' : 'node', | |
language: 'javascript' | |
}; | |
SDK_INFO.versionString = | |
CONNECTION_METADATA_PARAMS.version + '=' + SDK_INFO.version + '&' + | |
CONNECTION_METADATA_PARAMS.platform + '=' + SDK_INFO.platform + '&' + | |
CONNECTION_METADATA_PARAMS.language + '=' + SDK_INFO.language; | |
// In case you're wrapping the socket.io client to prevent pollution of the | |
// global namespace, you can pass in your own `io` to replace the global one. | |
// But we still grab access to the global one if it's available here: | |
var _io = (typeof io !== 'undefined') ? io : null; | |
/** | |
* Augment the `io` object passed in with methods for talking and listening | |
* to one or more Sails backend(s). Automatically connects a socket and | |
* exposes it on `io.socket`. If a socket tries to make requests before it | |
* is connected, the sails.io.js client will queue it up. | |
* | |
* @param {SocketIO} io | |
*/ | |
function SailsIOClient(io) { | |
// Prefer the passed-in `io` instance, but also use the global one if we've got it. | |
io = io || _io; | |
// If the socket.io client is not available, none of this will work. | |
if (!io) throw new Error('`sails.io.js` requires a socket.io client, but `io` was not passed in.'); | |
////////////////////////////////////////////////////////////// | |
///// /////////////////////////// | |
///// PRIVATE METHODS/CONSTRUCTORS /////////////////////////// | |
///// /////////////////////////// | |
////////////////////////////////////////////////////////////// | |
/** | |
* TmpSocket | |
* | |
* A mock Socket used for binding events before the real thing | |
* has been instantiated (since we need to use io.connect() to | |
* instantiate the real thing, which would kick off the connection | |
* process w/ the server, and we don't necessarily have the valid | |
* configuration to know WHICH SERVER to talk to yet.) | |
* | |
* @api private | |
* @constructor | |
*/ | |
function TmpSocket() { | |
var boundEvents = {}; | |
this.on = function (evName, fn) { | |
if (!boundEvents[evName]) boundEvents[evName] = [fn]; | |
else boundEvents[evName].push(fn); | |
return this; | |
}; | |
this.become = function(actualSocket) { | |
// Pass events and a reference to the request queue | |
// off to the actualSocket for consumption | |
for (var evName in boundEvents) { | |
for (var i in boundEvents[evName]) { | |
actualSocket.on(evName, boundEvents[evName][i]); | |
} | |
} | |
actualSocket.requestQueue = this.requestQueue; | |
// Bind a one-time function to run the request queue | |
// when the actualSocket connects. | |
if (!_isConnected(actualSocket)) { | |
var alreadyRanRequestQueue = false; | |
actualSocket.on('connect', function onActualSocketConnect() { | |
if (alreadyRanRequestQueue) return; | |
runRequestQueue(actualSocket); | |
alreadyRanRequestQueue = true; | |
}); | |
} | |
// Or run it immediately if actualSocket is already connected | |
else { | |
runRequestQueue(actualSocket); | |
} | |
return actualSocket; | |
}; | |
// Uses `this` instead of `TmpSocket.prototype` purely | |
// for convenience, since it makes more sense to attach | |
// our extra methods to the `Socket` prototype down below. | |
// This could be optimized by moving those Socket method defs | |
// to the top of this SDK file instead of the bottom. Will | |
// gladly do it if it is an issue for anyone. | |
this.get = Socket.prototype.get; | |
this.post = Socket.prototype.post; | |
this.put = Socket.prototype.put; | |
this['delete'] = Socket.prototype['delete']; | |
this.request = Socket.prototype.request; | |
this._request = Socket.prototype._request; | |
} | |
/** | |
* A little logger for this library to use internally. | |
* Basically just a wrapper around `console.log` with | |
* support for feature-detection. | |
* | |
* @api private | |
* @factory | |
*/ | |
function LoggerFactory(options) { | |
options = options || { | |
prefix: true | |
}; | |
// If `console.log` is not accessible, `log` is a noop. | |
if ( | |
typeof console !== 'object' || | |
typeof console.log !== 'function' || | |
typeof console.log.bind !== 'function' | |
) { | |
return function noop() {}; | |
} | |
return function log() { | |
var args = Array.prototype.slice.call(arguments); | |
// All logs are disabled when `io.sails.environment = 'production'`. | |
if (io.sails.environment === 'production') return; | |
// Add prefix to log messages (unless disabled) | |
var PREFIX = ''; | |
if (options.prefix) { | |
args.unshift(PREFIX); | |
} | |
// Call wrapped logger | |
console.log | |
.bind(console) | |
.apply(this, args); | |
}; | |
} | |
// Create a private logger instance | |
var consolog = LoggerFactory(); | |
consolog.noPrefix = LoggerFactory({ | |
prefix: false | |
}); | |
/** | |
* _isConnected | |
* | |
* @api private | |
* @param {Socket} socket | |
* @return {Boolean} whether the socket is connected and able to | |
* communicate w/ the server. | |
*/ | |
function _isConnected(socket) { | |
return socket.socket && socket.socket.connected; | |
} | |
/** | |
* What is the `requestQueue`? | |
* | |
* The request queue is used to simplify app-level connection logic-- | |
* i.e. so you don't have to wait for the socket to be connected | |
* to start trying to synchronize data. | |
* | |
* @api private | |
* @param {Socket} socket | |
*/ | |
function runRequestQueue (socket) { | |
var queue = socket.requestQueue; | |
if (!queue) return; | |
for (var i in queue) { | |
// Double-check that `queue[i]` will not | |
// inadvertently discover extra properties attached to the Object | |
// and/or Array prototype by other libraries/frameworks/tools. | |
// (e.g. Ember does this. See https://github.com/balderdashy/sails.io.js/pull/5) | |
var isSafeToDereference = ({}).hasOwnProperty.call(queue, i); | |
if (isSafeToDereference) { | |
// Emit the request. | |
_emitFrom(socket, queue[i]); | |
} | |
} | |
} | |
/** | |
* Send an AJAX request. | |
* | |
* @param {Object} opts [optional] | |
* @param {Function} cb | |
* @return {XMLHttpRequest} | |
*/ | |
function ajax(opts, cb) { | |
opts = opts || {}; | |
var xmlhttp; | |
if (typeof window === 'undefined') { | |
// TODO: refactor node usage to live in here | |
return cb(); | |
} | |
if (window.XMLHttpRequest) { | |
// code for IE7+, Firefox, Chrome, Opera, Safari | |
xmlhttp = new XMLHttpRequest(); | |
} else { | |
// code for IE6, IE5 | |
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); | |
} | |
xmlhttp.onreadystatechange = function() { | |
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { | |
cb(xmlhttp.responseText); | |
} | |
}; | |
xmlhttp.open(opts.method, opts.url, true); | |
xmlhttp.send(); | |
return xmlhttp; | |
} | |
/** | |
* The JWR (JSON WebSocket Response) received from a Sails server. | |
* | |
* @api private | |
* @param {Object} responseCtx | |
* => :body | |
* => :statusCode | |
* => :headers | |
* @constructor | |
*/ | |
function JWR(responseCtx) { | |
this.body = responseCtx.body || {}; | |
this.headers = responseCtx.headers || {}; | |
this.statusCode = responseCtx.statusCode || 200; | |
} | |
JWR.prototype.toString = function() { | |
return '[ResponseFromSails]' + ' -- ' + | |
'Status: ' + this.statusCode + ' -- ' + | |
'Headers: ' + this.headers + ' -- ' + | |
'Body: ' + this.body; | |
}; | |
JWR.prototype.toPOJO = function() { | |
return { | |
body: this.body, | |
headers: this.headers, | |
statusCode: this.statusCode | |
}; | |
}; | |
JWR.prototype.pipe = function() { | |
// TODO: look at substack's stuff | |
return new Error('Not implemented yet.'); | |
}; | |
/** | |
* @api private | |
* @param {Socket} socket [description] | |
* @param {Object} requestCtx [description] | |
*/ | |
function _emitFrom(socket, requestCtx) { | |
// Since callback is embedded in requestCtx, | |
// retrieve it and delete the key before continuing. | |
var cb = requestCtx.cb; | |
delete requestCtx.cb; | |
// Name of socket request listener on the server | |
// ( === the request method, e.g. 'get', 'post', 'put', etc. ) | |
var sailsEndpoint = requestCtx.method; | |
socket.emit(sailsEndpoint, requestCtx, function serverResponded(responseCtx) { | |
// Adds backwards-compatibility for 0.9.x projects | |
// If `responseCtx.body` does not exist, the entire | |
// `responseCtx` object must actually be the `body`. | |
var body; | |
if (!responseCtx.body) { | |
body = responseCtx; | |
} else { | |
body = responseCtx.body; | |
} | |
// Send back (emulatedHTTPBody, jsonWebSocketResponse) | |
if (cb) { | |
cb(JSON.parse(body) || body, new JWR(responseCtx)); | |
} | |
}); | |
} | |
////////////////////////////////////////////////////////////// | |
///// </PRIVATE METHODS/CONSTRUCTORS> //////////////////////// | |
////////////////////////////////////////////////////////////// | |
// We'll be adding methods to `io.SocketNamespace.prototype`, the prototype for the | |
// Socket instance returned when the browser connects with `io.connect()` | |
var Socket = io.SocketNamespace; | |
/** | |
* Simulate a GET request to sails | |
* e.g. | |
* `socket.get('/user/3', Stats.populate)` | |
* | |
* @api public | |
* @param {String} url :: destination URL | |
* @param {Object} params :: parameters to send with the request [optional] | |
* @param {Function} cb :: callback function to call when finished [optional] | |
*/ | |
Socket.prototype.get = function(url, data, cb) { | |
// `data` is optional | |
if (typeof data === 'function') { | |
cb = data; | |
data = {}; | |
} | |
return this._request({ | |
method: 'get', | |
data: data, | |
url: url | |
}, cb); | |
}; | |
/** | |
* Simulate a POST request to sails | |
* e.g. | |
* `socket.post('/event', newMeeting, $spinner.hide)` | |
* | |
* @api public | |
* @param {String} url :: destination URL | |
* @param {Object} params :: parameters to send with the request [optional] | |
* @param {Function} cb :: callback function to call when finished [optional] | |
*/ | |
Socket.prototype.post = function(url, data, cb) { | |
// `data` is optional | |
if (typeof data === 'function') { | |
cb = data; | |
data = {}; | |
} | |
return this._request({ | |
method: 'post', | |
data: data, | |
url: url | |
}, cb); | |
}; | |
/** | |
* Simulate a PUT request to sails | |
* e.g. | |
* `socket.post('/event/3', changedFields, $spinner.hide)` | |
* | |
* @api public | |
* @param {String} url :: destination URL | |
* @param {Object} params :: parameters to send with the request [optional] | |
* @param {Function} cb :: callback function to call when finished [optional] | |
*/ | |
Socket.prototype.put = function(url, data, cb) { | |
// `data` is optional | |
if (typeof data === 'function') { | |
cb = data; | |
data = {}; | |
} | |
return this._request({ | |
method: 'put', | |
data: data, | |
url: url | |
}, cb); | |
}; | |
/** | |
* Simulate a DELETE request to sails | |
* e.g. | |
* `socket.delete('/event', $spinner.hide)` | |
* | |
* @api public | |
* @param {String} url :: destination URL | |
* @param {Object} params :: parameters to send with the request [optional] | |
* @param {Function} cb :: callback function to call when finished [optional] | |
*/ | |
Socket.prototype['delete'] = function(url, data, cb) { | |
// `data` is optional | |
if (typeof data === 'function') { | |
cb = data; | |
data = {}; | |
} | |
return this._request({ | |
method: 'delete', | |
data: data, | |
url: url | |
}, cb); | |
}; | |
/** | |
* Simulate an HTTP request to sails | |
* e.g. | |
* `socket.request('/user', newUser, $spinner.hide, 'post')` | |
* | |
* @api public | |
* @param {String} url :: destination URL | |
* @param {Object} params :: parameters to send with the request [optional] | |
* @param {Function} cb :: callback function to call when finished [optional] | |
* @param {String} method :: HTTP request method [optional] | |
*/ | |
Socket.prototype.request = function(url, data, cb, method) { | |
// `cb` is optional | |
if (typeof cb === 'string') { | |
method = cb; | |
cb = null; | |
} | |
// `data` is optional | |
if (typeof data === 'function') { | |
cb = data; | |
data = {}; | |
} | |
return this._request({ | |
method: method || 'get', | |
data: data, | |
url: url | |
}, cb); | |
}; | |
/** | |
* Socket.prototype._request | |
* | |
* Simulate HTTP over Socket.io. | |
* | |
* @api private | |
* @param {[type]} options [description] | |
* @param {Function} cb [description] | |
*/ | |
Socket.prototype._request = function(options, cb) { | |
// Sanitize options (also data & headers) | |
var usage = 'Usage:\n socket.' + | |
(options.method || 'request') + | |
'( destinationURL, [dataToSend], [fnToCallWhenComplete] )'; | |
options = options || {}; | |
options.data = options.data || {}; | |
options.headers = options.headers || {}; | |
// Remove trailing slashes and spaces to make packets smaller. | |
options.url = options.url.replace(/^(.+)\/*\s*$/, '$1'); | |
if (typeof options.url !== 'string') { | |
throw new Error('Invalid or missing URL!\n' + usage); | |
} | |
// Build a simulated request object. | |
var request = { | |
method: options.method, | |
data: options.data, | |
url: options.url, | |
headers: options.headers, | |
cb: cb | |
}; | |
// If this socket is not connected yet, queue up this request | |
// instead of sending it. | |
// (so it can be replayed when the socket comes online.) | |
if (!_isConnected(this)) { | |
// If no queue array exists for this socket yet, create it. | |
this.requestQueue = this.requestQueue || []; | |
this.requestQueue.push(request); | |
return; | |
} | |
// Otherwise, our socket is ok! | |
// Send the request. | |
_emitFrom(this, request); | |
}; | |
// Set a `sails` object that may be used for configuration before the | |
// first socket connects (i.e. to prevent auto-connect) | |
io.sails = { | |
// Whether to automatically connect a socket and save it as `io.socket`. | |
autoConnect: true, | |
url: hostUrl, | |
// Whether to use JSONP to get a cookie for cross-origin requests | |
useCORSRouteToGetCookie: true, | |
// The environment we're running in. | |
// (logs are not displayed when this is set to 'production') | |
// | |
// Defaults to development unless this script was fetched from a URL | |
// that ends in `*.min.js` or '#production' (may also be manually overridden.) | |
// | |
environment: urlThisScriptWasFetchedFrom.match(/(\#production|\.min\.js)/) ? 'production' : 'development' | |
}; | |
/** | |
* Override `io.connect` to coerce it into using the io.sails | |
* connection URL config, as well as sending identifying information | |
* (most importantly, the current version of this SDK) | |
* | |
* @param {String} url [optional] | |
* @param {Object} opts [optional] | |
* @return {Socket} | |
*/ | |
io.sails._origConnectFn = io.connect; | |
io.connect = function(url, opts) { | |
opts = opts || {}; | |
// If explicit connection url is specified, use it | |
url = url || io.sails.url || undefined; | |
// Ensure URL has no trailing slash | |
url = url ? url.replace(/(\/)$/, '') : undefined; | |
// Mix the current SDK version into the query string in | |
// the connection request to the server: | |
if (typeof opts.query !== 'string') opts.query = SDK_INFO.versionString; | |
else opts.query += '&' + SDK_INFO.versionString; | |
return io.sails._origConnectFn(url, opts); | |
}; | |
// io.socket | |
// | |
// The eager instance of Socket which will automatically try to connect | |
// using the host that this js file was served from. | |
// | |
// This can be disabled or configured by setting `io.socket.options` within the | |
// first cycle of the event loop. | |
// | |
// In the mean time, this eager socket will be defined as a TmpSocket | |
// so that events bound by the user before the first cycle of the event | |
// loop (using `.on()`) can be rebound on the true socket. | |
io.socket = new TmpSocket(); | |
setTimeout(function() { | |
// If autoConnect is disabled, delete the TmpSocket and bail out. | |
if (!io.sails.autoConnect) { | |
delete io.socket; | |
return io; | |
} | |
// If this is an attempt at a cross-origin or cross-port | |
// socket connection, send an AJAX request first to ensure | |
// that a valid cookie is available. This can be disabled | |
// by setting `io.sails.useCORSRouteToGetCookie` to false. | |
var isXOrigin = io.sails.url && true; //url.match(); | |
// TODO: check whether the URL is cross-domain | |
// var port = global.location.port || ('https:' == global.location.protocol ? 443 : 80); | |
// this.options.host !== global.location.hostname || this.options.port != port; | |
if (io.sails.useCORSRouteToGetCookie && isXOrigin) { | |
// Figure out the x-origin CORS route | |
// (Sails provides a default) | |
var xOriginCookieRoute = '/__getcookie'; | |
if (typeof io.sails.useCORSRouteToGetCookie === 'string') { | |
xOriginCookieRoute = io.sails.useCORSRouteToGetCookie; | |
} | |
var xOriginCookieURL = io.sails.url + xOriginCookieRoute; | |
// Make the AJAX request (CORS) | |
if (typeof window !== 'undefined') { | |
ajax({ | |
url: xOriginCookieURL, | |
method: 'GET' | |
}, goAheadAndActuallyConnect); | |
} | |
// If there's no `window` object, we must be running in Node.js | |
// so just require the request module and send the HTTP request that | |
// way. | |
else { | |
var mikealsReq = require('request'); | |
mikealsReq.get(io.sails.url + xOriginCookieRoute, function(err, httpResponse, body) { | |
if (err) { | |
consolog( | |
'Failed to connect socket (failed to get cookie)', | |
'Error:', err | |
); | |
return; | |
} | |
goAheadAndActuallyConnect(); | |
}); | |
} | |
} else goAheadAndActuallyConnect(); | |
// Start connecting after the current cycle of the event loop | |
// has completed. | |
// consolog('Auto-connecting `io.socket` to Sails... (requests will be queued in the mean-time)'); | |
function goAheadAndActuallyConnect() { | |
// Initiate connection | |
var actualSocket = io.connect(io.sails.url); | |
// Replay event bindings from the existing TmpSocket | |
io.socket = io.socket.become(actualSocket); | |
/** | |
* 'connect' event is triggered when the socket establishes a connection | |
* successfully. | |
*/ | |
io.socket.on('connect', function socketConnected() { | |
consolog.noPrefix( | |
'\n' + | |
' |> ' + '\n' + | |
' \\___/ ' | |
); | |
consolog( | |
'`io.socket` connected successfully.' + '\n' + | |
// 'e.g. to send a GET request to Sails via WebSockets, run:'+ '\n' + | |
// '`io.socket.get("/foo", function serverRespondedWith (body, jwr) { console.log(body); })`'+ '\n' + | |
' (for help, see: http://sailsjs.org/#!documentation/reference/BrowserSDK/BrowserSDK.html)' | |
); | |
// consolog('(this app is running in development mode - log messages will be displayed)'); | |
if (!io.socket.$events.disconnect) { | |
io.socket.on('disconnect', function() { | |
consolog('===================================='); | |
consolog('io.socket was disconnected from Sails.'); | |
consolog('Usually, this is due to one of the following reasons:' + '\n' + | |
' -> the server ' + (io.sails.url ? io.sails.url + ' ' : '') + 'was taken down' + '\n' + | |
' -> your browser lost internet connectivity'); | |
consolog('===================================='); | |
}); | |
} | |
if (!io.socket.$events.reconnect) { | |
io.socket.on('reconnect', function(transport, numAttempts) { | |
var numSecsOffline = io.socket.msSinceConnectionLost / 1000; | |
consolog( | |
'io.socket reconnected successfully after being offline ' + | |
'for ' + numSecsOffline + ' seconds.'); | |
}); | |
} | |
if (!io.socket.$events.reconnecting) { | |
io.socket.on('reconnecting', function(msSinceConnectionLost, numAttempts) { | |
io.socket.msSinceConnectionLost = msSinceConnectionLost; | |
consolog( | |
'io.socket is trying to reconnect to Sails...' + | |
'(attempt #' + numAttempts + ')'); | |
}); | |
} | |
// 'error' event is triggered if connection can not be established. | |
// (usually because of a failed authorization, which is in turn | |
// usually due to a missing or invalid cookie) | |
if (!io.socket.$events.error) { | |
io.socket.on('error', function failedToConnect(err) { | |
// TODO: | |
// handle failed connections due to failed authorization | |
// in a smarter way (probably can listen for a different event) | |
// A bug in Socket.io 0.9.x causes `connect_failed` | |
// and `reconnect_failed` not to fire. | |
// Check out the discussion in github issues for details: | |
// https://github.com/LearnBoost/socket.io/issues/652 | |
// io.socket.on('connect_failed', function () { | |
// consolog('io.socket emitted `connect_failed`'); | |
// }); | |
// io.socket.on('reconnect_failed', function () { | |
// consolog('io.socket emitted `reconnect_failed`'); | |
// }); | |
consolog( | |
'Failed to connect socket (probably due to failed authorization on server)', | |
'Error:', err | |
); | |
}); | |
} | |
}); | |
} | |
// TODO: | |
// Listen for a special private message on any connected that allows the server | |
// to set the environment (giving us 100% certainty that we guessed right) | |
// However, note that the `console.log`s called before and after connection | |
// are still forced to rely on our existing heuristics (to disable, tack #production | |
// onto the URL used to fetch this file.) | |
}, 0); // </setTimeout> | |
// Return the `io` object. | |
return io; | |
} | |
// Add CommonJS support to allow this client SDK to be used from Node.js. | |
if (typeof module === 'object' && typeof module.exports !== 'undefined') { | |
module.exports = SailsIOClient; | |
return SailsIOClient; | |
} | |
// Otherwise, try to instantiate the client: | |
// In case you're wrapping the socket.io client to prevent pollution of the | |
// global namespace, you can replace the global `io` with your own `io` here: | |
return SailsIOClient(); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment