socket.io.js 140 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569
  1. /*! Socket.IO.js build:0.9.17, development. Copyright(c) 2011 LearnBoost <dev@learnboost.com> MIT Licensed */
  2. var io = ('undefined' === typeof module ? {} : module.exports);
  3. (function () {
  4. /**
  5. * socket.io
  6. * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
  7. * MIT Licensed
  8. */
  9. (function (exports, global) {
  10. /**
  11. * IO namespace.
  12. *
  13. * @namespace
  14. */
  15. var io = exports;
  16. /**
  17. * Socket.IO version
  18. *
  19. * @api public
  20. */
  21. io.version = '0.9.17';
  22. /**
  23. * Protocol implemented.
  24. *
  25. * @api public
  26. */
  27. io.protocol = 1;
  28. /**
  29. * Available transports, these will be populated with the available transports
  30. *
  31. * @api public
  32. */
  33. io.transports = [];
  34. /**
  35. * Keep track of jsonp callbacks.
  36. *
  37. * @api private
  38. */
  39. io.j = [];
  40. /**
  41. * Keep track of our io.Sockets
  42. *
  43. * @api private
  44. */
  45. io.sockets = {};
  46. /**
  47. * Manages connections to hosts.
  48. *
  49. * @param {String} uri
  50. * @Param {Boolean} force creation of new socket (defaults to false)
  51. * @api public
  52. */
  53. io.connect = function (host, details) {
  54. var uri = io.util.parseUri(host)
  55. , uuri
  56. , socket;
  57. if (global && global.location) {
  58. uri.protocol = uri.protocol || global.location.protocol.slice(0, -1);
  59. uri.host = uri.host || (global.document
  60. ? global.document.domain : global.location.hostname);
  61. uri.port = uri.port || global.location.port;
  62. }
  63. uuri = io.util.uniqueUri(uri);
  64. var options = {
  65. host: uri.host
  66. , secure: 'https' == uri.protocol
  67. , port: uri.port || ('https' == uri.protocol ? 443 : 80)
  68. , query: uri.query || ''
  69. };
  70. io.util.merge(options, details);
  71. if (options['force new connection'] || !io.sockets[uuri]) {
  72. socket = new io.Socket(options);
  73. }
  74. if (!options['force new connection'] && socket) {
  75. io.sockets[uuri] = socket;
  76. }
  77. socket = socket || io.sockets[uuri];
  78. // if path is different from '' or /
  79. return socket.of(uri.path.length > 1 ? uri.path : '');
  80. };
  81. })('object' === typeof module ? module.exports : (this.io = {}), this);
  82. /**
  83. * socket.io
  84. * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
  85. * MIT Licensed
  86. */
  87. (function (exports, global) {
  88. /**
  89. * Utilities namespace.
  90. *
  91. * @namespace
  92. */
  93. var util = exports.util = {};
  94. /**
  95. * Parses an URI
  96. *
  97. * @author Steven Levithan <stevenlevithan.com> (MIT license)
  98. * @api public
  99. */
  100. var re = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
  101. var parts = ['source', 'protocol', 'authority', 'userInfo', 'user', 'password',
  102. 'host', 'port', 'relative', 'path', 'directory', 'file', 'query',
  103. 'anchor'];
  104. util.parseUri = function (str) {
  105. var m = re.exec(str || '')
  106. , uri = {}
  107. , i = 14;
  108. while (i--) {
  109. uri[parts[i]] = m[i] || '';
  110. }
  111. return uri;
  112. };
  113. /**
  114. * Produces a unique url that identifies a Socket.IO connection.
  115. *
  116. * @param {Object} uri
  117. * @api public
  118. */
  119. util.uniqueUri = function (uri) {
  120. var protocol = uri.protocol
  121. , host = uri.host
  122. , port = uri.port;
  123. if ('document' in global) {
  124. host = host || document.domain;
  125. port = port || (protocol == 'https'
  126. && document.location.protocol !== 'https:' ? 443 : document.location.port);
  127. } else {
  128. host = host || 'localhost';
  129. if (!port && protocol == 'https') {
  130. port = 443;
  131. }
  132. }
  133. return (protocol || 'http') + '://' + host + ':' + (port || 80);
  134. };
  135. /**
  136. * Mergest 2 query strings in to once unique query string
  137. *
  138. * @param {String} base
  139. * @param {String} addition
  140. * @api public
  141. */
  142. util.query = function (base, addition) {
  143. var query = util.chunkQuery(base || '')
  144. , components = [];
  145. util.merge(query, util.chunkQuery(addition || ''));
  146. for (var part in query) {
  147. if (query.hasOwnProperty(part)) {
  148. components.push(part + '=' + query[part]);
  149. }
  150. }
  151. return components.length ? '?' + components.join('&') : '';
  152. };
  153. /**
  154. * Transforms a querystring in to an object
  155. *
  156. * @param {String} qs
  157. * @api public
  158. */
  159. util.chunkQuery = function (qs) {
  160. var query = {}
  161. , params = qs.split('&')
  162. , i = 0
  163. , l = params.length
  164. , kv;
  165. for (; i < l; ++i) {
  166. kv = params[i].split('=');
  167. if (kv[0]) {
  168. query[kv[0]] = kv[1];
  169. }
  170. }
  171. return query;
  172. };
  173. /**
  174. * Executes the given function when the page is loaded.
  175. *
  176. * io.util.load(function () { console.log('page loaded'); });
  177. *
  178. * @param {Function} fn
  179. * @api public
  180. */
  181. var pageLoaded = false;
  182. util.load = function (fn) {
  183. if ('document' in global && document.readyState === 'complete' || pageLoaded) {
  184. return fn();
  185. }
  186. util.on(global, 'load', fn, false);
  187. };
  188. /**
  189. * Adds an event.
  190. *
  191. * @api private
  192. */
  193. util.on = function (element, event, fn, capture) {
  194. if (element.attachEvent) {
  195. element.attachEvent('on' + event, fn);
  196. } else if (element.addEventListener) {
  197. element.addEventListener(event, fn, capture);
  198. }
  199. };
  200. /**
  201. * Generates the correct `XMLHttpRequest` for regular and cross domain requests.
  202. *
  203. * @param {Boolean} [xdomain] Create a request that can be used cross domain.
  204. * @returns {XMLHttpRequest|false} If we can create a XMLHttpRequest.
  205. * @api private
  206. */
  207. util.request = function (xdomain) {
  208. if (xdomain && 'undefined' != typeof XDomainRequest && !util.ua.hasCORS) {
  209. return new XDomainRequest();
  210. }
  211. if ('undefined' != typeof XMLHttpRequest && (!xdomain || util.ua.hasCORS)) {
  212. return new XMLHttpRequest();
  213. }
  214. if (!xdomain) {
  215. try {
  216. return new window[(['Active'].concat('Object').join('X'))]('Microsoft.XMLHTTP');
  217. } catch (e) {
  218. }
  219. }
  220. return null;
  221. };
  222. /**
  223. * XHR based transport constructor.
  224. *
  225. * @constructor
  226. * @api public
  227. */
  228. /**
  229. * Change the internal pageLoaded value.
  230. */
  231. if ('undefined' != typeof window) {
  232. util.load(function () {
  233. pageLoaded = true;
  234. });
  235. }
  236. /**
  237. * Defers a function to ensure a spinner is not displayed by the browser
  238. *
  239. * @param {Function} fn
  240. * @api public
  241. */
  242. util.defer = function (fn) {
  243. if (!util.ua.webkit || 'undefined' != typeof importScripts) {
  244. return fn();
  245. }
  246. util.load(function () {
  247. setTimeout(fn, 100);
  248. });
  249. };
  250. /**
  251. * Merges two objects.
  252. *
  253. * @api public
  254. */
  255. util.merge = function merge(target, additional, deep, lastseen) {
  256. var seen = lastseen || []
  257. , depth = typeof deep == 'undefined' ? 2 : deep
  258. , prop;
  259. for (prop in additional) {
  260. if (additional.hasOwnProperty(prop) && util.indexOf(seen, prop) < 0) {
  261. if (typeof target[prop] !== 'object' || !depth) {
  262. target[prop] = additional[prop];
  263. seen.push(additional[prop]);
  264. } else {
  265. util.merge(target[prop], additional[prop], depth - 1, seen);
  266. }
  267. }
  268. }
  269. return target;
  270. };
  271. /**
  272. * Merges prototypes from objects
  273. *
  274. * @api public
  275. */
  276. util.mixin = function (ctor, ctor2) {
  277. util.merge(ctor.prototype, ctor2.prototype);
  278. };
  279. /**
  280. * Shortcut for prototypical and static inheritance.
  281. *
  282. * @api private
  283. */
  284. util.inherit = function (ctor, ctor2) {
  285. function f() {
  286. };
  287. f.prototype = ctor2.prototype;
  288. ctor.prototype = new f;
  289. };
  290. /**
  291. * Checks if the given object is an Array.
  292. *
  293. * io.util.isArray([]); // true
  294. * io.util.isArray({}); // false
  295. *
  296. * @param Object obj
  297. * @api public
  298. */
  299. util.isArray = Array.isArray || function (obj) {
  300. return Object.prototype.toString.call(obj) === '[object Array]';
  301. };
  302. /**
  303. * Intersects values of two arrays into a third
  304. *
  305. * @api public
  306. */
  307. util.intersect = function (arr, arr2) {
  308. var ret = []
  309. , longest = arr.length > arr2.length ? arr : arr2
  310. , shortest = arr.length > arr2.length ? arr2 : arr;
  311. for (var i = 0, l = shortest.length; i < l; i++) {
  312. if (~util.indexOf(longest, shortest[i]))
  313. ret.push(shortest[i]);
  314. }
  315. return ret;
  316. };
  317. /**
  318. * Array indexOf compatibility.
  319. *
  320. * @see bit.ly/a5Dxa2
  321. * @api public
  322. */
  323. util.indexOf = function (arr, o, i) {
  324. for (var j = arr.length, i = i < 0 ? i + j < 0 ? 0 : i + j : i || 0;
  325. i < j && arr[i] !== o; i++) {
  326. }
  327. return j <= i ? -1 : i;
  328. };
  329. /**
  330. * Converts enumerables to array.
  331. *
  332. * @api public
  333. */
  334. util.toArray = function (enu) {
  335. var arr = [];
  336. for (var i = 0, l = enu.length; i < l; i++)
  337. arr.push(enu[i]);
  338. return arr;
  339. };
  340. /**
  341. * UA / engines detection namespace.
  342. *
  343. * @namespace
  344. */
  345. util.ua = {};
  346. /**
  347. * Whether the UA supports CORS for XHR.
  348. *
  349. * @api public
  350. */
  351. util.ua.hasCORS = 'undefined' != typeof XMLHttpRequest && (function () {
  352. try {
  353. var a = new XMLHttpRequest();
  354. } catch (e) {
  355. return false;
  356. }
  357. return a.withCredentials != undefined;
  358. })();
  359. /**
  360. * Detect webkit.
  361. *
  362. * @api public
  363. */
  364. util.ua.webkit = 'undefined' != typeof navigator
  365. && /webkit/i.test(navigator.userAgent);
  366. /**
  367. * Detect iPad/iPhone/iPod.
  368. *
  369. * @api public
  370. */
  371. util.ua.iDevice = 'undefined' != typeof navigator
  372. && /iPad|iPhone|iPod/i.test(navigator.userAgent);
  373. })('undefined' != typeof io ? io : module.exports, this);
  374. /**
  375. * socket.io
  376. * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
  377. * MIT Licensed
  378. */
  379. (function (exports, io) {
  380. /**
  381. * Expose constructor.
  382. */
  383. exports.EventEmitter = EventEmitter;
  384. /**
  385. * Event emitter constructor.
  386. *
  387. * @api public.
  388. */
  389. function EventEmitter() {
  390. };
  391. /**
  392. * Adds a listener
  393. *
  394. * @api public
  395. */
  396. EventEmitter.prototype.on = function (name, fn) {
  397. if (!this.$events) {
  398. this.$events = {};
  399. }
  400. if (!this.$events[name]) {
  401. this.$events[name] = fn;
  402. } else if (io.util.isArray(this.$events[name])) {
  403. this.$events[name].push(fn);
  404. } else {
  405. this.$events[name] = [this.$events[name], fn];
  406. }
  407. return this;
  408. };
  409. EventEmitter.prototype.addListener = EventEmitter.prototype.on;
  410. /**
  411. * Adds a volatile listener.
  412. *
  413. * @api public
  414. */
  415. EventEmitter.prototype.once = function (name, fn) {
  416. var self = this;
  417. function on() {
  418. self.removeListener(name, on);
  419. fn.apply(this, arguments);
  420. };
  421. on.listener = fn;
  422. this.on(name, on);
  423. return this;
  424. };
  425. /**
  426. * Removes a listener.
  427. *
  428. * @api public
  429. */
  430. EventEmitter.prototype.removeListener = function (name, fn) {
  431. if (this.$events && this.$events[name]) {
  432. var list = this.$events[name];
  433. if (io.util.isArray(list)) {
  434. var pos = -1;
  435. for (var i = 0, l = list.length; i < l; i++) {
  436. if (list[i] === fn || (list[i].listener && list[i].listener === fn)) {
  437. pos = i;
  438. break;
  439. }
  440. }
  441. if (pos < 0) {
  442. return this;
  443. }
  444. list.splice(pos, 1);
  445. if (!list.length) {
  446. delete this.$events[name];
  447. }
  448. } else if (list === fn || (list.listener && list.listener === fn)) {
  449. delete this.$events[name];
  450. }
  451. }
  452. return this;
  453. };
  454. /**
  455. * Removes all listeners for an event.
  456. *
  457. * @api public
  458. */
  459. EventEmitter.prototype.removeAllListeners = function (name) {
  460. if (name === undefined) {
  461. this.$events = {};
  462. return this;
  463. }
  464. if (this.$events && this.$events[name]) {
  465. this.$events[name] = null;
  466. }
  467. return this;
  468. };
  469. /**
  470. * Gets all listeners for a certain event.
  471. *
  472. * @api publci
  473. */
  474. EventEmitter.prototype.listeners = function (name) {
  475. if (!this.$events) {
  476. this.$events = {};
  477. }
  478. if (!this.$events[name]) {
  479. this.$events[name] = [];
  480. }
  481. if (!io.util.isArray(this.$events[name])) {
  482. this.$events[name] = [this.$events[name]];
  483. }
  484. return this.$events[name];
  485. };
  486. /**
  487. * Emits an event.
  488. *
  489. * @api public
  490. */
  491. EventEmitter.prototype.emit = function (name) {
  492. if (!this.$events) {
  493. return false;
  494. }
  495. var handler = this.$events[name];
  496. if (!handler) {
  497. return false;
  498. }
  499. var args = Array.prototype.slice.call(arguments, 1);
  500. if ('function' == typeof handler) {
  501. handler.apply(this, args);
  502. } else if (io.util.isArray(handler)) {
  503. var listeners = handler.slice();
  504. for (var i = 0, l = listeners.length; i < l; i++) {
  505. listeners[i].apply(this, args);
  506. }
  507. } else {
  508. return false;
  509. }
  510. return true;
  511. };
  512. })(
  513. 'undefined' != typeof io ? io : module.exports
  514. , 'undefined' != typeof io ? io : module.parent.exports
  515. );
  516. /**
  517. * socket.io
  518. * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
  519. * MIT Licensed
  520. */
  521. /**
  522. * Based on JSON2 (http://www.JSON.org/js.html).
  523. */
  524. (function (exports, nativeJSON) {
  525. "use strict";
  526. // use native JSON if it's available
  527. if (nativeJSON && nativeJSON.parse) {
  528. return exports.JSON = {
  529. parse: nativeJSON.parse
  530. , stringify: nativeJSON.stringify
  531. };
  532. }
  533. var JSON = exports.JSON = {};
  534. function f(n) {
  535. // Format integers to have at least two digits.
  536. return n < 10 ? '0' + n : n;
  537. }
  538. function date(d, key) {
  539. return isFinite(d.valueOf()) ?
  540. d.getUTCFullYear() + '-' +
  541. f(d.getUTCMonth() + 1) + '-' +
  542. f(d.getUTCDate()) + 'T' +
  543. f(d.getUTCHours()) + ':' +
  544. f(d.getUTCMinutes()) + ':' +
  545. f(d.getUTCSeconds()) + 'Z' : null;
  546. };
  547. var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
  548. escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
  549. gap,
  550. indent,
  551. meta = { // table of character substitutions
  552. '\b': '\\b',
  553. '\t': '\\t',
  554. '\n': '\\n',
  555. '\f': '\\f',
  556. '\r': '\\r',
  557. '"': '\\"',
  558. '\\': '\\\\'
  559. },
  560. rep;
  561. function quote(string) {
  562. // If the string contains no control characters, no quote characters, and no
  563. // backslash characters, then we can safely slap some quotes around it.
  564. // Otherwise we must also replace the offending characters with safe escape
  565. // sequences.
  566. escapable.lastIndex = 0;
  567. return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
  568. var c = meta[a];
  569. return typeof c === 'string' ? c :
  570. '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
  571. }) + '"' : '"' + string + '"';
  572. }
  573. function str(key, holder) {
  574. // Produce a string from holder[key].
  575. var i, // The loop counter.
  576. k, // The member key.
  577. v, // The member value.
  578. length,
  579. mind = gap,
  580. partial,
  581. value = holder[key];
  582. // If the value has a toJSON method, call it to obtain a replacement value.
  583. if (value instanceof Date) {
  584. value = date(key);
  585. }
  586. // If we were called with a replacer function, then call the replacer to
  587. // obtain a replacement value.
  588. if (typeof rep === 'function') {
  589. value = rep.call(holder, key, value);
  590. }
  591. // What happens next depends on the value's type.
  592. switch (typeof value) {
  593. case 'string':
  594. return quote(value);
  595. case 'number':
  596. // JSON numbers must be finite. Encode non-finite numbers as null.
  597. return isFinite(value) ? String(value) : 'null';
  598. case 'boolean':
  599. case 'null':
  600. // If the value is a boolean or null, convert it to a string. Note:
  601. // typeof null does not produce 'null'. The case is included here in
  602. // the remote chance that this gets fixed someday.
  603. return String(value);
  604. // If the type is 'object', we might be dealing with an object or an array or
  605. // null.
  606. case 'object':
  607. // Due to a specification blunder in ECMAScript, typeof null is 'object',
  608. // so watch out for that case.
  609. if (!value) {
  610. return 'null';
  611. }
  612. // Make an array to hold the partial results of stringifying this object value.
  613. gap += indent;
  614. partial = [];
  615. // Is the value an array?
  616. if (Object.prototype.toString.apply(value) === '[object Array]') {
  617. // The value is an array. Stringify every element. Use null as a placeholder
  618. // for non-JSON values.
  619. length = value.length;
  620. for (i = 0; i < length; i += 1) {
  621. partial[i] = str(i, value) || 'null';
  622. }
  623. // Join all of the elements together, separated with commas, and wrap them in
  624. // brackets.
  625. v = partial.length === 0 ? '[]' : gap ?
  626. '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
  627. '[' + partial.join(',') + ']';
  628. gap = mind;
  629. return v;
  630. }
  631. // If the replacer is an array, use it to select the members to be stringified.
  632. if (rep && typeof rep === 'object') {
  633. length = rep.length;
  634. for (i = 0; i < length; i += 1) {
  635. if (typeof rep[i] === 'string') {
  636. k = rep[i];
  637. v = str(k, value);
  638. if (v) {
  639. partial.push(quote(k) + (gap ? ': ' : ':') + v);
  640. }
  641. }
  642. }
  643. } else {
  644. // Otherwise, iterate through all of the keys in the object.
  645. for (k in value) {
  646. if (Object.prototype.hasOwnProperty.call(value, k)) {
  647. v = str(k, value);
  648. if (v) {
  649. partial.push(quote(k) + (gap ? ': ' : ':') + v);
  650. }
  651. }
  652. }
  653. }
  654. // Join all of the member texts together, separated with commas,
  655. // and wrap them in braces.
  656. v = partial.length === 0 ? '{}' : gap ?
  657. '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
  658. '{' + partial.join(',') + '}';
  659. gap = mind;
  660. return v;
  661. }
  662. }
  663. // If the JSON object does not yet have a stringify method, give it one.
  664. JSON.stringify = function (value, replacer, space) {
  665. // The stringify method takes a value and an optional replacer, and an optional
  666. // space parameter, and returns a JSON text. The replacer can be a function
  667. // that can replace values, or an array of strings that will select the keys.
  668. // A default replacer method can be provided. Use of the space parameter can
  669. // produce text that is more easily readable.
  670. var i;
  671. gap = '';
  672. indent = '';
  673. // If the space parameter is a number, make an indent string containing that
  674. // many spaces.
  675. if (typeof space === 'number') {
  676. for (i = 0; i < space; i += 1) {
  677. indent += ' ';
  678. }
  679. // If the space parameter is a string, it will be used as the indent string.
  680. } else if (typeof space === 'string') {
  681. indent = space;
  682. }
  683. // If there is a replacer, it must be a function or an array.
  684. // Otherwise, throw an error.
  685. rep = replacer;
  686. if (replacer && typeof replacer !== 'function' &&
  687. (typeof replacer !== 'object' ||
  688. typeof replacer.length !== 'number')) {
  689. throw new Error('JSON.stringify');
  690. }
  691. // Make a fake root object containing our value under the key of ''.
  692. // Return the result of stringifying the value.
  693. return str('', {'': value});
  694. };
  695. // If the JSON object does not yet have a parse method, give it one.
  696. JSON.parse = function (text, reviver) {
  697. // The parse method takes a text and an optional reviver function, and returns
  698. // a JavaScript value if the text is a valid JSON text.
  699. var j;
  700. function walk(holder, key) {
  701. // The walk method is used to recursively walk the resulting structure so
  702. // that modifications can be made.
  703. var k, v, value = holder[key];
  704. if (value && typeof value === 'object') {
  705. for (k in value) {
  706. if (Object.prototype.hasOwnProperty.call(value, k)) {
  707. v = walk(value, k);
  708. if (v !== undefined) {
  709. value[k] = v;
  710. } else {
  711. delete value[k];
  712. }
  713. }
  714. }
  715. }
  716. return reviver.call(holder, key, value);
  717. }
  718. // Parsing happens in four stages. In the first stage, we replace certain
  719. // Unicode characters with escape sequences. JavaScript handles many characters
  720. // incorrectly, either silently deleting them, or treating them as line endings.
  721. text = String(text);
  722. cx.lastIndex = 0;
  723. if (cx.test(text)) {
  724. text = text.replace(cx, function (a) {
  725. return '\\u' +
  726. ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
  727. });
  728. }
  729. // In the second stage, we run the text against regular expressions that look
  730. // for non-JSON patterns. We are especially concerned with '()' and 'new'
  731. // because they can cause invocation, and '=' because it can cause mutation.
  732. // But just to be safe, we want to reject all unexpected forms.
  733. // We split the second stage into 4 regexp operations in order to work around
  734. // crippling inefficiencies in IE's and Safari's regexp engines. First we
  735. // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
  736. // replace all simple value tokens with ']' characters. Third, we delete all
  737. // open brackets that follow a colon or comma or that begin the text. Finally,
  738. // we look to see that the remaining characters are only whitespace or ']' or
  739. // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
  740. if (/^[\],:{}\s]*$/
  741. .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
  742. .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
  743. .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
  744. // In the third stage we use the eval function to compile the text into a
  745. // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
  746. // in JavaScript: it can begin a block or an object literal. We wrap the text
  747. // in parens to eliminate the ambiguity.
  748. j = eval('(' + text + ')');
  749. // In the optional fourth stage, we recursively walk the new structure, passing
  750. // each name/value pair to a reviver function for possible transformation.
  751. return typeof reviver === 'function' ?
  752. walk({'': j}, '') : j;
  753. }
  754. // If the text is not JSON parseable, then a SyntaxError is thrown.
  755. throw new SyntaxError('JSON.parse');
  756. };
  757. })(
  758. 'undefined' != typeof io ? io : module.exports
  759. , typeof JSON !== 'undefined' ? JSON : undefined
  760. );
  761. /**
  762. * socket.io
  763. * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
  764. * MIT Licensed
  765. */
  766. (function (exports, io) {
  767. /**
  768. * Parser namespace.
  769. *
  770. * @namespace
  771. */
  772. var parser = exports.parser = {};
  773. /**
  774. * Packet types.
  775. */
  776. var packets = parser.packets = [
  777. 'disconnect'
  778. , 'connect'
  779. , 'heartbeat'
  780. , 'message'
  781. , 'json'
  782. , 'event'
  783. , 'ack'
  784. , 'error'
  785. , 'noop'
  786. ];
  787. /**
  788. * Errors reasons.
  789. */
  790. var reasons = parser.reasons = [
  791. 'transport not supported'
  792. , 'client not handshaken'
  793. , 'unauthorized'
  794. ];
  795. /**
  796. * Errors advice.
  797. */
  798. var advice = parser.advice = [
  799. 'reconnect'
  800. ];
  801. /**
  802. * Shortcuts.
  803. */
  804. var JSON = io.JSON
  805. , indexOf = io.util.indexOf;
  806. /**
  807. * Encodes a packet.
  808. *
  809. * @api private
  810. */
  811. parser.encodePacket = function (packet) {
  812. var type = indexOf(packets, packet.type)
  813. , id = packet.id || ''
  814. , endpoint = packet.endpoint || ''
  815. , ack = packet.ack
  816. , data = null;
  817. switch (packet.type) {
  818. case 'error':
  819. var reason = packet.reason ? indexOf(reasons, packet.reason) : ''
  820. , adv = packet.advice ? indexOf(advice, packet.advice) : '';
  821. if (reason !== '' || adv !== '')
  822. data = reason + (adv !== '' ? ('+' + adv) : '');
  823. break;
  824. case 'message':
  825. if (packet.data !== '')
  826. data = packet.data;
  827. break;
  828. case 'event':
  829. var ev = {name: packet.name};
  830. if (packet.args && packet.args.length) {
  831. ev.args = packet.args;
  832. }
  833. data = JSON.stringify(ev);
  834. break;
  835. case 'json':
  836. data = JSON.stringify(packet.data);
  837. break;
  838. case 'connect':
  839. if (packet.qs)
  840. data = packet.qs;
  841. break;
  842. case 'ack':
  843. data = packet.ackId
  844. + (packet.args && packet.args.length
  845. ? '+' + JSON.stringify(packet.args) : '');
  846. break;
  847. }
  848. // construct packet with required fragments
  849. var encoded = [
  850. type
  851. , id + (ack == 'data' ? '+' : '')
  852. , endpoint
  853. ];
  854. // data fragment is optional
  855. if (data !== null && data !== undefined)
  856. encoded.push(data);
  857. return encoded.join(':');
  858. };
  859. /**
  860. * Encodes multiple messages (payload).
  861. *
  862. * @param {Array} messages
  863. * @api private
  864. */
  865. parser.encodePayload = function (packets) {
  866. var decoded = '';
  867. if (packets.length == 1)
  868. return packets[0];
  869. for (var i = 0, l = packets.length; i < l; i++) {
  870. var packet = packets[i];
  871. decoded += '\ufffd' + packet.length + '\ufffd' + packets[i];
  872. }
  873. return decoded;
  874. };
  875. /**
  876. * Decodes a packet
  877. *
  878. * @api private
  879. */
  880. var regexp = /([^:]+):([0-9]+)?(\+)?:([^:]+)?:?([\s\S]*)?/;
  881. parser.decodePacket = function (data) {
  882. var pieces = data.match(regexp);
  883. if (!pieces) return {};
  884. var id = pieces[2] || ''
  885. , data = pieces[5] || ''
  886. , packet = {
  887. type: packets[pieces[1]]
  888. , endpoint: pieces[4] || ''
  889. };
  890. // whether we need to acknowledge the packet
  891. if (id) {
  892. packet.id = id;
  893. if (pieces[3])
  894. packet.ack = 'data';
  895. else
  896. packet.ack = true;
  897. }
  898. // handle different packet types
  899. switch (packet.type) {
  900. case 'error':
  901. var pieces = data.split('+');
  902. packet.reason = reasons[pieces[0]] || '';
  903. packet.advice = advice[pieces[1]] || '';
  904. break;
  905. case 'message':
  906. packet.data = data || '';
  907. break;
  908. case 'event':
  909. try {
  910. var opts = JSON.parse(data);
  911. packet.name = opts.name;
  912. packet.args = opts.args;
  913. } catch (e) {
  914. }
  915. packet.args = packet.args || [];
  916. break;
  917. case 'json':
  918. try {
  919. packet.data = JSON.parse(data);
  920. } catch (e) {
  921. }
  922. break;
  923. case 'connect':
  924. packet.qs = data || '';
  925. break;
  926. case 'ack':
  927. var pieces = data.match(/^([0-9]+)(\+)?(.*)/);
  928. if (pieces) {
  929. packet.ackId = pieces[1];
  930. packet.args = [];
  931. if (pieces[3]) {
  932. try {
  933. packet.args = pieces[3] ? JSON.parse(pieces[3]) : [];
  934. } catch (e) {
  935. }
  936. }
  937. }
  938. break;
  939. case 'disconnect':
  940. case 'heartbeat':
  941. break;
  942. }
  943. ;
  944. return packet;
  945. };
  946. /**
  947. * Decodes data payload. Detects multiple messages
  948. *
  949. * @return {Array} messages
  950. * @api public
  951. */
  952. parser.decodePayload = function (data) {
  953. // IE doesn't like data[i] for unicode chars, charAt works fine
  954. if (data.charAt(0) == '\ufffd') {
  955. var ret = [];
  956. for (var i = 1, length = ''; i < data.length; i++) {
  957. if (data.charAt(i) == '\ufffd') {
  958. ret.push(parser.decodePacket(data.substr(i + 1).substr(0, length)));
  959. i += Number(length) + 1;
  960. length = '';
  961. } else {
  962. length += data.charAt(i);
  963. }
  964. }
  965. return ret;
  966. } else {
  967. return [parser.decodePacket(data)];
  968. }
  969. };
  970. })(
  971. 'undefined' != typeof io ? io : module.exports
  972. , 'undefined' != typeof io ? io : module.parent.exports
  973. );
  974. /**
  975. * socket.io
  976. * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
  977. * MIT Licensed
  978. */
  979. (function (exports, io) {
  980. /**
  981. * Expose constructor.
  982. */
  983. exports.Transport = Transport;
  984. /**
  985. * This is the transport template for all supported transport methods.
  986. *
  987. * @constructor
  988. * @api public
  989. */
  990. function Transport(socket, sessid) {
  991. this.socket = socket;
  992. this.sessid = sessid;
  993. };
  994. /**
  995. * Apply EventEmitter mixin.
  996. */
  997. io.util.mixin(Transport, io.EventEmitter);
  998. /**
  999. * Indicates whether heartbeats is enabled for this transport
  1000. *
  1001. * @api private
  1002. */
  1003. Transport.prototype.heartbeats = function () {
  1004. return true;
  1005. };
  1006. /**
  1007. * Handles the response from the server. When a new response is received
  1008. * it will automatically update the timeout, decode the message and
  1009. * forwards the response to the onMessage function for further processing.
  1010. *
  1011. * @param {String} data Response from the server.
  1012. * @api private
  1013. */
  1014. Transport.prototype.onData = function (data) {
  1015. this.clearCloseTimeout();
  1016. // If the connection in currently open (or in a reopening state) reset the close
  1017. // timeout since we have just received data. This check is necessary so
  1018. // that we don't reset the timeout on an explicitly disconnected connection.
  1019. if (this.socket.connected || this.socket.connecting || this.socket.reconnecting) {
  1020. this.setCloseTimeout();
  1021. }
  1022. if (data !== '') {
  1023. // todo: we should only do decodePayload for xhr transports
  1024. var msgs = io.parser.decodePayload(data);
  1025. if (msgs && msgs.length) {
  1026. for (var i = 0, l = msgs.length; i < l; i++) {
  1027. this.onPacket(msgs[i]);
  1028. }
  1029. }
  1030. }
  1031. return this;
  1032. };
  1033. /**
  1034. * Handles packets.
  1035. *
  1036. * @api private
  1037. */
  1038. Transport.prototype.onPacket = function (packet) {
  1039. this.socket.setHeartbeatTimeout();
  1040. if (packet.type == 'heartbeat') {
  1041. return this.onHeartbeat();
  1042. }
  1043. if (packet.type == 'connect' && packet.endpoint == '') {
  1044. this.onConnect();
  1045. }
  1046. if (packet.type == 'error' && packet.advice == 'reconnect') {
  1047. this.isOpen = false;
  1048. }
  1049. this.socket.onPacket(packet);
  1050. return this;
  1051. };
  1052. /**
  1053. * Sets close timeout
  1054. *
  1055. * @api private
  1056. */
  1057. Transport.prototype.setCloseTimeout = function () {
  1058. if (!this.closeTimeout) {
  1059. var self = this;
  1060. this.closeTimeout = setTimeout(function () {
  1061. self.onDisconnect();
  1062. }, this.socket.closeTimeout);
  1063. }
  1064. };
  1065. /**
  1066. * Called when transport disconnects.
  1067. *
  1068. * @api private
  1069. */
  1070. Transport.prototype.onDisconnect = function () {
  1071. if (this.isOpen) this.close();
  1072. this.clearTimeouts();
  1073. this.socket.onDisconnect();
  1074. return this;
  1075. };
  1076. /**
  1077. * Called when transport connects
  1078. *
  1079. * @api private
  1080. */
  1081. Transport.prototype.onConnect = function () {
  1082. this.socket.onConnect();
  1083. return this;
  1084. };
  1085. /**
  1086. * Clears close timeout
  1087. *
  1088. * @api private
  1089. */
  1090. Transport.prototype.clearCloseTimeout = function () {
  1091. if (this.closeTimeout) {
  1092. clearTimeout(this.closeTimeout);
  1093. this.closeTimeout = null;
  1094. }
  1095. };
  1096. /**
  1097. * Clear timeouts
  1098. *
  1099. * @api private
  1100. */
  1101. Transport.prototype.clearTimeouts = function () {
  1102. this.clearCloseTimeout();
  1103. if (this.reopenTimeout) {
  1104. clearTimeout(this.reopenTimeout);
  1105. }
  1106. };
  1107. /**
  1108. * Sends a packet
  1109. *
  1110. * @param {Object} packet object.
  1111. * @api private
  1112. */
  1113. Transport.prototype.packet = function (packet) {
  1114. this.send(io.parser.encodePacket(packet));
  1115. };
  1116. /**
  1117. * Send the received heartbeat message back to server. So the server
  1118. * knows we are still connected.
  1119. *
  1120. * @param {String} heartbeat Heartbeat response from the server.
  1121. * @api private
  1122. */
  1123. Transport.prototype.onHeartbeat = function (heartbeat) {
  1124. this.packet({type: 'heartbeat'});
  1125. };
  1126. /**
  1127. * Called when the transport opens.
  1128. *
  1129. * @api private
  1130. */
  1131. Transport.prototype.onOpen = function () {
  1132. this.isOpen = true;
  1133. this.clearCloseTimeout();
  1134. this.socket.onOpen();
  1135. };
  1136. /**
  1137. * Notifies the base when the connection with the Socket.IO server
  1138. * has been disconnected.
  1139. *
  1140. * @api private
  1141. */
  1142. Transport.prototype.onClose = function () {
  1143. var self = this;
  1144. /* FIXME: reopen delay causing a infinit loop
  1145. this.reopenTimeout = setTimeout(function () {
  1146. self.open();
  1147. }, this.socket.options['reopen delay']);*/
  1148. this.isOpen = false;
  1149. this.socket.onClose();
  1150. this.onDisconnect();
  1151. };
  1152. /**
  1153. * Generates a connection url based on the Socket.IO URL Protocol.
  1154. * See <https://github.com/learnboost/socket.io-node/> for more details.
  1155. *
  1156. * @returns {String} Connection url
  1157. * @api private
  1158. */
  1159. Transport.prototype.prepareUrl = function () {
  1160. var options = this.socket.options;
  1161. return this.scheme() + '://'
  1162. + options.host + ':' + options.port + '/'
  1163. + options.resource + '/' + io.protocol
  1164. + '/' + this.name + '/' + this.sessid;
  1165. };
  1166. /**
  1167. * Checks if the transport is ready to start a connection.
  1168. *
  1169. * @param {Socket} socket The socket instance that needs a transport
  1170. * @param {Function} fn The callback
  1171. * @api private
  1172. */
  1173. Transport.prototype.ready = function (socket, fn) {
  1174. fn.call(this);
  1175. };
  1176. })(
  1177. 'undefined' != typeof io ? io : module.exports
  1178. , 'undefined' != typeof io ? io : module.parent.exports
  1179. );
  1180. /**
  1181. * socket.io
  1182. * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
  1183. * MIT Licensed
  1184. */
  1185. (function (exports, io, global) {
  1186. /**
  1187. * Expose constructor.
  1188. */
  1189. exports.Socket = Socket;
  1190. /**
  1191. * Create a new `Socket.IO client` which can establish a persistent
  1192. * connection with a Socket.IO enabled server.
  1193. *
  1194. * @api public
  1195. */
  1196. function Socket(options) {
  1197. this.options = {
  1198. port: 80
  1199. , secure: false
  1200. , document: 'document' in global ? document : false
  1201. , resource: 'socket.io'
  1202. , transports: io.transports
  1203. , 'connect timeout': 10000
  1204. , 'try multiple transports': true
  1205. , 'reconnect': true
  1206. , 'reconnection delay': 500
  1207. , 'reconnection limit': Infinity
  1208. , 'reopen delay': 3000
  1209. , 'max reconnection attempts': 10
  1210. , 'sync disconnect on unload': false
  1211. , 'auto connect': true
  1212. , 'flash policy port': 10843
  1213. , 'manualFlush': false
  1214. };
  1215. io.util.merge(this.options, options);
  1216. this.connected = false;
  1217. this.open = false;
  1218. this.connecting = false;
  1219. this.reconnecting = false;
  1220. this.namespaces = {};
  1221. this.buffer = [];
  1222. this.doBuffer = false;
  1223. if (this.options['sync disconnect on unload'] &&
  1224. (!this.isXDomain() || io.util.ua.hasCORS)) {
  1225. var self = this;
  1226. io.util.on(global, 'beforeunload', function () {
  1227. self.disconnectSync();
  1228. }, false);
  1229. }
  1230. if (this.options['auto connect']) {
  1231. this.connect();
  1232. }
  1233. };
  1234. /**
  1235. * Apply EventEmitter mixin.
  1236. */
  1237. io.util.mixin(Socket, io.EventEmitter);
  1238. /**
  1239. * Returns a namespace listener/emitter for this socket
  1240. *
  1241. * @api public
  1242. */
  1243. Socket.prototype.of = function (name) {
  1244. if (!this.namespaces[name]) {
  1245. this.namespaces[name] = new io.SocketNamespace(this, name);
  1246. if (name !== '') {
  1247. this.namespaces[name].packet({type: 'connect'});
  1248. }
  1249. }
  1250. return this.namespaces[name];
  1251. };
  1252. /**
  1253. * Emits the given event to the Socket and all namespaces
  1254. *
  1255. * @api private
  1256. */
  1257. Socket.prototype.publish = function () {
  1258. this.emit.apply(this, arguments);
  1259. var nsp;
  1260. for (var i in this.namespaces) {
  1261. if (this.namespaces.hasOwnProperty(i)) {
  1262. nsp = this.of(i);
  1263. nsp.$emit.apply(nsp, arguments);
  1264. }
  1265. }
  1266. };
  1267. /**
  1268. * Performs the handshake
  1269. *
  1270. * @api private
  1271. */
  1272. function empty() {
  1273. };
  1274. Socket.prototype.handshake = function (fn) {
  1275. var self = this
  1276. , options = this.options;
  1277. function complete(data) {
  1278. if (data instanceof Error) {
  1279. self.connecting = false;
  1280. self.onError(data.message);
  1281. } else {
  1282. fn.apply(null, data.split(':'));
  1283. }
  1284. };
  1285. var url = [
  1286. 'http' + (options.secure ? 's' : '') + ':/'
  1287. , options.host + ':' + options.port
  1288. , options.resource
  1289. , io.protocol
  1290. , io.util.query(this.options.query, 't=' + +new Date)
  1291. ].join('/');
  1292. if (this.isXDomain() && !io.util.ua.hasCORS) {
  1293. var insertAt = document.getElementsByTagName('script')[0]
  1294. , script = document.createElement('script');
  1295. script.src = url + '&jsonp=' + io.j.length;
  1296. insertAt.parentNode.insertBefore(script, insertAt);
  1297. io.j.push(function (data) {
  1298. complete(data);
  1299. script.parentNode.removeChild(script);
  1300. });
  1301. } else {
  1302. var xhr = io.util.request();
  1303. xhr.open('GET', url, true);
  1304. if (this.isXDomain()) {
  1305. xhr.withCredentials = true;
  1306. }
  1307. xhr.onreadystatechange = function () {
  1308. if (xhr.readyState == 4) {
  1309. xhr.onreadystatechange = empty;
  1310. if (xhr.status == 200) {
  1311. complete(xhr.responseText);
  1312. } else if (xhr.status == 403) {
  1313. self.onError(xhr.responseText);
  1314. } else {
  1315. self.connecting = false;
  1316. !self.reconnecting && self.onError(xhr.responseText);
  1317. }
  1318. }
  1319. };
  1320. xhr.send(null);
  1321. }
  1322. };
  1323. /**
  1324. * Find an available transport based on the options supplied in the constructor.
  1325. *
  1326. * @api private
  1327. */
  1328. Socket.prototype.getTransport = function (override) {
  1329. var transports = override || this.transports, match;
  1330. for (var i = 0, transport; transport = transports[i]; i++) {
  1331. if (io.Transport[transport]
  1332. && io.Transport[transport].check(this)
  1333. && (!this.isXDomain() || io.Transport[transport].xdomainCheck(this))) {
  1334. return new io.Transport[transport](this, this.sessionid);
  1335. }
  1336. }
  1337. return null;
  1338. };
  1339. /**
  1340. * Connects to the server.
  1341. *
  1342. * @param {Function} [fn] Callback.
  1343. * @returns {io.Socket}
  1344. * @api public
  1345. */
  1346. Socket.prototype.connect = function (fn) {
  1347. if (this.connecting) {
  1348. return this;
  1349. }
  1350. var self = this;
  1351. self.connecting = true;
  1352. this.handshake(function (sid, heartbeat, close, transports) {
  1353. self.sessionid = sid;
  1354. self.closeTimeout = close * 1000;
  1355. self.heartbeatTimeout = heartbeat * 1000;
  1356. if (!self.transports)
  1357. self.transports = self.origTransports = (transports ? io.util.intersect(
  1358. transports.split(',')
  1359. , self.options.transports
  1360. ) : self.options.transports);
  1361. self.setHeartbeatTimeout();
  1362. function connect(transports) {
  1363. if (self.transport) self.transport.clearTimeouts();
  1364. self.transport = self.getTransport(transports);
  1365. if (!self.transport) return self.publish('connect_failed');
  1366. // once the transport is ready
  1367. self.transport.ready(self, function () {
  1368. self.connecting = true;
  1369. self.publish('connecting', self.transport.name);
  1370. self.transport.open();
  1371. if (self.options['connect timeout']) {
  1372. self.connectTimeoutTimer = setTimeout(function () {
  1373. if (!self.connected) {
  1374. self.connecting = false;
  1375. if (self.options['try multiple transports']) {
  1376. var remaining = self.transports;
  1377. while (remaining.length > 0 && remaining.splice(0, 1)[0] !=
  1378. self.transport.name) {
  1379. }
  1380. if (remaining.length) {
  1381. connect(remaining);
  1382. } else {
  1383. self.publish('connect_failed');
  1384. }
  1385. }
  1386. }
  1387. }, self.options['connect timeout']);
  1388. }
  1389. });
  1390. }
  1391. connect(self.transports);
  1392. self.once('connect', function () {
  1393. clearTimeout(self.connectTimeoutTimer);
  1394. fn && typeof fn == 'function' && fn();
  1395. });
  1396. });
  1397. return this;
  1398. };
  1399. /**
  1400. * Clears and sets a new heartbeat timeout using the value given by the
  1401. * server during the handshake.
  1402. *
  1403. * @api private
  1404. */
  1405. Socket.prototype.setHeartbeatTimeout = function () {
  1406. clearTimeout(this.heartbeatTimeoutTimer);
  1407. if (this.transport && !this.transport.heartbeats()) return;
  1408. var self = this;
  1409. this.heartbeatTimeoutTimer = setTimeout(function () {
  1410. self.transport.onClose();
  1411. }, this.heartbeatTimeout);
  1412. };
  1413. /**
  1414. * Sends a message.
  1415. *
  1416. * @param {Object} data packet.
  1417. * @returns {io.Socket}
  1418. * @api public
  1419. */
  1420. Socket.prototype.packet = function (data) {
  1421. if (this.connected && !this.doBuffer) {
  1422. this.transport.packet(data);
  1423. } else {
  1424. this.buffer.push(data);
  1425. }
  1426. return this;
  1427. };
  1428. /**
  1429. * Sets buffer state
  1430. *
  1431. * @api private
  1432. */
  1433. Socket.prototype.setBuffer = function (v) {
  1434. this.doBuffer = v;
  1435. if (!v && this.connected && this.buffer.length) {
  1436. if (!this.options['manualFlush']) {
  1437. this.flushBuffer();
  1438. }
  1439. }
  1440. };
  1441. /**
  1442. * Flushes the buffer data over the wire.
  1443. * To be invoked manually when 'manualFlush' is set to true.
  1444. *
  1445. * @api public
  1446. */
  1447. Socket.prototype.flushBuffer = function () {
  1448. this.transport.payload(this.buffer);
  1449. this.buffer = [];
  1450. };
  1451. /**
  1452. * Disconnect the established connect.
  1453. *
  1454. * @returns {io.Socket}
  1455. * @api public
  1456. */
  1457. Socket.prototype.disconnect = function () {
  1458. if (this.connected || this.connecting) {
  1459. if (this.open) {
  1460. this.of('').packet({type: 'disconnect'});
  1461. }
  1462. // handle disconnection immediately
  1463. this.onDisconnect('booted');
  1464. }
  1465. return this;
  1466. };
  1467. /**
  1468. * Disconnects the socket with a sync XHR.
  1469. *
  1470. * @api private
  1471. */
  1472. Socket.prototype.disconnectSync = function () {
  1473. // ensure disconnection
  1474. var xhr = io.util.request();
  1475. var uri = [
  1476. 'http' + (this.options.secure ? 's' : '') + ':/'
  1477. , this.options.host + ':' + this.options.port
  1478. , this.options.resource
  1479. , io.protocol
  1480. , ''
  1481. , this.sessionid
  1482. ].join('/') + '/?disconnect=1';
  1483. xhr.open('GET', uri, false);
  1484. xhr.send(null);
  1485. // handle disconnection immediately
  1486. this.onDisconnect('booted');
  1487. };
  1488. /**
  1489. * Check if we need to use cross domain enabled transports. Cross domain would
  1490. * be a different port or different domain name.
  1491. *
  1492. * @returns {Boolean}
  1493. * @api private
  1494. */
  1495. Socket.prototype.isXDomain = function () {
  1496. var port = global.location.port ||
  1497. ('https:' == global.location.protocol ? 443 : 80);
  1498. return this.options.host !== global.location.hostname
  1499. || this.options.port != port;
  1500. };
  1501. /**
  1502. * Called upon handshake.
  1503. *
  1504. * @api private
  1505. */
  1506. Socket.prototype.onConnect = function () {
  1507. if (!this.connected) {
  1508. this.connected = true;
  1509. this.connecting = false;
  1510. if (!this.doBuffer) {
  1511. // make sure to flush the buffer
  1512. this.setBuffer(false);
  1513. }
  1514. this.emit('connect');
  1515. }
  1516. };
  1517. /**
  1518. * Called when the transport opens
  1519. *
  1520. * @api private
  1521. */
  1522. Socket.prototype.onOpen = function () {
  1523. this.open = true;
  1524. };
  1525. /**
  1526. * Called when the transport closes.
  1527. *
  1528. * @api private
  1529. */
  1530. Socket.prototype.onClose = function () {
  1531. this.open = false;
  1532. clearTimeout(this.heartbeatTimeoutTimer);
  1533. };
  1534. /**
  1535. * Called when the transport first opens a connection
  1536. *
  1537. * @param text
  1538. */
  1539. Socket.prototype.onPacket = function (packet) {
  1540. this.of(packet.endpoint).onPacket(packet);
  1541. };
  1542. /**
  1543. * Handles an error.
  1544. *
  1545. * @api private
  1546. */
  1547. Socket.prototype.onError = function (err) {
  1548. if (err && err.advice) {
  1549. if (err.advice === 'reconnect' && (this.connected || this.connecting)) {
  1550. this.disconnect();
  1551. if (this.options.reconnect) {
  1552. this.reconnect();
  1553. }
  1554. }
  1555. }
  1556. this.publish('error', err && err.reason ? err.reason : err);
  1557. };
  1558. /**
  1559. * Called when the transport disconnects.
  1560. *
  1561. * @api private
  1562. */
  1563. Socket.prototype.onDisconnect = function (reason) {
  1564. var wasConnected = this.connected
  1565. , wasConnecting = this.connecting;
  1566. this.connected = false;
  1567. this.connecting = false;
  1568. this.open = false;
  1569. if (wasConnected || wasConnecting) {
  1570. this.transport.close();
  1571. this.transport.clearTimeouts();
  1572. if (wasConnected) {
  1573. this.publish('disconnect', reason);
  1574. if ('booted' != reason && this.options.reconnect && !this.reconnecting) {
  1575. this.reconnect();
  1576. }
  1577. }
  1578. }
  1579. };
  1580. /**
  1581. * Called upon reconnection.
  1582. *
  1583. * @api private
  1584. */
  1585. Socket.prototype.reconnect = function () {
  1586. this.reconnecting = true;
  1587. this.reconnectionAttempts = 0;
  1588. this.reconnectionDelay = this.options['reconnection delay'];
  1589. var self = this
  1590. , maxAttempts = this.options['max reconnection attempts']
  1591. , tryMultiple = this.options['try multiple transports']
  1592. , limit = this.options['reconnection limit'];
  1593. function reset() {
  1594. if (self.connected) {
  1595. for (var i in self.namespaces) {
  1596. if (self.namespaces.hasOwnProperty(i) && '' !== i) {
  1597. self.namespaces[i].packet({type: 'connect'});
  1598. }
  1599. }
  1600. self.publish('reconnect', self.transport.name, self.reconnectionAttempts);
  1601. }
  1602. clearTimeout(self.reconnectionTimer);
  1603. self.removeListener('connect_failed', maybeReconnect);
  1604. self.removeListener('connect', maybeReconnect);
  1605. self.reconnecting = false;
  1606. delete self.reconnectionAttempts;
  1607. delete self.reconnectionDelay;
  1608. delete self.reconnectionTimer;
  1609. delete self.redoTransports;
  1610. self.options['try multiple transports'] = tryMultiple;
  1611. };
  1612. function maybeReconnect() {
  1613. if (!self.reconnecting) {
  1614. return;
  1615. }
  1616. if (self.connected) {
  1617. return reset();
  1618. }
  1619. ;
  1620. if (self.connecting && self.reconnecting) {
  1621. return self.reconnectionTimer = setTimeout(maybeReconnect, 1000);
  1622. }
  1623. if (self.reconnectionAttempts++ >= maxAttempts) {
  1624. if (!self.redoTransports) {
  1625. self.on('connect_failed', maybeReconnect);
  1626. self.options['try multiple transports'] = true;
  1627. self.transports = self.origTransports;
  1628. self.transport = self.getTransport();
  1629. self.redoTransports = true;
  1630. self.connect();
  1631. } else {
  1632. self.publish('reconnect_failed');
  1633. reset();
  1634. }
  1635. } else {
  1636. if (self.reconnectionDelay < limit) {
  1637. self.reconnectionDelay *= 2; // exponential back off
  1638. }
  1639. self.connect();
  1640. self.publish('reconnecting', self.reconnectionDelay, self.reconnectionAttempts);
  1641. self.reconnectionTimer = setTimeout(maybeReconnect, self.reconnectionDelay);
  1642. }
  1643. };
  1644. this.options['try multiple transports'] = false;
  1645. this.reconnectionTimer = setTimeout(maybeReconnect, this.reconnectionDelay);
  1646. this.on('connect', maybeReconnect);
  1647. };
  1648. })(
  1649. 'undefined' != typeof io ? io : module.exports
  1650. , 'undefined' != typeof io ? io : module.parent.exports
  1651. , this
  1652. );
  1653. /**
  1654. * socket.io
  1655. * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
  1656. * MIT Licensed
  1657. */
  1658. (function (exports, io) {
  1659. /**
  1660. * Expose constructor.
  1661. */
  1662. exports.SocketNamespace = SocketNamespace;
  1663. /**
  1664. * Socket namespace constructor.
  1665. *
  1666. * @constructor
  1667. * @api public
  1668. */
  1669. function SocketNamespace(socket, name) {
  1670. this.socket = socket;
  1671. this.name = name || '';
  1672. this.flags = {};
  1673. this.json = new Flag(this, 'json');
  1674. this.ackPackets = 0;
  1675. this.acks = {};
  1676. };
  1677. /**
  1678. * Apply EventEmitter mixin.
  1679. */
  1680. io.util.mixin(SocketNamespace, io.EventEmitter);
  1681. /**
  1682. * Copies emit since we override it
  1683. *
  1684. * @api private
  1685. */
  1686. SocketNamespace.prototype.$emit = io.EventEmitter.prototype.emit;
  1687. /**
  1688. * Creates a new namespace, by proxying the request to the socket. This
  1689. * allows us to use the synax as we do on the server.
  1690. *
  1691. * @api public
  1692. */
  1693. SocketNamespace.prototype.of = function () {
  1694. return this.socket.of.apply(this.socket, arguments);
  1695. };
  1696. /**
  1697. * Sends a packet.
  1698. *
  1699. * @api private
  1700. */
  1701. SocketNamespace.prototype.packet = function (packet) {
  1702. packet.endpoint = this.name;
  1703. this.socket.packet(packet);
  1704. this.flags = {};
  1705. return this;
  1706. };
  1707. /**
  1708. * Sends a message
  1709. *
  1710. * @api public
  1711. */
  1712. SocketNamespace.prototype.send = function (data, fn) {
  1713. var packet = {
  1714. type: this.flags.json ? 'json' : 'message'
  1715. , data: data
  1716. };
  1717. if ('function' == typeof fn) {
  1718. packet.id = ++this.ackPackets;
  1719. packet.ack = true;
  1720. this.acks[packet.id] = fn;
  1721. }
  1722. return this.packet(packet);
  1723. };
  1724. /**
  1725. * Emits an event
  1726. *
  1727. * @api public
  1728. */
  1729. SocketNamespace.prototype.emit = function (name) {
  1730. var args = Array.prototype.slice.call(arguments, 1)
  1731. , lastArg = args[args.length - 1]
  1732. , packet = {
  1733. type: 'event'
  1734. , name: name
  1735. };
  1736. if ('function' == typeof lastArg) {
  1737. packet.id = ++this.ackPackets;
  1738. packet.ack = 'data';
  1739. this.acks[packet.id] = lastArg;
  1740. args = args.slice(0, args.length - 1);
  1741. }
  1742. packet.args = args;
  1743. return this.packet(packet);
  1744. };
  1745. /**
  1746. * Disconnects the namespace
  1747. *
  1748. * @api private
  1749. */
  1750. SocketNamespace.prototype.disconnect = function () {
  1751. if (this.name === '') {
  1752. this.socket.disconnect();
  1753. } else {
  1754. this.packet({type: 'disconnect'});
  1755. this.$emit('disconnect');
  1756. }
  1757. return this;
  1758. };
  1759. /**
  1760. * Handles a packet
  1761. *
  1762. * @api private
  1763. */
  1764. SocketNamespace.prototype.onPacket = function (packet) {
  1765. var self = this;
  1766. function ack() {
  1767. self.packet({
  1768. type: 'ack'
  1769. , args: io.util.toArray(arguments)
  1770. , ackId: packet.id
  1771. });
  1772. };
  1773. switch (packet.type) {
  1774. case 'connect':
  1775. this.$emit('connect');
  1776. break;
  1777. case 'disconnect':
  1778. if (this.name === '') {
  1779. this.socket.onDisconnect(packet.reason || 'booted');
  1780. } else {
  1781. this.$emit('disconnect', packet.reason);
  1782. }
  1783. break;
  1784. case 'message':
  1785. case 'json':
  1786. var params = ['message', packet.data];
  1787. if (packet.ack == 'data') {
  1788. params.push(ack);
  1789. } else if (packet.ack) {
  1790. this.packet({type: 'ack', ackId: packet.id});
  1791. }
  1792. this.$emit.apply(this, params);
  1793. break;
  1794. case 'event':
  1795. var params = [packet.name].concat(packet.args);
  1796. if (packet.ack == 'data')
  1797. params.push(ack);
  1798. this.$emit.apply(this, params);
  1799. break;
  1800. case 'ack':
  1801. if (this.acks[packet.ackId]) {
  1802. this.acks[packet.ackId].apply(this, packet.args);
  1803. delete this.acks[packet.ackId];
  1804. }
  1805. break;
  1806. case 'error':
  1807. if (packet.advice) {
  1808. this.socket.onError(packet);
  1809. } else {
  1810. if (packet.reason == 'unauthorized') {
  1811. this.$emit('connect_failed', packet.reason);
  1812. } else {
  1813. this.$emit('error', packet.reason);
  1814. }
  1815. }
  1816. break;
  1817. }
  1818. };
  1819. /**
  1820. * Flag interface.
  1821. *
  1822. * @api private
  1823. */
  1824. function Flag(nsp, name) {
  1825. this.namespace = nsp;
  1826. this.name = name;
  1827. };
  1828. /**
  1829. * Send a message
  1830. *
  1831. * @api public
  1832. */
  1833. Flag.prototype.send = function () {
  1834. this.namespace.flags[this.name] = true;
  1835. this.namespace.send.apply(this.namespace, arguments);
  1836. };
  1837. /**
  1838. * Emit an event
  1839. *
  1840. * @api public
  1841. */
  1842. Flag.prototype.emit = function () {
  1843. this.namespace.flags[this.name] = true;
  1844. this.namespace.emit.apply(this.namespace, arguments);
  1845. };
  1846. })(
  1847. 'undefined' != typeof io ? io : module.exports
  1848. , 'undefined' != typeof io ? io : module.parent.exports
  1849. );
  1850. /**
  1851. * socket.io
  1852. * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
  1853. * MIT Licensed
  1854. */
  1855. (function (exports, io, global) {
  1856. /**
  1857. * Expose constructor.
  1858. */
  1859. exports.websocket = WS;
  1860. /**
  1861. * The WebSocket transport uses the HTML5 WebSocket API to establish an
  1862. * persistent connection with the Socket.IO server. This transport will also
  1863. * be inherited by the FlashSocket fallback as it provides a API compatible
  1864. * polyfill for the WebSockets.
  1865. *
  1866. * @constructor
  1867. * @extends {io.Transport}
  1868. * @api public
  1869. */
  1870. function WS(socket) {
  1871. io.Transport.apply(this, arguments);
  1872. };
  1873. /**
  1874. * Inherits from Transport.
  1875. */
  1876. io.util.inherit(WS, io.Transport);
  1877. /**
  1878. * Transport name
  1879. *
  1880. * @api public
  1881. */
  1882. WS.prototype.name = 'websocket';
  1883. /**
  1884. * Initializes a new `WebSocket` connection with the Socket.IO server. We attach
  1885. * all the appropriate listeners to handle the responses from the server.
  1886. *
  1887. * @returns {Transport}
  1888. * @api public
  1889. */
  1890. WS.prototype.open = function () {
  1891. var query = io.util.query(this.socket.options.query)
  1892. , self = this
  1893. , Socket
  1894. if (!Socket) {
  1895. Socket = global.MozWebSocket || global.WebSocket;
  1896. }
  1897. this.websocket = new Socket(this.prepareUrl() + query);
  1898. this.websocket.onopen = function () {
  1899. self.onOpen();
  1900. self.socket.setBuffer(false);
  1901. };
  1902. this.websocket.onmessage = function (ev) {
  1903. self.onData(ev.data);
  1904. };
  1905. this.websocket.onclose = function () {
  1906. self.onClose();
  1907. self.socket.setBuffer(true);
  1908. };
  1909. this.websocket.onerror = function (e) {
  1910. self.onError(e);
  1911. };
  1912. return this;
  1913. };
  1914. /**
  1915. * Send a message to the Socket.IO server. The message will automatically be
  1916. * encoded in the correct message format.
  1917. *
  1918. * @returns {Transport}
  1919. * @api public
  1920. */
  1921. // Do to a bug in the current IDevices browser, we need to wrap the send in a
  1922. // setTimeout, when they resume from sleeping the browser will crash if
  1923. // we don't allow the browser time to detect the socket has been closed
  1924. if (io.util.ua.iDevice) {
  1925. WS.prototype.send = function (data) {
  1926. var self = this;
  1927. setTimeout(function () {
  1928. self.websocket.send(data);
  1929. }, 0);
  1930. return this;
  1931. };
  1932. } else {
  1933. WS.prototype.send = function (data) {
  1934. this.websocket.send(data);
  1935. return this;
  1936. };
  1937. }
  1938. /**
  1939. * Payload
  1940. *
  1941. * @api private
  1942. */
  1943. WS.prototype.payload = function (arr) {
  1944. for (var i = 0, l = arr.length; i < l; i++) {
  1945. this.packet(arr[i]);
  1946. }
  1947. return this;
  1948. };
  1949. /**
  1950. * Disconnect the established `WebSocket` connection.
  1951. *
  1952. * @returns {Transport}
  1953. * @api public
  1954. */
  1955. WS.prototype.close = function () {
  1956. this.websocket.close();
  1957. return this;
  1958. };
  1959. /**
  1960. * Handle the errors that `WebSocket` might be giving when we
  1961. * are attempting to connect or send messages.
  1962. *
  1963. * @param {Error} e The error.
  1964. * @api private
  1965. */
  1966. WS.prototype.onError = function (e) {
  1967. this.socket.onError(e);
  1968. };
  1969. /**
  1970. * Returns the appropriate scheme for the URI generation.
  1971. *
  1972. * @api private
  1973. */
  1974. WS.prototype.scheme = function () {
  1975. return this.socket.options.secure ? 'wss' : 'ws';
  1976. };
  1977. /**
  1978. * Checks if the browser has support for native `WebSockets` and that
  1979. * it's not the polyfill created for the FlashSocket transport.
  1980. *
  1981. * @return {Boolean}
  1982. * @api public
  1983. */
  1984. WS.check = function () {
  1985. return ('WebSocket' in global && !('__addTask' in WebSocket))
  1986. || 'MozWebSocket' in global;
  1987. };
  1988. /**
  1989. * Check if the `WebSocket` transport support cross domain communications.
  1990. *
  1991. * @returns {Boolean}
  1992. * @api public
  1993. */
  1994. WS.xdomainCheck = function () {
  1995. return true;
  1996. };
  1997. /**
  1998. * Add the transport to your public io.transports array.
  1999. *
  2000. * @api private
  2001. */
  2002. io.transports.push('websocket');
  2003. })(
  2004. 'undefined' != typeof io ? io.Transport : module.exports
  2005. , 'undefined' != typeof io ? io : module.parent.exports
  2006. , this
  2007. );
  2008. /**
  2009. * socket.io
  2010. * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
  2011. * MIT Licensed
  2012. */
  2013. (function (exports, io) {
  2014. /**
  2015. * Expose constructor.
  2016. */
  2017. exports.flashsocket = Flashsocket;
  2018. /**
  2019. * The FlashSocket transport. This is a API wrapper for the HTML5 WebSocket
  2020. * specification. It uses a .swf file to communicate with the server. If you want
  2021. * to serve the .swf file from a other server than where the Socket.IO script is
  2022. * coming from you need to use the insecure version of the .swf. More information
  2023. * about this can be found on the github page.
  2024. *
  2025. * @constructor
  2026. * @extends {io.Transport.websocket}
  2027. * @api public
  2028. */
  2029. function Flashsocket() {
  2030. io.Transport.websocket.apply(this, arguments);
  2031. };
  2032. /**
  2033. * Inherits from Transport.
  2034. */
  2035. io.util.inherit(Flashsocket, io.Transport.websocket);
  2036. /**
  2037. * Transport name
  2038. *
  2039. * @api public
  2040. */
  2041. Flashsocket.prototype.name = 'flashsocket';
  2042. /**
  2043. * Disconnect the established `FlashSocket` connection. This is done by adding a
  2044. * new task to the FlashSocket. The rest will be handled off by the `WebSocket`
  2045. * transport.
  2046. *
  2047. * @returns {Transport}
  2048. * @api public
  2049. */
  2050. Flashsocket.prototype.open = function () {
  2051. var self = this
  2052. , args = arguments;
  2053. WebSocket.__addTask(function () {
  2054. io.Transport.websocket.prototype.open.apply(self, args);
  2055. });
  2056. return this;
  2057. };
  2058. /**
  2059. * Sends a message to the Socket.IO server. This is done by adding a new
  2060. * task to the FlashSocket. The rest will be handled off by the `WebSocket`
  2061. * transport.
  2062. *
  2063. * @returns {Transport}
  2064. * @api public
  2065. */
  2066. Flashsocket.prototype.send = function () {
  2067. var self = this, args = arguments;
  2068. WebSocket.__addTask(function () {
  2069. io.Transport.websocket.prototype.send.apply(self, args);
  2070. });
  2071. return this;
  2072. };
  2073. /**
  2074. * Disconnects the established `FlashSocket` connection.
  2075. *
  2076. * @returns {Transport}
  2077. * @api public
  2078. */
  2079. Flashsocket.prototype.close = function () {
  2080. WebSocket.__tasks.length = 0;
  2081. io.Transport.websocket.prototype.close.call(this);
  2082. return this;
  2083. };
  2084. /**
  2085. * The WebSocket fall back needs to append the flash container to the body
  2086. * element, so we need to make sure we have access to it. Or defer the call
  2087. * until we are sure there is a body element.
  2088. *
  2089. * @param {Socket} socket The socket instance that needs a transport
  2090. * @param {Function} fn The callback
  2091. * @api private
  2092. */
  2093. Flashsocket.prototype.ready = function (socket, fn) {
  2094. function init() {
  2095. var options = socket.options
  2096. , port = options['flash policy port']
  2097. , path = [
  2098. 'http' + (options.secure ? 's' : '') + ':/'
  2099. , options.host + ':' + options.port
  2100. , options.resource
  2101. , 'static/flashsocket'
  2102. , 'WebSocketMain' + (socket.isXDomain() ? 'Insecure' : '') + '.swf'
  2103. ];
  2104. // Only start downloading the swf file when the checked that this browser
  2105. // actually supports it
  2106. if (!Flashsocket.loaded) {
  2107. if (typeof WEB_SOCKET_SWF_LOCATION === 'undefined') {
  2108. // Set the correct file based on the XDomain settings
  2109. WEB_SOCKET_SWF_LOCATION = path.join('/');
  2110. }
  2111. if (port !== 843) {
  2112. WebSocket.loadFlashPolicyFile('xmlsocket://' + options.host + ':' + port);
  2113. }
  2114. WebSocket.__initialize();
  2115. Flashsocket.loaded = true;
  2116. }
  2117. fn.call(self);
  2118. }
  2119. var self = this;
  2120. if (document.body) return init();
  2121. io.util.load(init);
  2122. };
  2123. /**
  2124. * Check if the FlashSocket transport is supported as it requires that the Adobe
  2125. * Flash Player plug-in version `10.0.0` or greater is installed. And also check if
  2126. * the polyfill is correctly loaded.
  2127. *
  2128. * @returns {Boolean}
  2129. * @api public
  2130. */
  2131. Flashsocket.check = function () {
  2132. if (
  2133. typeof WebSocket == 'undefined'
  2134. || !('__initialize' in WebSocket) || !swfobject
  2135. ) return false;
  2136. return swfobject.getFlashPlayerVersion().major >= 10;
  2137. };
  2138. /**
  2139. * Check if the FlashSocket transport can be used as cross domain / cross origin
  2140. * transport. Because we can't see which type (secure or insecure) of .swf is used
  2141. * we will just return true.
  2142. *
  2143. * @returns {Boolean}
  2144. * @api public
  2145. */
  2146. Flashsocket.xdomainCheck = function () {
  2147. return true;
  2148. };
  2149. /**
  2150. * Disable AUTO_INITIALIZATION
  2151. */
  2152. if (typeof window != 'undefined') {
  2153. WEB_SOCKET_DISABLE_AUTO_INITIALIZATION = true;
  2154. }
  2155. /**
  2156. * Add the transport to your public io.transports array.
  2157. *
  2158. * @api private
  2159. */
  2160. io.transports.push('flashsocket');
  2161. })(
  2162. 'undefined' != typeof io ? io.Transport : module.exports
  2163. , 'undefined' != typeof io ? io : module.parent.exports
  2164. );
  2165. /* SWFObject v2.2 <http://code.google.com/p/swfobject/>
  2166. is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
  2167. */
  2168. if ('undefined' != typeof window) {
  2169. var swfobject = function () {
  2170. var D = "undefined", r = "object", S = "Shockwave Flash", W = "ShockwaveFlash.ShockwaveFlash",
  2171. q = "application/x-shockwave-flash", R = "SWFObjectExprInst", x = "onreadystatechange", O = window,
  2172. j = document, t = navigator, T = false, U = [h], o = [], N = [], I = [], l, Q, E, B, J = false,
  2173. a = false, n, G, m = true, M = function () {
  2174. var aa = typeof j.getElementById != D && typeof j.getElementsByTagName != D && typeof j.createElement != D,
  2175. ah = t.userAgent.toLowerCase(), Y = t.platform.toLowerCase(),
  2176. ae = Y ? /win/.test(Y) : /win/.test(ah), ac = Y ? /mac/.test(Y) : /mac/.test(ah),
  2177. af = /webkit/.test(ah) ? parseFloat(ah.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false,
  2178. X = !+"\v1", ag = [0, 0, 0], ab = null;
  2179. if (typeof t.plugins != D && typeof t.plugins[S] == r) {
  2180. ab = t.plugins[S].description;
  2181. if (ab && !(typeof t.mimeTypes != D && t.mimeTypes[q] && !t.mimeTypes[q].enabledPlugin)) {
  2182. T = true;
  2183. X = false;
  2184. ab = ab.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
  2185. ag[0] = parseInt(ab.replace(/^(.*)\..*$/, "$1"), 10);
  2186. ag[1] = parseInt(ab.replace(/^.*\.(.*)\s.*$/, "$1"), 10);
  2187. ag[2] = /[a-zA-Z]/.test(ab) ? parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0
  2188. }
  2189. } else {
  2190. if (typeof O[(['Active'].concat('Object').join('X'))] != D) {
  2191. try {
  2192. var ad = new window[(['Active'].concat('Object').join('X'))](W);
  2193. if (ad) {
  2194. ab = ad.GetVariable("$version");
  2195. if (ab) {
  2196. X = true;
  2197. ab = ab.split(" ")[1].split(",");
  2198. ag = [parseInt(ab[0], 10), parseInt(ab[1], 10), parseInt(ab[2], 10)]
  2199. }
  2200. }
  2201. } catch (Z) {
  2202. }
  2203. }
  2204. }
  2205. return {w3: aa, pv: ag, wk: af, ie: X, win: ae, mac: ac}
  2206. }(), k = function () {
  2207. if (!M.w3) {
  2208. return
  2209. }
  2210. if ((typeof j.readyState != D && j.readyState == "complete") || (typeof j.readyState == D && (j.getElementsByTagName("body")[0] || j.body))) {
  2211. f()
  2212. }
  2213. if (!J) {
  2214. if (typeof j.addEventListener != D) {
  2215. j.addEventListener("DOMContentLoaded", f, false)
  2216. }
  2217. if (M.ie && M.win) {
  2218. j.attachEvent(x, function () {
  2219. if (j.readyState == "complete") {
  2220. j.detachEvent(x, arguments.callee);
  2221. f()
  2222. }
  2223. });
  2224. if (O == top) {
  2225. (function () {
  2226. if (J) {
  2227. return
  2228. }
  2229. try {
  2230. j.documentElement.doScroll("left")
  2231. } catch (X) {
  2232. setTimeout(arguments.callee, 0);
  2233. return
  2234. }
  2235. f()
  2236. })()
  2237. }
  2238. }
  2239. if (M.wk) {
  2240. (function () {
  2241. if (J) {
  2242. return
  2243. }
  2244. if (!/loaded|complete/.test(j.readyState)) {
  2245. setTimeout(arguments.callee, 0);
  2246. return
  2247. }
  2248. f()
  2249. })()
  2250. }
  2251. s(f)
  2252. }
  2253. }();
  2254. function f() {
  2255. if (J) {
  2256. return
  2257. }
  2258. try {
  2259. var Z = j.getElementsByTagName("body")[0].appendChild(C("span"));
  2260. Z.parentNode.removeChild(Z)
  2261. } catch (aa) {
  2262. return
  2263. }
  2264. J = true;
  2265. var X = U.length;
  2266. for (var Y = 0; Y < X; Y++) {
  2267. U[Y]()
  2268. }
  2269. }
  2270. function K(X) {
  2271. if (J) {
  2272. X()
  2273. } else {
  2274. U[U.length] = X
  2275. }
  2276. }
  2277. function s(Y) {
  2278. if (typeof O.addEventListener != D) {
  2279. O.addEventListener("load", Y, false)
  2280. } else {
  2281. if (typeof j.addEventListener != D) {
  2282. j.addEventListener("load", Y, false)
  2283. } else {
  2284. if (typeof O.attachEvent != D) {
  2285. i(O, "onload", Y)
  2286. } else {
  2287. if (typeof O.onload == "function") {
  2288. var X = O.onload;
  2289. O.onload = function () {
  2290. X();
  2291. Y()
  2292. }
  2293. } else {
  2294. O.onload = Y
  2295. }
  2296. }
  2297. }
  2298. }
  2299. }
  2300. function h() {
  2301. if (T) {
  2302. V()
  2303. } else {
  2304. H()
  2305. }
  2306. }
  2307. function V() {
  2308. var X = j.getElementsByTagName("body")[0];
  2309. var aa = C(r);
  2310. aa.setAttribute("type", q);
  2311. var Z = X.appendChild(aa);
  2312. if (Z) {
  2313. var Y = 0;
  2314. (function () {
  2315. if (typeof Z.GetVariable != D) {
  2316. var ab = Z.GetVariable("$version");
  2317. if (ab) {
  2318. ab = ab.split(" ")[1].split(",");
  2319. M.pv = [parseInt(ab[0], 10), parseInt(ab[1], 10), parseInt(ab[2], 10)]
  2320. }
  2321. } else {
  2322. if (Y < 10) {
  2323. Y++;
  2324. setTimeout(arguments.callee, 10);
  2325. return
  2326. }
  2327. }
  2328. X.removeChild(aa);
  2329. Z = null;
  2330. H()
  2331. })()
  2332. } else {
  2333. H()
  2334. }
  2335. }
  2336. function H() {
  2337. var ag = o.length;
  2338. if (ag > 0) {
  2339. for (var af = 0; af < ag; af++) {
  2340. var Y = o[af].id;
  2341. var ab = o[af].callbackFn;
  2342. var aa = {success: false, id: Y};
  2343. if (M.pv[0] > 0) {
  2344. var ae = c(Y);
  2345. if (ae) {
  2346. if (F(o[af].swfVersion) && !(M.wk && M.wk < 312)) {
  2347. w(Y, true);
  2348. if (ab) {
  2349. aa.success = true;
  2350. aa.ref = z(Y);
  2351. ab(aa)
  2352. }
  2353. } else {
  2354. if (o[af].expressInstall && A()) {
  2355. var ai = {};
  2356. ai.data = o[af].expressInstall;
  2357. ai.width = ae.getAttribute("width") || "0";
  2358. ai.height = ae.getAttribute("height") || "0";
  2359. if (ae.getAttribute("class")) {
  2360. ai.styleclass = ae.getAttribute("class")
  2361. }
  2362. if (ae.getAttribute("align")) {
  2363. ai.align = ae.getAttribute("align")
  2364. }
  2365. var ah = {};
  2366. var X = ae.getElementsByTagName("param");
  2367. var ac = X.length;
  2368. for (var ad = 0; ad < ac; ad++) {
  2369. if (X[ad].getAttribute("name").toLowerCase() != "movie") {
  2370. ah[X[ad].getAttribute("name")] = X[ad].getAttribute("value")
  2371. }
  2372. }
  2373. P(ai, ah, Y, ab)
  2374. } else {
  2375. p(ae);
  2376. if (ab) {
  2377. ab(aa)
  2378. }
  2379. }
  2380. }
  2381. }
  2382. } else {
  2383. w(Y, true);
  2384. if (ab) {
  2385. var Z = z(Y);
  2386. if (Z && typeof Z.SetVariable != D) {
  2387. aa.success = true;
  2388. aa.ref = Z
  2389. }
  2390. ab(aa)
  2391. }
  2392. }
  2393. }
  2394. }
  2395. }
  2396. function z(aa) {
  2397. var X = null;
  2398. var Y = c(aa);
  2399. if (Y && Y.nodeName == "OBJECT") {
  2400. if (typeof Y.SetVariable != D) {
  2401. X = Y
  2402. } else {
  2403. var Z = Y.getElementsByTagName(r)[0];
  2404. if (Z) {
  2405. X = Z
  2406. }
  2407. }
  2408. }
  2409. return X
  2410. }
  2411. function A() {
  2412. return !a && F("6.0.65") && (M.win || M.mac) && !(M.wk && M.wk < 312)
  2413. }
  2414. function P(aa, ab, X, Z) {
  2415. a = true;
  2416. E = Z || null;
  2417. B = {success: false, id: X};
  2418. var ae = c(X);
  2419. if (ae) {
  2420. if (ae.nodeName == "OBJECT") {
  2421. l = g(ae);
  2422. Q = null
  2423. } else {
  2424. l = ae;
  2425. Q = X
  2426. }
  2427. aa.id = R;
  2428. if (typeof aa.width == D || (!/%$/.test(aa.width) && parseInt(aa.width, 10) < 310)) {
  2429. aa.width = "310"
  2430. }
  2431. if (typeof aa.height == D || (!/%$/.test(aa.height) && parseInt(aa.height, 10) < 137)) {
  2432. aa.height = "137"
  2433. }
  2434. j.title = j.title.slice(0, 47) + " - Flash Player Installation";
  2435. var ad = M.ie && M.win ? (['Active'].concat('').join('X')) : "PlugIn",
  2436. ac = "MMredirectURL=" + O.location.toString().replace(/&/g, "%26") + "&MMplayerType=" + ad + "&MMdoctitle=" + j.title;
  2437. if (typeof ab.flashvars != D) {
  2438. ab.flashvars += "&" + ac
  2439. } else {
  2440. ab.flashvars = ac
  2441. }
  2442. if (M.ie && M.win && ae.readyState != 4) {
  2443. var Y = C("div");
  2444. X += "SWFObjectNew";
  2445. Y.setAttribute("id", X);
  2446. ae.parentNode.insertBefore(Y, ae);
  2447. ae.style.display = "none";
  2448. (function () {
  2449. if (ae.readyState == 4) {
  2450. ae.parentNode.removeChild(ae)
  2451. } else {
  2452. setTimeout(arguments.callee, 10)
  2453. }
  2454. })()
  2455. }
  2456. u(aa, ab, X)
  2457. }
  2458. }
  2459. function p(Y) {
  2460. if (M.ie && M.win && Y.readyState != 4) {
  2461. var X = C("div");
  2462. Y.parentNode.insertBefore(X, Y);
  2463. X.parentNode.replaceChild(g(Y), X);
  2464. Y.style.display = "none";
  2465. (function () {
  2466. if (Y.readyState == 4) {
  2467. Y.parentNode.removeChild(Y)
  2468. } else {
  2469. setTimeout(arguments.callee, 10)
  2470. }
  2471. })()
  2472. } else {
  2473. Y.parentNode.replaceChild(g(Y), Y)
  2474. }
  2475. }
  2476. function g(ab) {
  2477. var aa = C("div");
  2478. if (M.win && M.ie) {
  2479. aa.innerHTML = ab.innerHTML
  2480. } else {
  2481. var Y = ab.getElementsByTagName(r)[0];
  2482. if (Y) {
  2483. var ad = Y.childNodes;
  2484. if (ad) {
  2485. var X = ad.length;
  2486. for (var Z = 0; Z < X; Z++) {
  2487. if (!(ad[Z].nodeType == 1 && ad[Z].nodeName == "PARAM") && !(ad[Z].nodeType == 8)) {
  2488. aa.appendChild(ad[Z].cloneNode(true))
  2489. }
  2490. }
  2491. }
  2492. }
  2493. }
  2494. return aa
  2495. }
  2496. function u(ai, ag, Y) {
  2497. var X, aa = c(Y);
  2498. if (M.wk && M.wk < 312) {
  2499. return X
  2500. }
  2501. if (aa) {
  2502. if (typeof ai.id == D) {
  2503. ai.id = Y
  2504. }
  2505. if (M.ie && M.win) {
  2506. var ah = "";
  2507. for (var ae in ai) {
  2508. if (ai[ae] != Object.prototype[ae]) {
  2509. if (ae.toLowerCase() == "data") {
  2510. ag.movie = ai[ae]
  2511. } else {
  2512. if (ae.toLowerCase() == "styleclass") {
  2513. ah += ' class="' + ai[ae] + '"'
  2514. } else {
  2515. if (ae.toLowerCase() != "classid") {
  2516. ah += " " + ae + '="' + ai[ae] + '"'
  2517. }
  2518. }
  2519. }
  2520. }
  2521. }
  2522. var af = "";
  2523. for (var ad in ag) {
  2524. if (ag[ad] != Object.prototype[ad]) {
  2525. af += '<param name="' + ad + '" value="' + ag[ad] + '" />'
  2526. }
  2527. }
  2528. aa.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' + ah + ">" + af + "</object>";
  2529. N[N.length] = ai.id;
  2530. X = c(ai.id)
  2531. } else {
  2532. var Z = C(r);
  2533. Z.setAttribute("type", q);
  2534. for (var ac in ai) {
  2535. if (ai[ac] != Object.prototype[ac]) {
  2536. if (ac.toLowerCase() == "styleclass") {
  2537. Z.setAttribute("class", ai[ac])
  2538. } else {
  2539. if (ac.toLowerCase() != "classid") {
  2540. Z.setAttribute(ac, ai[ac])
  2541. }
  2542. }
  2543. }
  2544. }
  2545. for (var ab in ag) {
  2546. if (ag[ab] != Object.prototype[ab] && ab.toLowerCase() != "movie") {
  2547. e(Z, ab, ag[ab])
  2548. }
  2549. }
  2550. aa.parentNode.replaceChild(Z, aa);
  2551. X = Z
  2552. }
  2553. }
  2554. return X
  2555. }
  2556. function e(Z, X, Y) {
  2557. var aa = C("param");
  2558. aa.setAttribute("name", X);
  2559. aa.setAttribute("value", Y);
  2560. Z.appendChild(aa)
  2561. }
  2562. function y(Y) {
  2563. var X = c(Y);
  2564. if (X && X.nodeName == "OBJECT") {
  2565. if (M.ie && M.win) {
  2566. X.style.display = "none";
  2567. (function () {
  2568. if (X.readyState == 4) {
  2569. b(Y)
  2570. } else {
  2571. setTimeout(arguments.callee, 10)
  2572. }
  2573. })()
  2574. } else {
  2575. X.parentNode.removeChild(X)
  2576. }
  2577. }
  2578. }
  2579. function b(Z) {
  2580. var Y = c(Z);
  2581. if (Y) {
  2582. for (var X in Y) {
  2583. if (typeof Y[X] == "function") {
  2584. Y[X] = null
  2585. }
  2586. }
  2587. Y.parentNode.removeChild(Y)
  2588. }
  2589. }
  2590. function c(Z) {
  2591. var X = null;
  2592. try {
  2593. X = j.getElementById(Z)
  2594. } catch (Y) {
  2595. }
  2596. return X
  2597. }
  2598. function C(X) {
  2599. return j.createElement(X)
  2600. }
  2601. function i(Z, X, Y) {
  2602. Z.attachEvent(X, Y);
  2603. I[I.length] = [Z, X, Y]
  2604. }
  2605. function F(Z) {
  2606. var Y = M.pv, X = Z.split(".");
  2607. X[0] = parseInt(X[0], 10);
  2608. X[1] = parseInt(X[1], 10) || 0;
  2609. X[2] = parseInt(X[2], 10) || 0;
  2610. 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
  2611. }
  2612. function v(ac, Y, ad, ab) {
  2613. if (M.ie && M.mac) {
  2614. return
  2615. }
  2616. var aa = j.getElementsByTagName("head")[0];
  2617. if (!aa) {
  2618. return
  2619. }
  2620. var X = (ad && typeof ad == "string") ? ad : "screen";
  2621. if (ab) {
  2622. n = null;
  2623. G = null
  2624. }
  2625. if (!n || G != X) {
  2626. var Z = C("style");
  2627. Z.setAttribute("type", "text/css");
  2628. Z.setAttribute("media", X);
  2629. n = aa.appendChild(Z);
  2630. if (M.ie && M.win && typeof j.styleSheets != D && j.styleSheets.length > 0) {
  2631. n = j.styleSheets[j.styleSheets.length - 1]
  2632. }
  2633. G = X
  2634. }
  2635. if (M.ie && M.win) {
  2636. if (n && typeof n.addRule == r) {
  2637. n.addRule(ac, Y)
  2638. }
  2639. } else {
  2640. if (n && typeof j.createTextNode != D) {
  2641. n.appendChild(j.createTextNode(ac + " {" + Y + "}"))
  2642. }
  2643. }
  2644. }
  2645. function w(Z, X) {
  2646. if (!m) {
  2647. return
  2648. }
  2649. var Y = X ? "visible" : "hidden";
  2650. if (J && c(Z)) {
  2651. c(Z).style.visibility = Y
  2652. } else {
  2653. v("#" + Z, "visibility:" + Y)
  2654. }
  2655. }
  2656. function L(Y) {
  2657. var Z = /[\\\"<>\.;]/;
  2658. var X = Z.exec(Y) != null;
  2659. return X && typeof encodeURIComponent != D ? encodeURIComponent(Y) : Y
  2660. }
  2661. var d = function () {
  2662. if (M.ie && M.win) {
  2663. window.attachEvent("onunload", function () {
  2664. var ac = I.length;
  2665. for (var ab = 0; ab < ac; ab++) {
  2666. I[ab][0].detachEvent(I[ab][1], I[ab][2])
  2667. }
  2668. var Z = N.length;
  2669. for (var aa = 0; aa < Z; aa++) {
  2670. y(N[aa])
  2671. }
  2672. for (var Y in M) {
  2673. M[Y] = null
  2674. }
  2675. M = null;
  2676. for (var X in swfobject) {
  2677. swfobject[X] = null
  2678. }
  2679. swfobject = null
  2680. })
  2681. }
  2682. }();
  2683. return {
  2684. registerObject: function (ab, X, aa, Z) {
  2685. if (M.w3 && ab && X) {
  2686. var Y = {};
  2687. Y.id = ab;
  2688. Y.swfVersion = X;
  2689. Y.expressInstall = aa;
  2690. Y.callbackFn = Z;
  2691. o[o.length] = Y;
  2692. w(ab, false)
  2693. } else {
  2694. if (Z) {
  2695. Z({success: false, id: ab})
  2696. }
  2697. }
  2698. }, getObjectById: function (X) {
  2699. if (M.w3) {
  2700. return z(X)
  2701. }
  2702. }, embedSWF: function (ab, ah, ae, ag, Y, aa, Z, ad, af, ac) {
  2703. var X = {success: false, id: ah};
  2704. if (M.w3 && !(M.wk && M.wk < 312) && ab && ah && ae && ag && Y) {
  2705. w(ah, false);
  2706. K(function () {
  2707. ae += "";
  2708. ag += "";
  2709. var aj = {};
  2710. if (af && typeof af === r) {
  2711. for (var al in af) {
  2712. aj[al] = af[al]
  2713. }
  2714. }
  2715. aj.data = ab;
  2716. aj.width = ae;
  2717. aj.height = ag;
  2718. var am = {};
  2719. if (ad && typeof ad === r) {
  2720. for (var ak in ad) {
  2721. am[ak] = ad[ak]
  2722. }
  2723. }
  2724. if (Z && typeof Z === r) {
  2725. for (var ai in Z) {
  2726. if (typeof am.flashvars != D) {
  2727. am.flashvars += "&" + ai + "=" + Z[ai]
  2728. } else {
  2729. am.flashvars = ai + "=" + Z[ai]
  2730. }
  2731. }
  2732. }
  2733. if (F(Y)) {
  2734. var an = u(aj, am, ah);
  2735. if (aj.id == ah) {
  2736. w(ah, true)
  2737. }
  2738. X.success = true;
  2739. X.ref = an
  2740. } else {
  2741. if (aa && A()) {
  2742. aj.data = aa;
  2743. P(aj, am, ah, ac);
  2744. return
  2745. } else {
  2746. w(ah, true)
  2747. }
  2748. }
  2749. if (ac) {
  2750. ac(X)
  2751. }
  2752. })
  2753. } else {
  2754. if (ac) {
  2755. ac(X)
  2756. }
  2757. }
  2758. }, switchOffAutoHideShow: function () {
  2759. m = false
  2760. }, ua: M, getFlashPlayerVersion: function () {
  2761. return {major: M.pv[0], minor: M.pv[1], release: M.pv[2]}
  2762. }, hasFlashPlayerVersion: F, createSWF: function (Z, Y, X) {
  2763. if (M.w3) {
  2764. return u(Z, Y, X)
  2765. } else {
  2766. return undefined
  2767. }
  2768. }, showExpressInstall: function (Z, aa, X, Y) {
  2769. if (M.w3 && A()) {
  2770. P(Z, aa, X, Y)
  2771. }
  2772. }, removeSWF: function (X) {
  2773. if (M.w3) {
  2774. y(X)
  2775. }
  2776. }, createCSS: function (aa, Z, Y, X) {
  2777. if (M.w3) {
  2778. v(aa, Z, Y, X)
  2779. }
  2780. }, addDomLoadEvent: K, addLoadEvent: s, getQueryParamValue: function (aa) {
  2781. var Z = j.location.search || j.location.hash;
  2782. if (Z) {
  2783. if (/\?/.test(Z)) {
  2784. Z = Z.split("?")[1]
  2785. }
  2786. if (aa == null) {
  2787. return L(Z)
  2788. }
  2789. var Y = Z.split("&");
  2790. for (var X = 0; X < Y.length; X++) {
  2791. if (Y[X].substring(0, Y[X].indexOf("=")) == aa) {
  2792. return L(Y[X].substring((Y[X].indexOf("=") + 1)))
  2793. }
  2794. }
  2795. }
  2796. return ""
  2797. }, expressInstallCallback: function () {
  2798. if (a) {
  2799. var X = c(R);
  2800. if (X && l) {
  2801. X.parentNode.replaceChild(l, X);
  2802. if (Q) {
  2803. w(Q, true);
  2804. if (M.ie && M.win) {
  2805. l.style.display = "block"
  2806. }
  2807. }
  2808. if (E) {
  2809. E(B)
  2810. }
  2811. }
  2812. a = false
  2813. }
  2814. }
  2815. }
  2816. }();
  2817. }
  2818. // Copyright: Hiroshi Ichikawa <http://gimite.net/en/>
  2819. // License: New BSD License
  2820. // Reference: http://dev.w3.org/html5/websockets/
  2821. // Reference: http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol
  2822. (function () {
  2823. if ('undefined' == typeof window || window.WebSocket) return;
  2824. var console = window.console;
  2825. if (!console || !console.log || !console.error) {
  2826. console = {
  2827. log: function () {
  2828. }, error: function () {
  2829. }
  2830. };
  2831. }
  2832. if (!swfobject.hasFlashPlayerVersion("10.0.0")) {
  2833. console.error("Flash Player >= 10.0.0 is required.");
  2834. return;
  2835. }
  2836. if (location.protocol == "file:") {
  2837. console.error(
  2838. "WARNING: web-socket-js doesn't work in file:///... URL " +
  2839. "unless you set Flash Security Settings properly. " +
  2840. "Open the page via Web server i.e. http://...");
  2841. }
  2842. /**
  2843. * This class represents a faux web socket.
  2844. * @param {string} url
  2845. * @param {array or string} protocols
  2846. * @param {string} proxyHost
  2847. * @param {int} proxyPort
  2848. * @param {string} headers
  2849. */
  2850. WebSocket = function (url, protocols, proxyHost, proxyPort, headers) {
  2851. var self = this;
  2852. self.__id = WebSocket.__nextId++;
  2853. WebSocket.__instances[self.__id] = self;
  2854. self.readyState = WebSocket.CONNECTING;
  2855. self.bufferedAmount = 0;
  2856. self.__events = {};
  2857. if (!protocols) {
  2858. protocols = [];
  2859. } else if (typeof protocols == "string") {
  2860. protocols = [protocols];
  2861. }
  2862. // Uses setTimeout() to make sure __createFlash() runs after the caller sets ws.onopen etc.
  2863. // Otherwise, when onopen fires immediately, onopen is called before it is set.
  2864. setTimeout(function () {
  2865. WebSocket.__addTask(function () {
  2866. WebSocket.__flash.create(
  2867. self.__id, url, protocols, proxyHost || null, proxyPort || 0, headers || null);
  2868. });
  2869. }, 0);
  2870. };
  2871. /**
  2872. * Send data to the web socket.
  2873. * @param {string} data The data to send to the socket.
  2874. * @return {boolean} True for success, false for failure.
  2875. */
  2876. WebSocket.prototype.send = function (data) {
  2877. if (this.readyState == WebSocket.CONNECTING) {
  2878. throw "INVALID_STATE_ERR: Web Socket connection has not been established";
  2879. }
  2880. // We use encodeURIComponent() here, because FABridge doesn't work if
  2881. // the argument includes some characters. We don't use escape() here
  2882. // because of this:
  2883. // https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Functions#escape_and_unescape_Functions
  2884. // But it looks decodeURIComponent(encodeURIComponent(s)) doesn't
  2885. // preserve all Unicode characters either e.g. "\uffff" in Firefox.
  2886. // Note by wtritch: Hopefully this will not be necessary using ExternalInterface. Will require
  2887. // additional testing.
  2888. var result = WebSocket.__flash.send(this.__id, encodeURIComponent(data));
  2889. if (result < 0) { // success
  2890. return true;
  2891. } else {
  2892. this.bufferedAmount += result;
  2893. return false;
  2894. }
  2895. };
  2896. /**
  2897. * Close this web socket gracefully.
  2898. */
  2899. WebSocket.prototype.close = function () {
  2900. if (this.readyState == WebSocket.CLOSED || this.readyState == WebSocket.CLOSING) {
  2901. return;
  2902. }
  2903. this.readyState = WebSocket.CLOSING;
  2904. WebSocket.__flash.close(this.__id);
  2905. };
  2906. /**
  2907. * Implementation of {@link <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-registration">DOM 2 EventTarget Interface</a>}
  2908. *
  2909. * @param {string} type
  2910. * @param {function} listener
  2911. * @param {boolean} useCapture
  2912. * @return void
  2913. */
  2914. WebSocket.prototype.addEventListener = function (type, listener, useCapture) {
  2915. if (!(type in this.__events)) {
  2916. this.__events[type] = [];
  2917. }
  2918. this.__events[type].push(listener);
  2919. };
  2920. /**
  2921. * Implementation of {@link <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-registration">DOM 2 EventTarget Interface</a>}
  2922. *
  2923. * @param {string} type
  2924. * @param {function} listener
  2925. * @param {boolean} useCapture
  2926. * @return void
  2927. */
  2928. WebSocket.prototype.removeEventListener = function (type, listener, useCapture) {
  2929. if (!(type in this.__events)) return;
  2930. var events = this.__events[type];
  2931. for (var i = events.length - 1; i >= 0; --i) {
  2932. if (events[i] === listener) {
  2933. events.splice(i, 1);
  2934. break;
  2935. }
  2936. }
  2937. };
  2938. /**
  2939. * Implementation of {@link <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-registration">DOM 2 EventTarget Interface</a>}
  2940. *
  2941. * @param {Event} event
  2942. * @return void
  2943. */
  2944. WebSocket.prototype.dispatchEvent = function (event) {
  2945. var events = this.__events[event.type] || [];
  2946. for (var i = 0; i < events.length; ++i) {
  2947. events[i](event);
  2948. }
  2949. var handler = this["on" + event.type];
  2950. if (handler) handler(event);
  2951. };
  2952. /**
  2953. * Handles an event from Flash.
  2954. * @param {Object} flashEvent
  2955. */
  2956. WebSocket.prototype.__handleEvent = function (flashEvent) {
  2957. if ("readyState" in flashEvent) {
  2958. this.readyState = flashEvent.readyState;
  2959. }
  2960. if ("protocol" in flashEvent) {
  2961. this.protocol = flashEvent.protocol;
  2962. }
  2963. var jsEvent;
  2964. if (flashEvent.type == "open" || flashEvent.type == "error") {
  2965. jsEvent = this.__createSimpleEvent(flashEvent.type);
  2966. } else if (flashEvent.type == "close") {
  2967. // TODO implement jsEvent.wasClean
  2968. jsEvent = this.__createSimpleEvent("close");
  2969. } else if (flashEvent.type == "message") {
  2970. var data = decodeURIComponent(flashEvent.message);
  2971. jsEvent = this.__createMessageEvent("message", data);
  2972. } else {
  2973. throw "unknown event type: " + flashEvent.type;
  2974. }
  2975. this.dispatchEvent(jsEvent);
  2976. };
  2977. WebSocket.prototype.__createSimpleEvent = function (type) {
  2978. if (document.createEvent && window.Event) {
  2979. var event = document.createEvent("Event");
  2980. event.initEvent(type, false, false);
  2981. return event;
  2982. } else {
  2983. return {type: type, bubbles: false, cancelable: false};
  2984. }
  2985. };
  2986. WebSocket.prototype.__createMessageEvent = function (type, data) {
  2987. if (document.createEvent && window.MessageEvent && !window.opera) {
  2988. var event = document.createEvent("MessageEvent");
  2989. event.initMessageEvent("message", false, false, data, null, null, window, null);
  2990. return event;
  2991. } else {
  2992. // IE and Opera, the latter one truncates the data parameter after any 0x00 bytes.
  2993. return {type: type, data: data, bubbles: false, cancelable: false};
  2994. }
  2995. };
  2996. /**
  2997. * Define the WebSocket readyState enumeration.
  2998. */
  2999. WebSocket.CONNECTING = 0;
  3000. WebSocket.OPEN = 1;
  3001. WebSocket.CLOSING = 2;
  3002. WebSocket.CLOSED = 3;
  3003. WebSocket.__flash = null;
  3004. WebSocket.__instances = {};
  3005. WebSocket.__tasks = [];
  3006. WebSocket.__nextId = 0;
  3007. /**
  3008. * Load a new flash security policy file.
  3009. * @param {string} url
  3010. */
  3011. WebSocket.loadFlashPolicyFile = function (url) {
  3012. WebSocket.__addTask(function () {
  3013. WebSocket.__flash.loadManualPolicyFile(url);
  3014. });
  3015. };
  3016. /**
  3017. * Loads WebSocketMain.swf and creates WebSocketMain object in Flash.
  3018. */
  3019. WebSocket.__initialize = function () {
  3020. if (WebSocket.__flash) return;
  3021. if (WebSocket.__swfLocation) {
  3022. // For backword compatibility.
  3023. window.WEB_SOCKET_SWF_LOCATION = WebSocket.__swfLocation;
  3024. }
  3025. if (!window.WEB_SOCKET_SWF_LOCATION) {
  3026. console.error("[WebSocket] set WEB_SOCKET_SWF_LOCATION to location of WebSocketMain.swf");
  3027. return;
  3028. }
  3029. var container = document.createElement("div");
  3030. container.id = "webSocketContainer";
  3031. // Hides Flash box. We cannot use display: none or visibility: hidden because it prevents
  3032. // Flash from loading at least in IE. So we move it out of the screen at (-100, -100).
  3033. // But this even doesn't work with Flash Lite (e.g. in Droid Incredible). So with Flash
  3034. // Lite, we put it at (0, 0). This shows 1x1 box visible at left-top corner but this is
  3035. // the best we can do as far as we know now.
  3036. container.style.position = "absolute";
  3037. if (WebSocket.__isFlashLite()) {
  3038. container.style.left = "0px";
  3039. container.style.top = "0px";
  3040. } else {
  3041. container.style.left = "-100px";
  3042. container.style.top = "-100px";
  3043. }
  3044. var holder = document.createElement("div");
  3045. holder.id = "webSocketFlash";
  3046. container.appendChild(holder);
  3047. document.body.appendChild(container);
  3048. // See this article for hasPriority:
  3049. // http://help.adobe.com/en_US/as3/mobile/WS4bebcd66a74275c36cfb8137124318eebc6-7ffd.html
  3050. swfobject.embedSWF(
  3051. WEB_SOCKET_SWF_LOCATION,
  3052. "webSocketFlash",
  3053. "1" /* width */,
  3054. "1" /* height */,
  3055. "10.0.0" /* SWF version */,
  3056. null,
  3057. null,
  3058. {hasPriority: true, swliveconnect: true, allowScriptAccess: "always"},
  3059. null,
  3060. function (e) {
  3061. if (!e.success) {
  3062. console.error("[WebSocket] swfobject.embedSWF failed");
  3063. }
  3064. });
  3065. };
  3066. /**
  3067. * Called by Flash to notify JS that it's fully loaded and ready
  3068. * for communication.
  3069. */
  3070. WebSocket.__onFlashInitialized = function () {
  3071. // We need to set a timeout here to avoid round-trip calls
  3072. // to flash during the initialization process.
  3073. setTimeout(function () {
  3074. WebSocket.__flash = document.getElementById("webSocketFlash");
  3075. WebSocket.__flash.setCallerUrl(location.href);
  3076. WebSocket.__flash.setDebug(!!window.WEB_SOCKET_DEBUG);
  3077. for (var i = 0; i < WebSocket.__tasks.length; ++i) {
  3078. WebSocket.__tasks[i]();
  3079. }
  3080. WebSocket.__tasks = [];
  3081. }, 0);
  3082. };
  3083. /**
  3084. * Called by Flash to notify WebSockets events are fired.
  3085. */
  3086. WebSocket.__onFlashEvent = function () {
  3087. setTimeout(function () {
  3088. try {
  3089. // Gets events using receiveEvents() instead of getting it from event object
  3090. // of Flash event. This is to make sure to keep message order.
  3091. // It seems sometimes Flash events don't arrive in the same order as they are sent.
  3092. var events = WebSocket.__flash.receiveEvents();
  3093. for (var i = 0; i < events.length; ++i) {
  3094. WebSocket.__instances[events[i].webSocketId].__handleEvent(events[i]);
  3095. }
  3096. } catch (e) {
  3097. console.error(e);
  3098. }
  3099. }, 0);
  3100. return true;
  3101. };
  3102. // Called by Flash.
  3103. WebSocket.__log = function (message) {
  3104. console.log(decodeURIComponent(message));
  3105. };
  3106. // Called by Flash.
  3107. WebSocket.__error = function (message) {
  3108. console.error(decodeURIComponent(message));
  3109. };
  3110. WebSocket.__addTask = function (task) {
  3111. if (WebSocket.__flash) {
  3112. task();
  3113. } else {
  3114. WebSocket.__tasks.push(task);
  3115. }
  3116. };
  3117. /**
  3118. * Test if the browser is running flash lite.
  3119. * @return {boolean} True if flash lite is running, false otherwise.
  3120. */
  3121. WebSocket.__isFlashLite = function () {
  3122. if (!window.navigator || !window.navigator.mimeTypes) {
  3123. return false;
  3124. }
  3125. var mimeType = window.navigator.mimeTypes["application/x-shockwave-flash"];
  3126. if (!mimeType || !mimeType.enabledPlugin || !mimeType.enabledPlugin.filename) {
  3127. return false;
  3128. }
  3129. return mimeType.enabledPlugin.filename.match(/flashlite/i) ? true : false;
  3130. };
  3131. if (!window.WEB_SOCKET_DISABLE_AUTO_INITIALIZATION) {
  3132. if (window.addEventListener) {
  3133. window.addEventListener("load", function () {
  3134. WebSocket.__initialize();
  3135. }, false);
  3136. } else {
  3137. window.attachEvent("onload", function () {
  3138. WebSocket.__initialize();
  3139. });
  3140. }
  3141. }
  3142. })();
  3143. /**
  3144. * socket.io
  3145. * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
  3146. * MIT Licensed
  3147. */
  3148. (function (exports, io, global) {
  3149. /**
  3150. * Expose constructor.
  3151. *
  3152. * @api public
  3153. */
  3154. exports.XHR = XHR;
  3155. /**
  3156. * XHR constructor
  3157. *
  3158. * @costructor
  3159. * @api public
  3160. */
  3161. function XHR(socket) {
  3162. if (!socket) return;
  3163. io.Transport.apply(this, arguments);
  3164. this.sendBuffer = [];
  3165. };
  3166. /**
  3167. * Inherits from Transport.
  3168. */
  3169. io.util.inherit(XHR, io.Transport);
  3170. /**
  3171. * Establish a connection
  3172. *
  3173. * @returns {Transport}
  3174. * @api public
  3175. */
  3176. XHR.prototype.open = function () {
  3177. this.socket.setBuffer(false);
  3178. this.onOpen();
  3179. this.get();
  3180. // we need to make sure the request succeeds since we have no indication
  3181. // whether the request opened or not until it succeeded.
  3182. this.setCloseTimeout();
  3183. return this;
  3184. };
  3185. /**
  3186. * Check if we need to send data to the Socket.IO server, if we have data in our
  3187. * buffer we encode it and forward it to the `post` method.
  3188. *
  3189. * @api private
  3190. */
  3191. XHR.prototype.payload = function (payload) {
  3192. var msgs = [];
  3193. for (var i = 0, l = payload.length; i < l; i++) {
  3194. msgs.push(io.parser.encodePacket(payload[i]));
  3195. }
  3196. this.send(io.parser.encodePayload(msgs));
  3197. };
  3198. /**
  3199. * Send data to the Socket.IO server.
  3200. *
  3201. * @param data The message
  3202. * @returns {Transport}
  3203. * @api public
  3204. */
  3205. XHR.prototype.send = function (data) {
  3206. this.post(data);
  3207. return this;
  3208. };
  3209. /**
  3210. * Posts a encoded message to the Socket.IO server.
  3211. *
  3212. * @param {String} data A encoded message.
  3213. * @api private
  3214. */
  3215. function empty() {
  3216. };
  3217. XHR.prototype.post = function (data) {
  3218. var self = this;
  3219. this.socket.setBuffer(true);
  3220. function stateChange() {
  3221. if (this.readyState == 4) {
  3222. this.onreadystatechange = empty;
  3223. self.posting = false;
  3224. if (this.status == 200) {
  3225. self.socket.setBuffer(false);
  3226. } else {
  3227. self.onClose();
  3228. }
  3229. }
  3230. }
  3231. function onload() {
  3232. this.onload = empty;
  3233. self.socket.setBuffer(false);
  3234. };
  3235. this.sendXHR = this.request('POST');
  3236. if (global.XDomainRequest && this.sendXHR instanceof XDomainRequest) {
  3237. this.sendXHR.onload = this.sendXHR.onerror = onload;
  3238. } else {
  3239. this.sendXHR.onreadystatechange = stateChange;
  3240. }
  3241. this.sendXHR.send(data);
  3242. };
  3243. /**
  3244. * Disconnects the established `XHR` connection.
  3245. *
  3246. * @returns {Transport}
  3247. * @api public
  3248. */
  3249. XHR.prototype.close = function () {
  3250. this.onClose();
  3251. return this;
  3252. };
  3253. /**
  3254. * Generates a configured XHR request
  3255. *
  3256. * @param {String} url The url that needs to be requested.
  3257. * @param {String} method The method the request should use.
  3258. * @returns {XMLHttpRequest}
  3259. * @api private
  3260. */
  3261. XHR.prototype.request = function (method) {
  3262. var req = io.util.request(this.socket.isXDomain())
  3263. , query = io.util.query(this.socket.options.query, 't=' + +new Date);
  3264. req.open(method || 'GET', this.prepareUrl() + query, true);
  3265. if (method == 'POST') {
  3266. try {
  3267. if (req.setRequestHeader) {
  3268. req.setRequestHeader('Content-type', 'text/plain;charset=UTF-8');
  3269. } else {
  3270. // XDomainRequest
  3271. req.contentType = 'text/plain';
  3272. }
  3273. } catch (e) {
  3274. }
  3275. }
  3276. return req;
  3277. };
  3278. /**
  3279. * Returns the scheme to use for the transport URLs.
  3280. *
  3281. * @api private
  3282. */
  3283. XHR.prototype.scheme = function () {
  3284. return this.socket.options.secure ? 'https' : 'http';
  3285. };
  3286. /**
  3287. * Check if the XHR transports are supported
  3288. *
  3289. * @param {Boolean} xdomain Check if we support cross domain requests.
  3290. * @returns {Boolean}
  3291. * @api public
  3292. */
  3293. XHR.check = function (socket, xdomain) {
  3294. try {
  3295. var request = io.util.request(xdomain),
  3296. usesXDomReq = (global.XDomainRequest && request instanceof XDomainRequest),
  3297. socketProtocol = (socket && socket.options && socket.options.secure ? 'https:' : 'http:'),
  3298. isXProtocol = (global.location && socketProtocol != global.location.protocol);
  3299. if (request && !(usesXDomReq && isXProtocol)) {
  3300. return true;
  3301. }
  3302. } catch (e) {
  3303. }
  3304. return false;
  3305. };
  3306. /**
  3307. * Check if the XHR transport supports cross domain requests.
  3308. *
  3309. * @returns {Boolean}
  3310. * @api public
  3311. */
  3312. XHR.xdomainCheck = function (socket) {
  3313. return XHR.check(socket, true);
  3314. };
  3315. })(
  3316. 'undefined' != typeof io ? io.Transport : module.exports
  3317. , 'undefined' != typeof io ? io : module.parent.exports
  3318. , this
  3319. );
  3320. /**
  3321. * socket.io
  3322. * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
  3323. * MIT Licensed
  3324. */
  3325. (function (exports, io) {
  3326. /**
  3327. * Expose constructor.
  3328. */
  3329. exports.htmlfile = HTMLFile;
  3330. /**
  3331. * The HTMLFile transport creates a `forever iframe` based transport
  3332. * for Internet Explorer. Regular forever iframe implementations will
  3333. * continuously trigger the browsers buzy indicators. If the forever iframe
  3334. * is created inside a `htmlfile` these indicators will not be trigged.
  3335. *
  3336. * @constructor
  3337. * @extends {io.Transport.XHR}
  3338. * @api public
  3339. */
  3340. function HTMLFile(socket) {
  3341. io.Transport.XHR.apply(this, arguments);
  3342. };
  3343. /**
  3344. * Inherits from XHR transport.
  3345. */
  3346. io.util.inherit(HTMLFile, io.Transport.XHR);
  3347. /**
  3348. * Transport name
  3349. *
  3350. * @api public
  3351. */
  3352. HTMLFile.prototype.name = 'htmlfile';
  3353. /**
  3354. * Creates a new Ac...eX `htmlfile` with a forever loading iframe
  3355. * that can be used to listen to messages. Inside the generated
  3356. * `htmlfile` a reference will be made to the HTMLFile transport.
  3357. *
  3358. * @api private
  3359. */
  3360. HTMLFile.prototype.get = function () {
  3361. this.doc = new window[(['Active'].concat('Object').join('X'))]('htmlfile');
  3362. this.doc.open();
  3363. this.doc.write('<html></html>');
  3364. this.doc.close();
  3365. this.doc.parentWindow.s = this;
  3366. var iframeC = this.doc.createElement('div');
  3367. iframeC.className = 'socketio';
  3368. this.doc.body.appendChild(iframeC);
  3369. this.iframe = this.doc.createElement('iframe');
  3370. iframeC.appendChild(this.iframe);
  3371. var self = this
  3372. , query = io.util.query(this.socket.options.query, 't=' + +new Date);
  3373. this.iframe.src = this.prepareUrl() + query;
  3374. io.util.on(window, 'unload', function () {
  3375. self.destroy();
  3376. });
  3377. };
  3378. /**
  3379. * The Socket.IO server will write script tags inside the forever
  3380. * iframe, this function will be used as callback for the incoming
  3381. * information.
  3382. *
  3383. * @param {String} data The message
  3384. * @param {document} doc Reference to the context
  3385. * @api private
  3386. */
  3387. HTMLFile.prototype._ = function (data, doc) {
  3388. // unescape all forward slashes. see GH-1251
  3389. data = data.replace(/\\\//g, '/');
  3390. this.onData(data);
  3391. try {
  3392. var script = doc.getElementsByTagName('script')[0];
  3393. script.parentNode.removeChild(script);
  3394. } catch (e) {
  3395. }
  3396. };
  3397. /**
  3398. * Destroy the established connection, iframe and `htmlfile`.
  3399. * And calls the `CollectGarbage` function of Internet Explorer
  3400. * to release the memory.
  3401. *
  3402. * @api private
  3403. */
  3404. HTMLFile.prototype.destroy = function () {
  3405. if (this.iframe) {
  3406. try {
  3407. this.iframe.src = 'about:blank';
  3408. } catch (e) {
  3409. }
  3410. this.doc = null;
  3411. this.iframe.parentNode.removeChild(this.iframe);
  3412. this.iframe = null;
  3413. CollectGarbage();
  3414. }
  3415. };
  3416. /**
  3417. * Disconnects the established connection.
  3418. *
  3419. * @returns {Transport} Chaining.
  3420. * @api public
  3421. */
  3422. HTMLFile.prototype.close = function () {
  3423. this.destroy();
  3424. return io.Transport.XHR.prototype.close.call(this);
  3425. };
  3426. /**
  3427. * Checks if the browser supports this transport. The browser
  3428. * must have an `Ac...eXObject` implementation.
  3429. *
  3430. * @return {Boolean}
  3431. * @api public
  3432. */
  3433. HTMLFile.check = function (socket) {
  3434. if (typeof window != "undefined" && (['Active'].concat('Object').join('X')) in window) {
  3435. try {
  3436. var a = new window[(['Active'].concat('Object').join('X'))]('htmlfile');
  3437. return a && io.Transport.XHR.check(socket);
  3438. } catch (e) {
  3439. }
  3440. }
  3441. return false;
  3442. };
  3443. /**
  3444. * Check if cross domain requests are supported.
  3445. *
  3446. * @returns {Boolean}
  3447. * @api public
  3448. */
  3449. HTMLFile.xdomainCheck = function () {
  3450. // we can probably do handling for sub-domains, we should
  3451. // test that it's cross domain but a subdomain here
  3452. return false;
  3453. };
  3454. /**
  3455. * Add the transport to your public io.transports array.
  3456. *
  3457. * @api private
  3458. */
  3459. io.transports.push('htmlfile');
  3460. })(
  3461. 'undefined' != typeof io ? io.Transport : module.exports
  3462. , 'undefined' != typeof io ? io : module.parent.exports
  3463. );
  3464. /**
  3465. * socket.io
  3466. * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
  3467. * MIT Licensed
  3468. */
  3469. (function (exports, io, global) {
  3470. /**
  3471. * Expose constructor.
  3472. */
  3473. exports['xhr-polling'] = XHRPolling;
  3474. /**
  3475. * The XHR-polling transport uses long polling XHR requests to create a
  3476. * "persistent" connection with the server.
  3477. *
  3478. * @constructor
  3479. * @api public
  3480. */
  3481. function XHRPolling() {
  3482. io.Transport.XHR.apply(this, arguments);
  3483. };
  3484. /**
  3485. * Inherits from XHR transport.
  3486. */
  3487. io.util.inherit(XHRPolling, io.Transport.XHR);
  3488. /**
  3489. * Merge the properties from XHR transport
  3490. */
  3491. io.util.merge(XHRPolling, io.Transport.XHR);
  3492. /**
  3493. * Transport name
  3494. *
  3495. * @api public
  3496. */
  3497. XHRPolling.prototype.name = 'xhr-polling';
  3498. /**
  3499. * Indicates whether heartbeats is enabled for this transport
  3500. *
  3501. * @api private
  3502. */
  3503. XHRPolling.prototype.heartbeats = function () {
  3504. return false;
  3505. };
  3506. /**
  3507. * Establish a connection, for iPhone and Android this will be done once the page
  3508. * is loaded.
  3509. *
  3510. * @returns {Transport} Chaining.
  3511. * @api public
  3512. */
  3513. XHRPolling.prototype.open = function () {
  3514. var self = this;
  3515. io.Transport.XHR.prototype.open.call(self);
  3516. return false;
  3517. };
  3518. /**
  3519. * Starts a XHR request to wait for incoming messages.
  3520. *
  3521. * @api private
  3522. */
  3523. function empty() {
  3524. };
  3525. XHRPolling.prototype.get = function () {
  3526. if (!this.isOpen) return;
  3527. var self = this;
  3528. function stateChange() {
  3529. if (this.readyState == 4) {
  3530. this.onreadystatechange = empty;
  3531. if (this.status == 200) {
  3532. self.onData(this.responseText);
  3533. self.get();
  3534. } else {
  3535. self.onClose();
  3536. }
  3537. }
  3538. };
  3539. function onload() {
  3540. this.onload = empty;
  3541. this.onerror = empty;
  3542. self.retryCounter = 1;
  3543. self.onData(this.responseText);
  3544. self.get();
  3545. };
  3546. function onerror() {
  3547. self.retryCounter++;
  3548. if (!self.retryCounter || self.retryCounter > 3) {
  3549. self.onClose();
  3550. } else {
  3551. self.get();
  3552. }
  3553. };
  3554. this.xhr = this.request();
  3555. if (global.XDomainRequest && this.xhr instanceof XDomainRequest) {
  3556. this.xhr.onload = onload;
  3557. this.xhr.onerror = onerror;
  3558. } else {
  3559. this.xhr.onreadystatechange = stateChange;
  3560. }
  3561. this.xhr.send(null);
  3562. };
  3563. /**
  3564. * Handle the unclean close behavior.
  3565. *
  3566. * @api private
  3567. */
  3568. XHRPolling.prototype.onClose = function () {
  3569. io.Transport.XHR.prototype.onClose.call(this);
  3570. if (this.xhr) {
  3571. this.xhr.onreadystatechange = this.xhr.onload = this.xhr.onerror = empty;
  3572. try {
  3573. this.xhr.abort();
  3574. } catch (e) {
  3575. }
  3576. this.xhr = null;
  3577. }
  3578. };
  3579. /**
  3580. * Webkit based browsers show a infinit spinner when you start a XHR request
  3581. * before the browsers onload event is called so we need to defer opening of
  3582. * the transport until the onload event is called. Wrapping the cb in our
  3583. * defer method solve this.
  3584. *
  3585. * @param {Socket} socket The socket instance that needs a transport
  3586. * @param {Function} fn The callback
  3587. * @api private
  3588. */
  3589. XHRPolling.prototype.ready = function (socket, fn) {
  3590. var self = this;
  3591. io.util.defer(function () {
  3592. fn.call(self);
  3593. });
  3594. };
  3595. /**
  3596. * Add the transport to your public io.transports array.
  3597. *
  3598. * @api private
  3599. */
  3600. io.transports.push('xhr-polling');
  3601. })(
  3602. 'undefined' != typeof io ? io.Transport : module.exports
  3603. , 'undefined' != typeof io ? io : module.parent.exports
  3604. , this
  3605. );
  3606. /**
  3607. * socket.io
  3608. * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
  3609. * MIT Licensed
  3610. */
  3611. (function (exports, io, global) {
  3612. /**
  3613. * There is a way to hide the loading indicator in Firefox. If you create and
  3614. * remove a iframe it will stop showing the current loading indicator.
  3615. * Unfortunately we can't feature detect that and UA sniffing is evil.
  3616. *
  3617. * @api private
  3618. */
  3619. var indicator = global.document && "MozAppearance" in
  3620. global.document.documentElement.style;
  3621. /**
  3622. * Expose constructor.
  3623. */
  3624. exports['jsonp-polling'] = JSONPPolling;
  3625. /**
  3626. * The JSONP transport creates an persistent connection by dynamically
  3627. * inserting a script tag in the page. This script tag will receive the
  3628. * information of the Socket.IO server. When new information is received
  3629. * it creates a new script tag for the new data stream.
  3630. *
  3631. * @constructor
  3632. * @extends {io.Transport.xhr-polling}
  3633. * @api public
  3634. */
  3635. function JSONPPolling(socket) {
  3636. io.Transport['xhr-polling'].apply(this, arguments);
  3637. this.index = io.j.length;
  3638. var self = this;
  3639. io.j.push(function (msg) {
  3640. self._(msg);
  3641. });
  3642. };
  3643. /**
  3644. * Inherits from XHR polling transport.
  3645. */
  3646. io.util.inherit(JSONPPolling, io.Transport['xhr-polling']);
  3647. /**
  3648. * Transport name
  3649. *
  3650. * @api public
  3651. */
  3652. JSONPPolling.prototype.name = 'jsonp-polling';
  3653. /**
  3654. * Posts a encoded message to the Socket.IO server using an iframe.
  3655. * The iframe is used because script tags can create POST based requests.
  3656. * The iframe is positioned outside of the view so the user does not
  3657. * notice it's existence.
  3658. *
  3659. * @param {String} data A encoded message.
  3660. * @api private
  3661. */
  3662. JSONPPolling.prototype.post = function (data) {
  3663. var self = this
  3664. , query = io.util.query(
  3665. this.socket.options.query
  3666. , 't=' + (+new Date) + '&i=' + this.index
  3667. );
  3668. if (!this.form) {
  3669. var form = document.createElement('form')
  3670. , area = document.createElement('textarea')
  3671. , id = this.iframeId = 'socketio_iframe_' + this.index
  3672. , iframe;
  3673. form.className = 'socketio';
  3674. form.style.position = 'absolute';
  3675. form.style.top = '0px';
  3676. form.style.left = '0px';
  3677. form.style.display = 'none';
  3678. form.target = id;
  3679. form.method = 'POST';
  3680. form.setAttribute('accept-charset', 'utf-8');
  3681. area.name = 'd';
  3682. form.appendChild(area);
  3683. document.body.appendChild(form);
  3684. this.form = form;
  3685. this.area = area;
  3686. }
  3687. this.form.action = this.prepareUrl() + query;
  3688. function complete() {
  3689. initIframe();
  3690. self.socket.setBuffer(false);
  3691. };
  3692. function initIframe() {
  3693. if (self.iframe) {
  3694. self.form.removeChild(self.iframe);
  3695. }
  3696. try {
  3697. // ie6 dynamic iframes with target="" support (thanks Chris Lambacher)
  3698. iframe = document.createElement('<iframe name="' + self.iframeId + '">');
  3699. } catch (e) {
  3700. iframe = document.createElement('iframe');
  3701. iframe.name = self.iframeId;
  3702. }
  3703. iframe.id = self.iframeId;
  3704. self.form.appendChild(iframe);
  3705. self.iframe = iframe;
  3706. };
  3707. initIframe();
  3708. // we temporarily stringify until we figure out how to prevent
  3709. // browsers from turning `\n` into `\r\n` in form inputs
  3710. this.area.value = io.JSON.stringify(data);
  3711. try {
  3712. this.form.submit();
  3713. } catch (e) {
  3714. }
  3715. if (this.iframe.attachEvent) {
  3716. iframe.onreadystatechange = function () {
  3717. if (self.iframe.readyState == 'complete') {
  3718. complete();
  3719. }
  3720. };
  3721. } else {
  3722. this.iframe.onload = complete;
  3723. }
  3724. this.socket.setBuffer(true);
  3725. };
  3726. /**
  3727. * Creates a new JSONP poll that can be used to listen
  3728. * for messages from the Socket.IO server.
  3729. *
  3730. * @api private
  3731. */
  3732. JSONPPolling.prototype.get = function () {
  3733. var self = this
  3734. , script = document.createElement('script')
  3735. , query = io.util.query(
  3736. this.socket.options.query
  3737. , 't=' + (+new Date) + '&i=' + this.index
  3738. );
  3739. if (this.script) {
  3740. this.script.parentNode.removeChild(this.script);
  3741. this.script = null;
  3742. }
  3743. script.async = true;
  3744. script.src = this.prepareUrl() + query;
  3745. script.onerror = function () {
  3746. self.onClose();
  3747. };
  3748. var insertAt = document.getElementsByTagName('script')[0];
  3749. insertAt.parentNode.insertBefore(script, insertAt);
  3750. this.script = script;
  3751. if (indicator) {
  3752. setTimeout(function () {
  3753. var iframe = document.createElement('iframe');
  3754. document.body.appendChild(iframe);
  3755. document.body.removeChild(iframe);
  3756. }, 100);
  3757. }
  3758. };
  3759. /**
  3760. * Callback function for the incoming message stream from the Socket.IO server.
  3761. *
  3762. * @param {String} data The message
  3763. * @api private
  3764. */
  3765. JSONPPolling.prototype._ = function (msg) {
  3766. this.onData(msg);
  3767. if (this.isOpen) {
  3768. this.get();
  3769. }
  3770. return this;
  3771. };
  3772. /**
  3773. * The indicator hack only works after onload
  3774. *
  3775. * @param {Socket} socket The socket instance that needs a transport
  3776. * @param {Function} fn The callback
  3777. * @api private
  3778. */
  3779. JSONPPolling.prototype.ready = function (socket, fn) {
  3780. var self = this;
  3781. if (!indicator) return fn.call(this);
  3782. io.util.load(function () {
  3783. fn.call(self);
  3784. });
  3785. };
  3786. /**
  3787. * Checks if browser supports this transport.
  3788. *
  3789. * @return {Boolean}
  3790. * @api public
  3791. */
  3792. JSONPPolling.check = function () {
  3793. return 'document' in global;
  3794. };
  3795. /**
  3796. * Check if cross domain requests are supported
  3797. *
  3798. * @returns {Boolean}
  3799. * @api public
  3800. */
  3801. JSONPPolling.xdomainCheck = function () {
  3802. return true;
  3803. };
  3804. /**
  3805. * Add the transport to your public io.transports array.
  3806. *
  3807. * @api private
  3808. */
  3809. io.transports.push('jsonp-polling');
  3810. })(
  3811. 'undefined' != typeof io ? io.Transport : module.exports
  3812. , 'undefined' != typeof io ? io : module.parent.exports
  3813. , this
  3814. );
  3815. if (typeof define === "function" && define.amd) {
  3816. define([], function () {
  3817. return io;
  3818. });
  3819. }
  3820. })();