juggernaut-kafka 2.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,142 @@
1
+ //= require socket_io
2
+
3
+ var Juggernaut = function(options){
4
+ this.options = options || {};
5
+
6
+ this.options.host = this.options.host || window.location.hostname;
7
+ this.options.port = this.options.port || 8080;
8
+
9
+ this.handlers = {};
10
+ this.meta = this.options.meta;
11
+
12
+ this.io = io.connect(this.options.host, this.options);
13
+
14
+ this.io.on("connect", this.proxy(this.onconnect));
15
+ this.io.on("message", this.proxy(this.onmessage));
16
+ this.io.on("disconnect", this.proxy(this.ondisconnect));
17
+
18
+ this.on("connect", this.proxy(this.writeMeta));
19
+ };
20
+
21
+ // Helper methods
22
+
23
+ Juggernaut.fn = Juggernaut.prototype;
24
+ Juggernaut.fn.proxy = function(func){
25
+ var thisObject = this;
26
+ return(function(){ return func.apply(thisObject, arguments); });
27
+ };
28
+
29
+ // Public methods
30
+
31
+ Juggernaut.fn.on = function(name, callback){
32
+ if ( !name || !callback ) return;
33
+ if ( !this.handlers[name] ) this.handlers[name] = [];
34
+ this.handlers[name].push(callback);
35
+ };
36
+ Juggernaut.fn.bind = Juggernaut.fn.on;
37
+
38
+ Juggernaut.fn.unbind = function(name){
39
+ if (!this.handlers) return;
40
+ delete this.handlers[name];
41
+ };
42
+
43
+ Juggernaut.fn.write = function(message){
44
+ if (typeof message.toJSON == "function")
45
+ message = message.toJSON();
46
+
47
+ this.io.send(message);
48
+ };
49
+
50
+ Juggernaut.fn.subscribe = function(channel, callback){
51
+ if ( !channel ) throw "Must provide a channel";
52
+
53
+ this.on(channel + ":data", callback);
54
+
55
+ var connectCallback = this.proxy(function(){
56
+ var message = new Juggernaut.Message;
57
+ message.type = "subscribe";
58
+ message.channel = channel;
59
+
60
+ this.write(message);
61
+ });
62
+
63
+ if (this.io.socket.connected)
64
+ connectCallback();
65
+ else {
66
+ this.on("connect", connectCallback);
67
+ }
68
+ };
69
+
70
+ Juggernaut.fn.unsubscribe = function(channel) {
71
+ if ( !channel ) throw "Must provide a channel";
72
+
73
+ this.unbind(channel + ":data");
74
+
75
+ var message = new Juggernaut.Message;
76
+ message.type = "unsubscribe";
77
+ message.channel = channel;
78
+
79
+ this.write(message);
80
+ };
81
+
82
+ // Private
83
+
84
+ Juggernaut.fn.trigger = function(){
85
+ var args = [];
86
+ for (var f=0; f < arguments.length; f++) args.push(arguments[f]);
87
+
88
+ var name = args.shift();
89
+
90
+ var callbacks = this.handlers[name];
91
+ if ( !callbacks ) return;
92
+
93
+ for(var i=0, len = callbacks.length; i < len; i++)
94
+ callbacks[i].apply(this, args);
95
+ };
96
+
97
+ Juggernaut.fn.writeMeta = function(){
98
+ if ( !this.meta ) return;
99
+ var message = new Juggernaut.Message;
100
+ message.type = "meta";
101
+ message.data = this.meta;
102
+ this.write(message);
103
+ };
104
+
105
+ Juggernaut.fn.onconnect = function(){
106
+ this.sessionID = this.io.socket.sessionid;
107
+ this.trigger("connect");
108
+ };
109
+
110
+ Juggernaut.fn.ondisconnect = function(){
111
+ this.trigger("disconnect");
112
+ };
113
+
114
+ Juggernaut.fn.onmessage = function(data){
115
+ var message = Juggernaut.Message.fromJSON(data);
116
+ this.trigger("message", message);
117
+ this.trigger("data", message.channel, message.data);
118
+ this.trigger(message.channel + ":data", message.data);
119
+ };
120
+
121
+ Juggernaut.Message = function(hash){
122
+ for (var key in hash) this[key] = hash[key];
123
+ };
124
+
125
+ Juggernaut.Message.fromJSON = function(json){
126
+ return(new this(JSON.parse(json)))
127
+ };
128
+
129
+ Juggernaut.Message.prototype.toJSON = function(){
130
+ var object = {};
131
+ for (var key in this) {
132
+ if (typeof this[key] != "function")
133
+ object[key] = this[key];
134
+ }
135
+ return(JSON.stringify(object));
136
+ };
137
+
138
+ if (typeof module != "undefined") {
139
+ module.exports = Juggernaut;
140
+ } else {
141
+ window.Juggernaut = Juggernaut;
142
+ }
@@ -0,0 +1,3204 @@
1
+ /*! Socket.IO.js build:0.8.7, development. Copyright(c) 2011 LearnBoost <dev@learnboost.com> MIT Licensed */
2
+
3
+ /**
4
+ * socket.io
5
+ * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
6
+ * MIT Licensed
7
+ */
8
+
9
+ (function (exports, global) {
10
+
11
+ /**
12
+ * IO namespace.
13
+ *
14
+ * @namespace
15
+ */
16
+
17
+ var io = exports;
18
+
19
+ /**
20
+ * Socket.IO version
21
+ *
22
+ * @api public
23
+ */
24
+
25
+ io.version = '0.8.7';
26
+
27
+ /**
28
+ * Protocol implemented.
29
+ *
30
+ * @api public
31
+ */
32
+
33
+ io.protocol = 1;
34
+
35
+ /**
36
+ * Available transports, these will be populated with the available transports
37
+ *
38
+ * @api public
39
+ */
40
+
41
+ io.transports = [];
42
+
43
+ /**
44
+ * Keep track of jsonp callbacks.
45
+ *
46
+ * @api private
47
+ */
48
+
49
+ io.j = [];
50
+
51
+ /**
52
+ * Keep track of our io.Sockets
53
+ *
54
+ * @api private
55
+ */
56
+ io.sockets = {};
57
+
58
+
59
+ /**
60
+ * Manages connections to hosts.
61
+ *
62
+ * @param {String} uri
63
+ * @Param {Boolean} force creation of new socket (defaults to false)
64
+ * @api public
65
+ */
66
+
67
+ io.connect = function (host, details) {
68
+ var uri = io.util.parseUri(host)
69
+ , uuri
70
+ , socket;
71
+
72
+ if (global && global.location) {
73
+ uri.protocol = uri.protocol || global.location.protocol.slice(0, -1);
74
+ uri.host = uri.host || (global.document
75
+ ? global.document.domain : global.location.hostname);
76
+ uri.port = uri.port || global.location.port;
77
+ }
78
+
79
+ uuri = io.util.uniqueUri(uri);
80
+
81
+ var options = {
82
+ host: uri.host
83
+ , secure: 'https' == uri.protocol
84
+ , port: uri.port || ('https' == uri.protocol ? 443 : 80)
85
+ , query: uri.query || ''
86
+ };
87
+
88
+ io.util.merge(options, details);
89
+
90
+ if (options['force new connection'] || !io.sockets[uuri]) {
91
+ socket = new io.Socket(options);
92
+ }
93
+
94
+ if (!options['force new connection'] && socket) {
95
+ io.sockets[uuri] = socket;
96
+ }
97
+
98
+ socket = socket || io.sockets[uuri];
99
+
100
+ // if path is different from '' or /
101
+ return socket.of(uri.path.length > 1 ? uri.path : '');
102
+ };
103
+
104
+ })('object' === typeof module ? module.exports : (this.io = {}), this);
105
+
106
+ /**
107
+ * socket.io
108
+ * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
109
+ * MIT Licensed
110
+ */
111
+
112
+ (function (exports, global) {
113
+
114
+ /**
115
+ * Utilities namespace.
116
+ *
117
+ * @namespace
118
+ */
119
+
120
+ var util = exports.util = {};
121
+
122
+ /**
123
+ * Parses an URI
124
+ *
125
+ * @author Steven Levithan <stevenlevithan.com> (MIT license)
126
+ * @api public
127
+ */
128
+
129
+ var re = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
130
+
131
+ var parts = ['source', 'protocol', 'authority', 'userInfo', 'user', 'password',
132
+ 'host', 'port', 'relative', 'path', 'directory', 'file', 'query',
133
+ 'anchor'];
134
+
135
+ util.parseUri = function (str) {
136
+ var m = re.exec(str || '')
137
+ , uri = {}
138
+ , i = 14;
139
+
140
+ while (i--) {
141
+ uri[parts[i]] = m[i] || '';
142
+ }
143
+
144
+ return uri;
145
+ };
146
+
147
+ /**
148
+ * Produces a unique url that identifies a Socket.IO connection.
149
+ *
150
+ * @param {Object} uri
151
+ * @api public
152
+ */
153
+
154
+ util.uniqueUri = function (uri) {
155
+ var protocol = uri.protocol
156
+ , host = uri.host
157
+ , port = uri.port;
158
+
159
+ if ('document' in global) {
160
+ host = host || document.domain;
161
+ port = port || (protocol == 'https'
162
+ && document.location.protocol !== 'https:' ? 443 : document.location.port);
163
+ } else {
164
+ host = host || 'localhost';
165
+
166
+ if (!port && protocol == 'https') {
167
+ port = 443;
168
+ }
169
+ }
170
+
171
+ return (protocol || 'http') + '://' + host + ':' + (port || 80);
172
+ };
173
+
174
+ /**
175
+ * Mergest 2 query strings in to once unique query string
176
+ *
177
+ * @param {String} base
178
+ * @param {String} addition
179
+ * @api public
180
+ */
181
+
182
+ util.query = function (base, addition) {
183
+ var query = util.chunkQuery(base || '')
184
+ , components = [];
185
+
186
+ util.merge(query, util.chunkQuery(addition || ''));
187
+ for (var part in query) {
188
+ if (query.hasOwnProperty(part)) {
189
+ components.push(part + '=' + query[part]);
190
+ }
191
+ }
192
+
193
+ return components.length ? '?' + components.join('&') : '';
194
+ };
195
+
196
+ /**
197
+ * Transforms a querystring in to an object
198
+ *
199
+ * @param {String} qs
200
+ * @api public
201
+ */
202
+
203
+ util.chunkQuery = function (qs) {
204
+ var query = {}
205
+ , params = qs.split('&')
206
+ , i = 0
207
+ , l = params.length
208
+ , kv;
209
+
210
+ for (; i < l; ++i) {
211
+ kv = params[i].split('=');
212
+ if (kv[0]) {
213
+ query[kv[0]] = decodeURIComponent(kv[1]);
214
+ }
215
+ }
216
+
217
+ return query;
218
+ };
219
+
220
+ /**
221
+ * Executes the given function when the page is loaded.
222
+ *
223
+ * io.util.load(function () { console.log('page loaded'); });
224
+ *
225
+ * @param {Function} fn
226
+ * @api public
227
+ */
228
+
229
+ var pageLoaded = false;
230
+
231
+ util.load = function (fn) {
232
+ if ('document' in global && document.readyState === 'complete' || pageLoaded) {
233
+ return fn();
234
+ }
235
+
236
+ util.on(global, 'load', fn, false);
237
+ };
238
+
239
+ /**
240
+ * Adds an event.
241
+ *
242
+ * @api private
243
+ */
244
+
245
+ util.on = function (element, event, fn, capture) {
246
+ if (element.attachEvent) {
247
+ element.attachEvent('on' + event, fn);
248
+ } else if (element.addEventListener) {
249
+ element.addEventListener(event, fn, capture);
250
+ }
251
+ };
252
+
253
+ /**
254
+ * Generates the correct `XMLHttpRequest` for regular and cross domain requests.
255
+ *
256
+ * @param {Boolean} [xdomain] Create a request that can be used cross domain.
257
+ * @returns {XMLHttpRequest|false} If we can create a XMLHttpRequest.
258
+ * @api private
259
+ */
260
+
261
+ util.request = function (xdomain) {
262
+
263
+ if (xdomain && 'undefined' != typeof XDomainRequest) {
264
+ return new XDomainRequest();
265
+ }
266
+
267
+ if ('undefined' != typeof XMLHttpRequest && (!xdomain || util.ua.hasCORS)) {
268
+ return new XMLHttpRequest();
269
+ }
270
+
271
+ if (!xdomain) {
272
+ try {
273
+ return new ActiveXObject('Microsoft.XMLHTTP');
274
+ } catch(e) { }
275
+ }
276
+
277
+ return null;
278
+ };
279
+
280
+ /**
281
+ * XHR based transport constructor.
282
+ *
283
+ * @constructor
284
+ * @api public
285
+ */
286
+
287
+ /**
288
+ * Change the internal pageLoaded value.
289
+ */
290
+
291
+ if ('undefined' != typeof window) {
292
+ util.load(function () {
293
+ pageLoaded = true;
294
+ });
295
+ }
296
+
297
+ /**
298
+ * Defers a function to ensure a spinner is not displayed by the browser
299
+ *
300
+ * @param {Function} fn
301
+ * @api public
302
+ */
303
+
304
+ util.defer = function (fn) {
305
+ if (!util.ua.webkit || 'undefined' != typeof importScripts) {
306
+ return fn();
307
+ }
308
+
309
+ util.load(function () {
310
+ setTimeout(fn, 100);
311
+ });
312
+ };
313
+
314
+ /**
315
+ * Merges two objects.
316
+ *
317
+ * @api public
318
+ */
319
+
320
+ util.merge = function merge (target, additional, deep, lastseen) {
321
+ var seen = lastseen || []
322
+ , depth = typeof deep == 'undefined' ? 2 : deep
323
+ , prop;
324
+
325
+ for (prop in additional) {
326
+ if (additional.hasOwnProperty(prop) && util.indexOf(seen, prop) < 0) {
327
+ if (typeof target[prop] !== 'object' || !depth) {
328
+ target[prop] = additional[prop];
329
+ seen.push(additional[prop]);
330
+ } else {
331
+ util.merge(target[prop], additional[prop], depth - 1, seen);
332
+ }
333
+ }
334
+ }
335
+
336
+ return target;
337
+ };
338
+
339
+ /**
340
+ * Merges prototypes from objects
341
+ *
342
+ * @api public
343
+ */
344
+
345
+ util.mixin = function (ctor, ctor2) {
346
+ util.merge(ctor.prototype, ctor2.prototype);
347
+ };
348
+
349
+ /**
350
+ * Shortcut for prototypical and static inheritance.
351
+ *
352
+ * @api private
353
+ */
354
+
355
+ util.inherit = function (ctor, ctor2) {
356
+ function f() {};
357
+ f.prototype = ctor2.prototype;
358
+ ctor.prototype = new f;
359
+ };
360
+
361
+ /**
362
+ * Checks if the given object is an Array.
363
+ *
364
+ * io.util.isArray([]); // true
365
+ * io.util.isArray({}); // false
366
+ *
367
+ * @param Object obj
368
+ * @api public
369
+ */
370
+
371
+ util.isArray = Array.isArray || function (obj) {
372
+ return Object.prototype.toString.call(obj) === '[object Array]';
373
+ };
374
+
375
+ /**
376
+ * Intersects values of two arrays into a third
377
+ *
378
+ * @api public
379
+ */
380
+
381
+ util.intersect = function (arr, arr2) {
382
+ var ret = []
383
+ , longest = arr.length > arr2.length ? arr : arr2
384
+ , shortest = arr.length > arr2.length ? arr2 : arr;
385
+
386
+ for (var i = 0, l = shortest.length; i < l; i++) {
387
+ if (~util.indexOf(longest, shortest[i]))
388
+ ret.push(shortest[i]);
389
+ }
390
+
391
+ return ret;
392
+ }
393
+
394
+ /**
395
+ * Array indexOf compatibility.
396
+ *
397
+ * @see bit.ly/a5Dxa2
398
+ * @api public
399
+ */
400
+
401
+ util.indexOf = function (arr, o, i) {
402
+ if (Array.prototype.indexOf) {
403
+ return Array.prototype.indexOf.call(arr, o, i);
404
+ }
405
+
406
+ for (var j = arr.length, i = i < 0 ? i + j < 0 ? 0 : i + j : i || 0;
407
+ i < j && arr[i] !== o; i++) {}
408
+
409
+ return j <= i ? -1 : i;
410
+ };
411
+
412
+ /**
413
+ * Converts enumerables to array.
414
+ *
415
+ * @api public
416
+ */
417
+
418
+ util.toArray = function (enu) {
419
+ var arr = [];
420
+
421
+ for (var i = 0, l = enu.length; i < l; i++)
422
+ arr.push(enu[i]);
423
+
424
+ return arr;
425
+ };
426
+
427
+ /**
428
+ * UA / engines detection namespace.
429
+ *
430
+ * @namespace
431
+ */
432
+
433
+ util.ua = {};
434
+
435
+ /**
436
+ * Whether the UA supports CORS for XHR.
437
+ *
438
+ * @api public
439
+ */
440
+
441
+ util.ua.hasCORS = 'undefined' != typeof XMLHttpRequest && (function () {
442
+ try {
443
+ var a = new XMLHttpRequest();
444
+ } catch (e) {
445
+ return false;
446
+ }
447
+
448
+ return a.withCredentials != undefined;
449
+ })();
450
+
451
+ /**
452
+ * Detect webkit.
453
+ *
454
+ * @api public
455
+ */
456
+
457
+ util.ua.webkit = 'undefined' != typeof navigator
458
+ && /webkit/i.test(navigator.userAgent);
459
+
460
+ })('undefined' != typeof io ? io : module.exports, this);
461
+
462
+ /**
463
+ * socket.io
464
+ * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
465
+ * MIT Licensed
466
+ */
467
+
468
+ (function (exports, io) {
469
+
470
+ /**
471
+ * Expose constructor.
472
+ */
473
+
474
+ exports.EventEmitter = EventEmitter;
475
+
476
+ /**
477
+ * Event emitter constructor.
478
+ *
479
+ * @api public.
480
+ */
481
+
482
+ function EventEmitter () {};
483
+
484
+ /**
485
+ * Adds a listener
486
+ *
487
+ * @api public
488
+ */
489
+
490
+ EventEmitter.prototype.on = function (name, fn) {
491
+ if (!this.$events) {
492
+ this.$events = {};
493
+ }
494
+
495
+ if (!this.$events[name]) {
496
+ this.$events[name] = fn;
497
+ } else if (io.util.isArray(this.$events[name])) {
498
+ this.$events[name].push(fn);
499
+ } else {
500
+ this.$events[name] = [this.$events[name], fn];
501
+ }
502
+
503
+ return this;
504
+ };
505
+
506
+ EventEmitter.prototype.addListener = EventEmitter.prototype.on;
507
+
508
+ /**
509
+ * Adds a volatile listener.
510
+ *
511
+ * @api public
512
+ */
513
+
514
+ EventEmitter.prototype.once = function (name, fn) {
515
+ var self = this;
516
+
517
+ function on () {
518
+ self.removeListener(name, on);
519
+ fn.apply(this, arguments);
520
+ };
521
+
522
+ on.listener = fn;
523
+ this.on(name, on);
524
+
525
+ return this;
526
+ };
527
+
528
+ /**
529
+ * Removes a listener.
530
+ *
531
+ * @api public
532
+ */
533
+
534
+ EventEmitter.prototype.removeListener = function (name, fn) {
535
+ if (this.$events && this.$events[name]) {
536
+ var list = this.$events[name];
537
+
538
+ if (io.util.isArray(list)) {
539
+ var pos = -1;
540
+
541
+ for (var i = 0, l = list.length; i < l; i++) {
542
+ if (list[i] === fn || (list[i].listener && list[i].listener === fn)) {
543
+ pos = i;
544
+ break;
545
+ }
546
+ }
547
+
548
+ if (pos < 0) {
549
+ return this;
550
+ }
551
+
552
+ list.splice(pos, 1);
553
+
554
+ if (!list.length) {
555
+ delete this.$events[name];
556
+ }
557
+ } else if (list === fn || (list.listener && list.listener === fn)) {
558
+ delete this.$events[name];
559
+ }
560
+ }
561
+
562
+ return this;
563
+ };
564
+
565
+ /**
566
+ * Removes all listeners for an event.
567
+ *
568
+ * @api public
569
+ */
570
+
571
+ EventEmitter.prototype.removeAllListeners = function (name) {
572
+ // TODO: enable this when node 0.5 is stable
573
+ //if (name === undefined) {
574
+ //this.$events = {};
575
+ //return this;
576
+ //}
577
+
578
+ if (this.$events && this.$events[name]) {
579
+ this.$events[name] = null;
580
+ }
581
+
582
+ return this;
583
+ };
584
+
585
+ /**
586
+ * Gets all listeners for a certain event.
587
+ *
588
+ * @api publci
589
+ */
590
+
591
+ EventEmitter.prototype.listeners = function (name) {
592
+ if (!this.$events) {
593
+ this.$events = {};
594
+ }
595
+
596
+ if (!this.$events[name]) {
597
+ this.$events[name] = [];
598
+ }
599
+
600
+ if (!io.util.isArray(this.$events[name])) {
601
+ this.$events[name] = [this.$events[name]];
602
+ }
603
+
604
+ return this.$events[name];
605
+ };
606
+
607
+ /**
608
+ * Emits an event.
609
+ *
610
+ * @api public
611
+ */
612
+
613
+ EventEmitter.prototype.emit = function (name) {
614
+ if (!this.$events) {
615
+ return false;
616
+ }
617
+
618
+ var handler = this.$events[name];
619
+
620
+ if (!handler) {
621
+ return false;
622
+ }
623
+
624
+ var args = Array.prototype.slice.call(arguments, 1);
625
+
626
+ if ('function' == typeof handler) {
627
+ handler.apply(this, args);
628
+ } else if (io.util.isArray(handler)) {
629
+ var listeners = handler.slice();
630
+
631
+ for (var i = 0, l = listeners.length; i < l; i++) {
632
+ listeners[i].apply(this, args);
633
+ }
634
+ } else {
635
+ return false;
636
+ }
637
+
638
+ return true;
639
+ };
640
+
641
+ })(
642
+ 'undefined' != typeof io ? io : module.exports
643
+ , 'undefined' != typeof io ? io : module.parent.exports
644
+ );
645
+
646
+ /**
647
+ * socket.io
648
+ * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
649
+ * MIT Licensed
650
+ */
651
+
652
+ /**
653
+ * Based on JSON2 (http://www.JSON.org/js.html).
654
+ */
655
+
656
+ (function (exports, nativeJSON) {
657
+ "use strict";
658
+
659
+ // use native JSON if it's available
660
+ if (nativeJSON && nativeJSON.parse){
661
+ return exports.JSON = {
662
+ parse: nativeJSON.parse
663
+ , stringify: nativeJSON.stringify
664
+ }
665
+ }
666
+
667
+ var JSON = exports.JSON = {};
668
+
669
+ function f(n) {
670
+ // Format integers to have at least two digits.
671
+ return n < 10 ? '0' + n : n;
672
+ }
673
+
674
+ function date(d, key) {
675
+ return isFinite(d.valueOf()) ?
676
+ d.getUTCFullYear() + '-' +
677
+ f(d.getUTCMonth() + 1) + '-' +
678
+ f(d.getUTCDate()) + 'T' +
679
+ f(d.getUTCHours()) + ':' +
680
+ f(d.getUTCMinutes()) + ':' +
681
+ f(d.getUTCSeconds()) + 'Z' : null;
682
+ };
683
+
684
+ var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
685
+ escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
686
+ gap,
687
+ indent,
688
+ meta = { // table of character substitutions
689
+ '\b': '\\b',
690
+ '\t': '\\t',
691
+ '\n': '\\n',
692
+ '\f': '\\f',
693
+ '\r': '\\r',
694
+ '"' : '\\"',
695
+ '\\': '\\\\'
696
+ },
697
+ rep;
698
+
699
+
700
+ function quote(string) {
701
+
702
+ // If the string contains no control characters, no quote characters, and no
703
+ // backslash characters, then we can safely slap some quotes around it.
704
+ // Otherwise we must also replace the offending characters with safe escape
705
+ // sequences.
706
+
707
+ escapable.lastIndex = 0;
708
+ return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
709
+ var c = meta[a];
710
+ return typeof c === 'string' ? c :
711
+ '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
712
+ }) + '"' : '"' + string + '"';
713
+ }
714
+
715
+
716
+ function str(key, holder) {
717
+
718
+ // Produce a string from holder[key].
719
+
720
+ var i, // The loop counter.
721
+ k, // The member key.
722
+ v, // The member value.
723
+ length,
724
+ mind = gap,
725
+ partial,
726
+ value = holder[key];
727
+
728
+ // If the value has a toJSON method, call it to obtain a replacement value.
729
+
730
+ if (value instanceof Date) {
731
+ value = date(key);
732
+ }
733
+
734
+ // If we were called with a replacer function, then call the replacer to
735
+ // obtain a replacement value.
736
+
737
+ if (typeof rep === 'function') {
738
+ value = rep.call(holder, key, value);
739
+ }
740
+
741
+ // What happens next depends on the value's type.
742
+
743
+ switch (typeof value) {
744
+ case 'string':
745
+ return quote(value);
746
+
747
+ case 'number':
748
+
749
+ // JSON numbers must be finite. Encode non-finite numbers as null.
750
+
751
+ return isFinite(value) ? String(value) : 'null';
752
+
753
+ case 'boolean':
754
+ case 'null':
755
+
756
+ // If the value is a boolean or null, convert it to a string. Note:
757
+ // typeof null does not produce 'null'. The case is included here in
758
+ // the remote chance that this gets fixed someday.
759
+
760
+ return String(value);
761
+
762
+ // If the type is 'object', we might be dealing with an object or an array or
763
+ // null.
764
+
765
+ case 'object':
766
+
767
+ // Due to a specification blunder in ECMAScript, typeof null is 'object',
768
+ // so watch out for that case.
769
+
770
+ if (!value) {
771
+ return 'null';
772
+ }
773
+
774
+ // Make an array to hold the partial results of stringifying this object value.
775
+
776
+ gap += indent;
777
+ partial = [];
778
+
779
+ // Is the value an array?
780
+
781
+ if (Object.prototype.toString.apply(value) === '[object Array]') {
782
+
783
+ // The value is an array. Stringify every element. Use null as a placeholder
784
+ // for non-JSON values.
785
+
786
+ length = value.length;
787
+ for (i = 0; i < length; i += 1) {
788
+ partial[i] = str(i, value) || 'null';
789
+ }
790
+
791
+ // Join all of the elements together, separated with commas, and wrap them in
792
+ // brackets.
793
+
794
+ v = partial.length === 0 ? '[]' : gap ?
795
+ '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
796
+ '[' + partial.join(',') + ']';
797
+ gap = mind;
798
+ return v;
799
+ }
800
+
801
+ // If the replacer is an array, use it to select the members to be stringified.
802
+
803
+ if (rep && typeof rep === 'object') {
804
+ length = rep.length;
805
+ for (i = 0; i < length; i += 1) {
806
+ if (typeof rep[i] === 'string') {
807
+ k = rep[i];
808
+ v = str(k, value);
809
+ if (v) {
810
+ partial.push(quote(k) + (gap ? ': ' : ':') + v);
811
+ }
812
+ }
813
+ }
814
+ } else {
815
+
816
+ // Otherwise, iterate through all of the keys in the object.
817
+
818
+ for (k in value) {
819
+ if (Object.prototype.hasOwnProperty.call(value, k)) {
820
+ v = str(k, value);
821
+ if (v) {
822
+ partial.push(quote(k) + (gap ? ': ' : ':') + v);
823
+ }
824
+ }
825
+ }
826
+ }
827
+
828
+ // Join all of the member texts together, separated with commas,
829
+ // and wrap them in braces.
830
+
831
+ v = partial.length === 0 ? '{}' : gap ?
832
+ '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
833
+ '{' + partial.join(',') + '}';
834
+ gap = mind;
835
+ return v;
836
+ }
837
+ }
838
+
839
+ // If the JSON object does not yet have a stringify method, give it one.
840
+
841
+ JSON.stringify = function (value, replacer, space) {
842
+
843
+ // The stringify method takes a value and an optional replacer, and an optional
844
+ // space parameter, and returns a JSON text. The replacer can be a function
845
+ // that can replace values, or an array of strings that will select the keys.
846
+ // A default replacer method can be provided. Use of the space parameter can
847
+ // produce text that is more easily readable.
848
+
849
+ var i;
850
+ gap = '';
851
+ indent = '';
852
+
853
+ // If the space parameter is a number, make an indent string containing that
854
+ // many spaces.
855
+
856
+ if (typeof space === 'number') {
857
+ for (i = 0; i < space; i += 1) {
858
+ indent += ' ';
859
+ }
860
+
861
+ // If the space parameter is a string, it will be used as the indent string.
862
+
863
+ } else if (typeof space === 'string') {
864
+ indent = space;
865
+ }
866
+
867
+ // If there is a replacer, it must be a function or an array.
868
+ // Otherwise, throw an error.
869
+
870
+ rep = replacer;
871
+ if (replacer && typeof replacer !== 'function' &&
872
+ (typeof replacer !== 'object' ||
873
+ typeof replacer.length !== 'number')) {
874
+ throw new Error('JSON.stringify');
875
+ }
876
+
877
+ // Make a fake root object containing our value under the key of ''.
878
+ // Return the result of stringifying the value.
879
+
880
+ return str('', {'': value});
881
+ };
882
+
883
+ // If the JSON object does not yet have a parse method, give it one.
884
+
885
+ JSON.parse = function (text, reviver) {
886
+ // The parse method takes a text and an optional reviver function, and returns
887
+ // a JavaScript value if the text is a valid JSON text.
888
+
889
+ var j;
890
+
891
+ function walk(holder, key) {
892
+
893
+ // The walk method is used to recursively walk the resulting structure so
894
+ // that modifications can be made.
895
+
896
+ var k, v, value = holder[key];
897
+ if (value && typeof value === 'object') {
898
+ for (k in value) {
899
+ if (Object.prototype.hasOwnProperty.call(value, k)) {
900
+ v = walk(value, k);
901
+ if (v !== undefined) {
902
+ value[k] = v;
903
+ } else {
904
+ delete value[k];
905
+ }
906
+ }
907
+ }
908
+ }
909
+ return reviver.call(holder, key, value);
910
+ }
911
+
912
+
913
+ // Parsing happens in four stages. In the first stage, we replace certain
914
+ // Unicode characters with escape sequences. JavaScript handles many characters
915
+ // incorrectly, either silently deleting them, or treating them as line endings.
916
+
917
+ text = String(text);
918
+ cx.lastIndex = 0;
919
+ if (cx.test(text)) {
920
+ text = text.replace(cx, function (a) {
921
+ return '\\u' +
922
+ ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
923
+ });
924
+ }
925
+
926
+ // In the second stage, we run the text against regular expressions that look
927
+ // for non-JSON patterns. We are especially concerned with '()' and 'new'
928
+ // because they can cause invocation, and '=' because it can cause mutation.
929
+ // But just to be safe, we want to reject all unexpected forms.
930
+
931
+ // We split the second stage into 4 regexp operations in order to work around
932
+ // crippling inefficiencies in IE's and Safari's regexp engines. First we
933
+ // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
934
+ // replace all simple value tokens with ']' characters. Third, we delete all
935
+ // open brackets that follow a colon or comma or that begin the text. Finally,
936
+ // we look to see that the remaining characters are only whitespace or ']' or
937
+ // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
938
+
939
+ if (/^[\],:{}\s]*$/
940
+ .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
941
+ .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
942
+ .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
943
+
944
+ // In the third stage we use the eval function to compile the text into a
945
+ // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
946
+ // in JavaScript: it can begin a block or an object literal. We wrap the text
947
+ // in parens to eliminate the ambiguity.
948
+
949
+ j = eval('(' + text + ')');
950
+
951
+ // In the optional fourth stage, we recursively walk the new structure, passing
952
+ // each name/value pair to a reviver function for possible transformation.
953
+
954
+ return typeof reviver === 'function' ?
955
+ walk({'': j}, '') : j;
956
+ }
957
+
958
+ // If the text is not JSON parseable, then a SyntaxError is thrown.
959
+
960
+ throw new SyntaxError('JSON.parse');
961
+ };
962
+
963
+ })(
964
+ 'undefined' != typeof io ? io : module.exports
965
+ , typeof JSON !== 'undefined' ? JSON : undefined
966
+ );
967
+
968
+ /**
969
+ * socket.io
970
+ * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
971
+ * MIT Licensed
972
+ */
973
+
974
+ (function (exports, io) {
975
+
976
+ /**
977
+ * Parser namespace.
978
+ *
979
+ * @namespace
980
+ */
981
+
982
+ var parser = exports.parser = {};
983
+
984
+ /**
985
+ * Packet types.
986
+ */
987
+
988
+ var packets = parser.packets = [
989
+ 'disconnect'
990
+ , 'connect'
991
+ , 'heartbeat'
992
+ , 'message'
993
+ , 'json'
994
+ , 'event'
995
+ , 'ack'
996
+ , 'error'
997
+ , 'noop'
998
+ ];
999
+
1000
+ /**
1001
+ * Errors reasons.
1002
+ */
1003
+
1004
+ var reasons = parser.reasons = [
1005
+ 'transport not supported'
1006
+ , 'client not handshaken'
1007
+ , 'unauthorized'
1008
+ ];
1009
+
1010
+ /**
1011
+ * Errors advice.
1012
+ */
1013
+
1014
+ var advice = parser.advice = [
1015
+ 'reconnect'
1016
+ ];
1017
+
1018
+ /**
1019
+ * Shortcuts.
1020
+ */
1021
+
1022
+ var JSON = io.JSON
1023
+ , indexOf = io.util.indexOf;
1024
+
1025
+ /**
1026
+ * Encodes a packet.
1027
+ *
1028
+ * @api private
1029
+ */
1030
+
1031
+ parser.encodePacket = function (packet) {
1032
+ var type = indexOf(packets, packet.type)
1033
+ , id = packet.id || ''
1034
+ , endpoint = packet.endpoint || ''
1035
+ , ack = packet.ack
1036
+ , data = null;
1037
+
1038
+ switch (packet.type) {
1039
+ case 'error':
1040
+ var reason = packet.reason ? indexOf(reasons, packet.reason) : ''
1041
+ , adv = packet.advice ? indexOf(advice, packet.advice) : '';
1042
+
1043
+ if (reason !== '' || adv !== '')
1044
+ data = reason + (adv !== '' ? ('+' + adv) : '');
1045
+
1046
+ break;
1047
+
1048
+ case 'message':
1049
+ if (packet.data !== '')
1050
+ data = packet.data;
1051
+ break;
1052
+
1053
+ case 'event':
1054
+ var ev = { name: packet.name };
1055
+
1056
+ if (packet.args && packet.args.length) {
1057
+ ev.args = packet.args;
1058
+ }
1059
+
1060
+ data = JSON.stringify(ev);
1061
+ break;
1062
+
1063
+ case 'json':
1064
+ data = JSON.stringify(packet.data);
1065
+ break;
1066
+
1067
+ case 'connect':
1068
+ if (packet.qs)
1069
+ data = packet.qs;
1070
+ break;
1071
+
1072
+ case 'ack':
1073
+ data = packet.ackId
1074
+ + (packet.args && packet.args.length
1075
+ ? '+' + JSON.stringify(packet.args) : '');
1076
+ break;
1077
+ }
1078
+
1079
+ // construct packet with required fragments
1080
+ var encoded = [
1081
+ type
1082
+ , id + (ack == 'data' ? '+' : '')
1083
+ , endpoint
1084
+ ];
1085
+
1086
+ // data fragment is optional
1087
+ if (data !== null && data !== undefined)
1088
+ encoded.push(data);
1089
+
1090
+ return encoded.join(':');
1091
+ };
1092
+
1093
+ /**
1094
+ * Encodes multiple messages (payload).
1095
+ *
1096
+ * @param {Array} messages
1097
+ * @api private
1098
+ */
1099
+
1100
+ parser.encodePayload = function (packets) {
1101
+ var decoded = '';
1102
+
1103
+ if (packets.length == 1)
1104
+ return packets[0];
1105
+
1106
+ for (var i = 0, l = packets.length; i < l; i++) {
1107
+ var packet = packets[i];
1108
+ decoded += '\ufffd' + packet.length + '\ufffd' + packets[i];
1109
+ }
1110
+
1111
+ return decoded;
1112
+ };
1113
+
1114
+ /**
1115
+ * Decodes a packet
1116
+ *
1117
+ * @api private
1118
+ */
1119
+
1120
+ var regexp = /([^:]+):([0-9]+)?(\+)?:([^:]+)?:?([\s\S]*)?/;
1121
+
1122
+ parser.decodePacket = function (data) {
1123
+ var pieces = data.match(regexp);
1124
+
1125
+ if (!pieces) return {};
1126
+
1127
+ var id = pieces[2] || ''
1128
+ , data = pieces[5] || ''
1129
+ , packet = {
1130
+ type: packets[pieces[1]]
1131
+ , endpoint: pieces[4] || ''
1132
+ };
1133
+
1134
+ // whether we need to acknowledge the packet
1135
+ if (id) {
1136
+ packet.id = id;
1137
+ if (pieces[3])
1138
+ packet.ack = 'data';
1139
+ else
1140
+ packet.ack = true;
1141
+ }
1142
+
1143
+ // handle different packet types
1144
+ switch (packet.type) {
1145
+ case 'error':
1146
+ var pieces = data.split('+');
1147
+ packet.reason = reasons[pieces[0]] || '';
1148
+ packet.advice = advice[pieces[1]] || '';
1149
+ break;
1150
+
1151
+ case 'message':
1152
+ packet.data = data || '';
1153
+ break;
1154
+
1155
+ case 'event':
1156
+ try {
1157
+ var opts = JSON.parse(data);
1158
+ packet.name = opts.name;
1159
+ packet.args = opts.args;
1160
+ } catch (e) { }
1161
+
1162
+ packet.args = packet.args || [];
1163
+ break;
1164
+
1165
+ case 'json':
1166
+ try {
1167
+ packet.data = JSON.parse(data);
1168
+ } catch (e) { }
1169
+ break;
1170
+
1171
+ case 'connect':
1172
+ packet.qs = data || '';
1173
+ break;
1174
+
1175
+ case 'ack':
1176
+ var pieces = data.match(/^([0-9]+)(\+)?(.*)/);
1177
+ if (pieces) {
1178
+ packet.ackId = pieces[1];
1179
+ packet.args = [];
1180
+
1181
+ if (pieces[3]) {
1182
+ try {
1183
+ packet.args = pieces[3] ? JSON.parse(pieces[3]) : [];
1184
+ } catch (e) { }
1185
+ }
1186
+ }
1187
+ break;
1188
+
1189
+ case 'disconnect':
1190
+ case 'heartbeat':
1191
+ break;
1192
+ };
1193
+
1194
+ return packet;
1195
+ };
1196
+
1197
+ /**
1198
+ * Decodes data payload. Detects multiple messages
1199
+ *
1200
+ * @return {Array} messages
1201
+ * @api public
1202
+ */
1203
+
1204
+ parser.decodePayload = function (data) {
1205
+ // IE doesn't like data[i] for unicode chars, charAt works fine
1206
+ if (data.charAt(0) == '\ufffd') {
1207
+ var ret = [];
1208
+
1209
+ for (var i = 1, length = ''; i < data.length; i++) {
1210
+ if (data.charAt(i) == '\ufffd') {
1211
+ ret.push(parser.decodePacket(data.substr(i + 1).substr(0, length)));
1212
+ i += Number(length) + 1;
1213
+ length = '';
1214
+ } else {
1215
+ length += data.charAt(i);
1216
+ }
1217
+ }
1218
+
1219
+ return ret;
1220
+ } else {
1221
+ return [parser.decodePacket(data)];
1222
+ }
1223
+ };
1224
+
1225
+ })(
1226
+ 'undefined' != typeof io ? io : module.exports
1227
+ , 'undefined' != typeof io ? io : module.parent.exports
1228
+ );
1229
+ /**
1230
+ * socket.io
1231
+ * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
1232
+ * MIT Licensed
1233
+ */
1234
+
1235
+ (function (exports, io) {
1236
+
1237
+ /**
1238
+ * Expose constructor.
1239
+ */
1240
+
1241
+ exports.Transport = Transport;
1242
+
1243
+ /**
1244
+ * This is the transport template for all supported transport methods.
1245
+ *
1246
+ * @constructor
1247
+ * @api public
1248
+ */
1249
+
1250
+ function Transport (socket, sessid) {
1251
+ this.socket = socket;
1252
+ this.sessid = sessid;
1253
+ };
1254
+
1255
+ /**
1256
+ * Apply EventEmitter mixin.
1257
+ */
1258
+
1259
+ io.util.mixin(Transport, io.EventEmitter);
1260
+
1261
+ /**
1262
+ * Handles the response from the server. When a new response is received
1263
+ * it will automatically update the timeout, decode the message and
1264
+ * forwards the response to the onMessage function for further processing.
1265
+ *
1266
+ * @param {String} data Response from the server.
1267
+ * @api private
1268
+ */
1269
+
1270
+ Transport.prototype.onData = function (data) {
1271
+ this.clearCloseTimeout();
1272
+
1273
+ // If the connection in currently open (or in a reopening state) reset the close
1274
+ // timeout since we have just received data. This check is necessary so
1275
+ // that we don't reset the timeout on an explicitly disconnected connection.
1276
+ if (this.connected || this.connecting || this.reconnecting) {
1277
+ this.setCloseTimeout();
1278
+ }
1279
+
1280
+ if (data !== '') {
1281
+ // todo: we should only do decodePayload for xhr transports
1282
+ var msgs = io.parser.decodePayload(data);
1283
+
1284
+ if (msgs && msgs.length) {
1285
+ for (var i = 0, l = msgs.length; i < l; i++) {
1286
+ this.onPacket(msgs[i]);
1287
+ }
1288
+ }
1289
+ }
1290
+
1291
+ return this;
1292
+ };
1293
+
1294
+ /**
1295
+ * Handles packets.
1296
+ *
1297
+ * @api private
1298
+ */
1299
+
1300
+ Transport.prototype.onPacket = function (packet) {
1301
+ if (packet.type == 'heartbeat') {
1302
+ return this.onHeartbeat();
1303
+ }
1304
+
1305
+ if (packet.type == 'connect' && packet.endpoint == '') {
1306
+ this.onConnect();
1307
+ }
1308
+
1309
+ this.socket.onPacket(packet);
1310
+
1311
+ return this;
1312
+ };
1313
+
1314
+ /**
1315
+ * Sets close timeout
1316
+ *
1317
+ * @api private
1318
+ */
1319
+
1320
+ Transport.prototype.setCloseTimeout = function () {
1321
+ if (!this.closeTimeout) {
1322
+ var self = this;
1323
+
1324
+ this.closeTimeout = setTimeout(function () {
1325
+ self.onDisconnect();
1326
+ }, this.socket.closeTimeout);
1327
+ }
1328
+ };
1329
+
1330
+ /**
1331
+ * Called when transport disconnects.
1332
+ *
1333
+ * @api private
1334
+ */
1335
+
1336
+ Transport.prototype.onDisconnect = function () {
1337
+ if (this.close && this.open) this.close();
1338
+ this.clearTimeouts();
1339
+ this.socket.onDisconnect();
1340
+ return this;
1341
+ };
1342
+
1343
+ /**
1344
+ * Called when transport connects
1345
+ *
1346
+ * @api private
1347
+ */
1348
+
1349
+ Transport.prototype.onConnect = function () {
1350
+ this.socket.onConnect();
1351
+ return this;
1352
+ }
1353
+
1354
+ /**
1355
+ * Clears close timeout
1356
+ *
1357
+ * @api private
1358
+ */
1359
+
1360
+ Transport.prototype.clearCloseTimeout = function () {
1361
+ if (this.closeTimeout) {
1362
+ clearTimeout(this.closeTimeout);
1363
+ this.closeTimeout = null;
1364
+ }
1365
+ };
1366
+
1367
+ /**
1368
+ * Clear timeouts
1369
+ *
1370
+ * @api private
1371
+ */
1372
+
1373
+ Transport.prototype.clearTimeouts = function () {
1374
+ this.clearCloseTimeout();
1375
+
1376
+ if (this.reopenTimeout) {
1377
+ clearTimeout(this.reopenTimeout);
1378
+ }
1379
+ };
1380
+
1381
+ /**
1382
+ * Sends a packet
1383
+ *
1384
+ * @param {Object} packet object.
1385
+ * @api private
1386
+ */
1387
+
1388
+ Transport.prototype.packet = function (packet) {
1389
+ this.send(io.parser.encodePacket(packet));
1390
+ };
1391
+
1392
+ /**
1393
+ * Send the received heartbeat message back to server. So the server
1394
+ * knows we are still connected.
1395
+ *
1396
+ * @param {String} heartbeat Heartbeat response from the server.
1397
+ * @api private
1398
+ */
1399
+
1400
+ Transport.prototype.onHeartbeat = function (heartbeat) {
1401
+ this.packet({ type: 'heartbeat' });
1402
+ };
1403
+
1404
+ /**
1405
+ * Called when the transport opens.
1406
+ *
1407
+ * @api private
1408
+ */
1409
+
1410
+ Transport.prototype.onOpen = function () {
1411
+ this.open = true;
1412
+ this.clearCloseTimeout();
1413
+ this.socket.onOpen();
1414
+ };
1415
+
1416
+ /**
1417
+ * Notifies the base when the connection with the Socket.IO server
1418
+ * has been disconnected.
1419
+ *
1420
+ * @api private
1421
+ */
1422
+
1423
+ Transport.prototype.onClose = function () {
1424
+ var self = this;
1425
+
1426
+ /* FIXME: reopen delay causing a infinit loop
1427
+ this.reopenTimeout = setTimeout(function () {
1428
+ self.open();
1429
+ }, this.socket.options['reopen delay']);*/
1430
+
1431
+ this.open = false;
1432
+ this.socket.onClose();
1433
+ this.onDisconnect();
1434
+ };
1435
+
1436
+ /**
1437
+ * Generates a connection url based on the Socket.IO URL Protocol.
1438
+ * See <https://github.com/learnboost/socket.io-node/> for more details.
1439
+ *
1440
+ * @returns {String} Connection url
1441
+ * @api private
1442
+ */
1443
+
1444
+ Transport.prototype.prepareUrl = function () {
1445
+ var options = this.socket.options;
1446
+
1447
+ return this.scheme() + '://'
1448
+ + options.host + ':' + options.port + '/'
1449
+ + options.resource + '/' + io.protocol
1450
+ + '/' + this.name + '/' + this.sessid;
1451
+ };
1452
+
1453
+ /**
1454
+ * Checks if the transport is ready to start a connection.
1455
+ *
1456
+ * @param {Socket} socket The socket instance that needs a transport
1457
+ * @param {Function} fn The callback
1458
+ * @api private
1459
+ */
1460
+
1461
+ Transport.prototype.ready = function (socket, fn) {
1462
+ fn.call(this);
1463
+ };
1464
+ })(
1465
+ 'undefined' != typeof io ? io : module.exports
1466
+ , 'undefined' != typeof io ? io : module.parent.exports
1467
+ );
1468
+
1469
+ /**
1470
+ * socket.io
1471
+ * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
1472
+ * MIT Licensed
1473
+ */
1474
+
1475
+ (function (exports, io, global) {
1476
+
1477
+ /**
1478
+ * Expose constructor.
1479
+ */
1480
+
1481
+ exports.Socket = Socket;
1482
+
1483
+ /**
1484
+ * Create a new `Socket.IO client` which can establish a persistent
1485
+ * connection with a Socket.IO enabled server.
1486
+ *
1487
+ * @api public
1488
+ */
1489
+
1490
+ function Socket (options) {
1491
+ this.options = {
1492
+ port: 80
1493
+ , secure: false
1494
+ , document: 'document' in global ? document : false
1495
+ , resource: 'socket.io'
1496
+ , transports: io.transports
1497
+ , 'connect timeout': 10000
1498
+ , 'try multiple transports': true
1499
+ , 'reconnect': true
1500
+ , 'reconnection delay': 500
1501
+ , 'reconnection limit': Infinity
1502
+ , 'reopen delay': 3000
1503
+ , 'max reconnection attempts': 10
1504
+ , 'sync disconnect on unload': true
1505
+ , 'auto connect': true
1506
+ , 'flash policy port': 10843
1507
+ };
1508
+
1509
+ io.util.merge(this.options, options);
1510
+
1511
+ this.connected = false;
1512
+ this.open = false;
1513
+ this.connecting = false;
1514
+ this.reconnecting = false;
1515
+ this.namespaces = {};
1516
+ this.buffer = [];
1517
+ this.doBuffer = false;
1518
+
1519
+ if (this.options['sync disconnect on unload'] &&
1520
+ (!this.isXDomain() || io.util.ua.hasCORS)) {
1521
+ var self = this;
1522
+
1523
+ io.util.on(global, 'beforeunload', function () {
1524
+ self.disconnectSync();
1525
+ }, false);
1526
+ }
1527
+
1528
+ if (this.options['auto connect']) {
1529
+ this.connect();
1530
+ }
1531
+ };
1532
+
1533
+ /**
1534
+ * Apply EventEmitter mixin.
1535
+ */
1536
+
1537
+ io.util.mixin(Socket, io.EventEmitter);
1538
+
1539
+ /**
1540
+ * Returns a namespace listener/emitter for this socket
1541
+ *
1542
+ * @api public
1543
+ */
1544
+
1545
+ Socket.prototype.of = function (name) {
1546
+ if (!this.namespaces[name]) {
1547
+ this.namespaces[name] = new io.SocketNamespace(this, name);
1548
+
1549
+ if (name !== '') {
1550
+ this.namespaces[name].packet({ type: 'connect' });
1551
+ }
1552
+ }
1553
+
1554
+ return this.namespaces[name];
1555
+ };
1556
+
1557
+ /**
1558
+ * Emits the given event to the Socket and all namespaces
1559
+ *
1560
+ * @api private
1561
+ */
1562
+
1563
+ Socket.prototype.publish = function () {
1564
+ this.emit.apply(this, arguments);
1565
+
1566
+ var nsp;
1567
+
1568
+ for (var i in this.namespaces) {
1569
+ if (this.namespaces.hasOwnProperty(i)) {
1570
+ nsp = this.of(i);
1571
+ nsp.$emit.apply(nsp, arguments);
1572
+ }
1573
+ }
1574
+ };
1575
+
1576
+ /**
1577
+ * Performs the handshake
1578
+ *
1579
+ * @api private
1580
+ */
1581
+
1582
+ function empty () { };
1583
+
1584
+ Socket.prototype.handshake = function (fn) {
1585
+ var self = this
1586
+ , options = this.options;
1587
+
1588
+ function complete (data) {
1589
+ if (data instanceof Error) {
1590
+ self.onError(data.message);
1591
+ } else {
1592
+ fn.apply(null, data.split(':'));
1593
+ }
1594
+ };
1595
+
1596
+ var url = [
1597
+ 'http' + (options.secure ? 's' : '') + ':/'
1598
+ , options.host + ':' + options.port
1599
+ , options.resource
1600
+ , io.protocol
1601
+ , io.util.query(this.options.query, 't=' + +new Date)
1602
+ ].join('/');
1603
+
1604
+ if (this.isXDomain() && !io.util.ua.hasCORS) {
1605
+ var insertAt = document.getElementsByTagName('script')[0]
1606
+ , script = document.createElement('script');
1607
+
1608
+ script.src = url + '&jsonp=' + io.j.length;
1609
+ insertAt.parentNode.insertBefore(script, insertAt);
1610
+
1611
+ io.j.push(function (data) {
1612
+ complete(data);
1613
+ script.parentNode.removeChild(script);
1614
+ });
1615
+ } else {
1616
+ var xhr = io.util.request();
1617
+
1618
+ xhr.open('GET', url, true);
1619
+ xhr.onreadystatechange = function () {
1620
+ if (xhr.readyState == 4) {
1621
+ xhr.onreadystatechange = empty;
1622
+
1623
+ if (xhr.status == 200) {
1624
+ complete(xhr.responseText);
1625
+ } else {
1626
+ !self.reconnecting && self.onError(xhr.responseText);
1627
+ }
1628
+ }
1629
+ };
1630
+ xhr.send(null);
1631
+ }
1632
+ };
1633
+
1634
+ /**
1635
+ * Find an available transport based on the options supplied in the constructor.
1636
+ *
1637
+ * @api private
1638
+ */
1639
+
1640
+ Socket.prototype.getTransport = function (override) {
1641
+ var transports = override || this.transports, match;
1642
+
1643
+ for (var i = 0, transport; transport = transports[i]; i++) {
1644
+ if (io.Transport[transport]
1645
+ && io.Transport[transport].check(this)
1646
+ && (!this.isXDomain() || io.Transport[transport].xdomainCheck())) {
1647
+ return new io.Transport[transport](this, this.sessionid);
1648
+ }
1649
+ }
1650
+
1651
+ return null;
1652
+ };
1653
+
1654
+ /**
1655
+ * Connects to the server.
1656
+ *
1657
+ * @param {Function} [fn] Callback.
1658
+ * @returns {io.Socket}
1659
+ * @api public
1660
+ */
1661
+
1662
+ Socket.prototype.connect = function (fn) {
1663
+ if (this.connecting) {
1664
+ return this;
1665
+ }
1666
+
1667
+ var self = this;
1668
+
1669
+ this.handshake(function (sid, heartbeat, close, transports) {
1670
+ self.sessionid = sid;
1671
+ self.closeTimeout = close * 1000;
1672
+ self.heartbeatTimeout = heartbeat * 1000;
1673
+ self.transports = io.util.intersect(
1674
+ transports.split(',')
1675
+ , self.options.transports
1676
+ );
1677
+
1678
+ function connect (transports){
1679
+ if (self.transport) self.transport.clearTimeouts();
1680
+
1681
+ self.transport = self.getTransport(transports);
1682
+ if (!self.transport) return self.publish('connect_failed');
1683
+
1684
+ // once the transport is ready
1685
+ self.transport.ready(self, function () {
1686
+ self.connecting = true;
1687
+ self.publish('connecting', self.transport.name);
1688
+ self.transport.open();
1689
+
1690
+ if (self.options['connect timeout']) {
1691
+ self.connectTimeoutTimer = setTimeout(function () {
1692
+ if (!self.connected) {
1693
+ self.connecting = false;
1694
+
1695
+ if (self.options['try multiple transports']) {
1696
+ if (!self.remainingTransports) {
1697
+ self.remainingTransports = self.transports.slice(0);
1698
+ }
1699
+
1700
+ var remaining = self.remainingTransports;
1701
+
1702
+ while (remaining.length > 0 && remaining.splice(0,1)[0] !=
1703
+ self.transport.name) {}
1704
+
1705
+ if (remaining.length){
1706
+ connect(remaining);
1707
+ } else {
1708
+ self.publish('connect_failed');
1709
+ }
1710
+ }
1711
+ }
1712
+ }, self.options['connect timeout']);
1713
+ }
1714
+ });
1715
+ }
1716
+
1717
+ connect();
1718
+
1719
+ self.once('connect', function (){
1720
+ clearTimeout(self.connectTimeoutTimer);
1721
+
1722
+ fn && typeof fn == 'function' && fn();
1723
+ });
1724
+ });
1725
+
1726
+ return this;
1727
+ };
1728
+
1729
+ /**
1730
+ * Sends a message.
1731
+ *
1732
+ * @param {Object} data packet.
1733
+ * @returns {io.Socket}
1734
+ * @api public
1735
+ */
1736
+
1737
+ Socket.prototype.packet = function (data) {
1738
+ if (this.connected && !this.doBuffer) {
1739
+ this.transport.packet(data);
1740
+ } else {
1741
+ this.buffer.push(data);
1742
+ }
1743
+
1744
+ return this;
1745
+ };
1746
+
1747
+ /**
1748
+ * Sets buffer state
1749
+ *
1750
+ * @api private
1751
+ */
1752
+
1753
+ Socket.prototype.setBuffer = function (v) {
1754
+ this.doBuffer = v;
1755
+
1756
+ if (!v && this.connected && this.buffer.length) {
1757
+ this.transport.payload(this.buffer);
1758
+ this.buffer = [];
1759
+ }
1760
+ };
1761
+
1762
+ /**
1763
+ * Disconnect the established connect.
1764
+ *
1765
+ * @returns {io.Socket}
1766
+ * @api public
1767
+ */
1768
+
1769
+ Socket.prototype.disconnect = function () {
1770
+ if (this.connected) {
1771
+ if (this.open) {
1772
+ this.of('').packet({ type: 'disconnect' });
1773
+ }
1774
+
1775
+ // handle disconnection immediately
1776
+ this.onDisconnect('booted');
1777
+ }
1778
+
1779
+ return this;
1780
+ };
1781
+
1782
+ /**
1783
+ * Disconnects the socket with a sync XHR.
1784
+ *
1785
+ * @api private
1786
+ */
1787
+
1788
+ Socket.prototype.disconnectSync = function () {
1789
+ // ensure disconnection
1790
+ var xhr = io.util.request()
1791
+ , uri = this.resource + '/' + io.protocol + '/' + this.sessionid;
1792
+
1793
+ xhr.open('GET', uri, true);
1794
+
1795
+ // handle disconnection immediately
1796
+ this.onDisconnect('booted');
1797
+ };
1798
+
1799
+ /**
1800
+ * Check if we need to use cross domain enabled transports. Cross domain would
1801
+ * be a different port or different domain name.
1802
+ *
1803
+ * @returns {Boolean}
1804
+ * @api private
1805
+ */
1806
+
1807
+ Socket.prototype.isXDomain = function () {
1808
+
1809
+ var port = global.location.port ||
1810
+ ('https:' == global.location.protocol ? 443 : 80);
1811
+
1812
+ return this.options.host !== global.location.hostname
1813
+ || this.options.port != port;
1814
+ };
1815
+
1816
+ /**
1817
+ * Called upon handshake.
1818
+ *
1819
+ * @api private
1820
+ */
1821
+
1822
+ Socket.prototype.onConnect = function () {
1823
+ if (!this.connected) {
1824
+ this.connected = true;
1825
+ this.connecting = false;
1826
+ if (!this.doBuffer) {
1827
+ // make sure to flush the buffer
1828
+ this.setBuffer(false);
1829
+ }
1830
+ this.emit('connect');
1831
+ }
1832
+ };
1833
+
1834
+ /**
1835
+ * Called when the transport opens
1836
+ *
1837
+ * @api private
1838
+ */
1839
+
1840
+ Socket.prototype.onOpen = function () {
1841
+ this.open = true;
1842
+ };
1843
+
1844
+ /**
1845
+ * Called when the transport closes.
1846
+ *
1847
+ * @api private
1848
+ */
1849
+
1850
+ Socket.prototype.onClose = function () {
1851
+ this.open = false;
1852
+ };
1853
+
1854
+ /**
1855
+ * Called when the transport first opens a connection
1856
+ *
1857
+ * @param text
1858
+ */
1859
+
1860
+ Socket.prototype.onPacket = function (packet) {
1861
+ this.of(packet.endpoint).onPacket(packet);
1862
+ };
1863
+
1864
+ /**
1865
+ * Handles an error.
1866
+ *
1867
+ * @api private
1868
+ */
1869
+
1870
+ Socket.prototype.onError = function (err) {
1871
+ if (err && err.advice) {
1872
+ if (err.advice === 'reconnect' && this.connected) {
1873
+ this.disconnect();
1874
+ this.reconnect();
1875
+ }
1876
+ }
1877
+
1878
+ this.publish('error', err && err.reason ? err.reason : err);
1879
+ };
1880
+
1881
+ /**
1882
+ * Called when the transport disconnects.
1883
+ *
1884
+ * @api private
1885
+ */
1886
+
1887
+ Socket.prototype.onDisconnect = function (reason) {
1888
+ var wasConnected = this.connected;
1889
+
1890
+ this.connected = false;
1891
+ this.connecting = false;
1892
+ this.open = false;
1893
+
1894
+ if (wasConnected) {
1895
+ this.transport.close();
1896
+ this.transport.clearTimeouts();
1897
+ this.publish('disconnect', reason);
1898
+
1899
+ if ('booted' != reason && this.options.reconnect && !this.reconnecting) {
1900
+ this.reconnect();
1901
+ }
1902
+ }
1903
+ };
1904
+
1905
+ /**
1906
+ * Called upon reconnection.
1907
+ *
1908
+ * @api private
1909
+ */
1910
+
1911
+ Socket.prototype.reconnect = function () {
1912
+ this.reconnecting = true;
1913
+ this.reconnectionAttempts = 0;
1914
+ this.reconnectionDelay = this.options['reconnection delay'];
1915
+
1916
+ var self = this
1917
+ , maxAttempts = this.options['max reconnection attempts']
1918
+ , tryMultiple = this.options['try multiple transports']
1919
+ , limit = this.options['reconnection limit'];
1920
+
1921
+ function reset () {
1922
+ if (self.connected) {
1923
+ for (var i in self.namespaces) {
1924
+ if (self.namespaces.hasOwnProperty(i) && '' !== i) {
1925
+ self.namespaces[i].packet({ type: 'connect' });
1926
+ }
1927
+ }
1928
+ self.publish('reconnect', self.transport.name, self.reconnectionAttempts);
1929
+ }
1930
+
1931
+ self.removeListener('connect_failed', maybeReconnect);
1932
+ self.removeListener('connect', maybeReconnect);
1933
+
1934
+ self.reconnecting = false;
1935
+
1936
+ delete self.reconnectionAttempts;
1937
+ delete self.reconnectionDelay;
1938
+ delete self.reconnectionTimer;
1939
+ delete self.redoTransports;
1940
+
1941
+ self.options['try multiple transports'] = tryMultiple;
1942
+ };
1943
+
1944
+ function maybeReconnect () {
1945
+ if (!self.reconnecting) {
1946
+ return;
1947
+ }
1948
+
1949
+ if (self.connected) {
1950
+ return reset();
1951
+ };
1952
+
1953
+ if (self.connecting && self.reconnecting) {
1954
+ return self.reconnectionTimer = setTimeout(maybeReconnect, 1000);
1955
+ }
1956
+
1957
+ if (self.reconnectionAttempts++ >= maxAttempts) {
1958
+ if (!self.redoTransports) {
1959
+ self.on('connect_failed', maybeReconnect);
1960
+ self.options['try multiple transports'] = true;
1961
+ self.transport = self.getTransport();
1962
+ self.redoTransports = true;
1963
+ self.connect();
1964
+ } else {
1965
+ self.publish('reconnect_failed');
1966
+ reset();
1967
+ }
1968
+ } else {
1969
+ if (self.reconnectionDelay < limit) {
1970
+ self.reconnectionDelay *= 2; // exponential back off
1971
+ }
1972
+
1973
+ self.connect();
1974
+ self.publish('reconnecting', self.reconnectionDelay, self.reconnectionAttempts);
1975
+ self.reconnectionTimer = setTimeout(maybeReconnect, self.reconnectionDelay);
1976
+ }
1977
+ };
1978
+
1979
+ this.options['try multiple transports'] = false;
1980
+ this.reconnectionTimer = setTimeout(maybeReconnect, this.reconnectionDelay);
1981
+
1982
+ this.on('connect', maybeReconnect);
1983
+ };
1984
+
1985
+ })(
1986
+ 'undefined' != typeof io ? io : module.exports
1987
+ , 'undefined' != typeof io ? io : module.parent.exports
1988
+ , this
1989
+ );
1990
+ /**
1991
+ * socket.io
1992
+ * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
1993
+ * MIT Licensed
1994
+ */
1995
+
1996
+ (function (exports, io) {
1997
+
1998
+ /**
1999
+ * Expose constructor.
2000
+ */
2001
+
2002
+ exports.SocketNamespace = SocketNamespace;
2003
+
2004
+ /**
2005
+ * Socket namespace constructor.
2006
+ *
2007
+ * @constructor
2008
+ * @api public
2009
+ */
2010
+
2011
+ function SocketNamespace (socket, name) {
2012
+ this.socket = socket;
2013
+ this.name = name || '';
2014
+ this.flags = {};
2015
+ this.json = new Flag(this, 'json');
2016
+ this.ackPackets = 0;
2017
+ this.acks = {};
2018
+ };
2019
+
2020
+ /**
2021
+ * Apply EventEmitter mixin.
2022
+ */
2023
+
2024
+ io.util.mixin(SocketNamespace, io.EventEmitter);
2025
+
2026
+ /**
2027
+ * Copies emit since we override it
2028
+ *
2029
+ * @api private
2030
+ */
2031
+
2032
+ SocketNamespace.prototype.$emit = io.EventEmitter.prototype.emit;
2033
+
2034
+ /**
2035
+ * Creates a new namespace, by proxying the request to the socket. This
2036
+ * allows us to use the synax as we do on the server.
2037
+ *
2038
+ * @api public
2039
+ */
2040
+
2041
+ SocketNamespace.prototype.of = function () {
2042
+ return this.socket.of.apply(this.socket, arguments);
2043
+ };
2044
+
2045
+ /**
2046
+ * Sends a packet.
2047
+ *
2048
+ * @api private
2049
+ */
2050
+
2051
+ SocketNamespace.prototype.packet = function (packet) {
2052
+ packet.endpoint = this.name;
2053
+ this.socket.packet(packet);
2054
+ this.flags = {};
2055
+ return this;
2056
+ };
2057
+
2058
+ /**
2059
+ * Sends a message
2060
+ *
2061
+ * @api public
2062
+ */
2063
+
2064
+ SocketNamespace.prototype.send = function (data, fn) {
2065
+ var packet = {
2066
+ type: this.flags.json ? 'json' : 'message'
2067
+ , data: data
2068
+ };
2069
+
2070
+ if ('function' == typeof fn) {
2071
+ packet.id = ++this.ackPackets;
2072
+ packet.ack = true;
2073
+ this.acks[packet.id] = fn;
2074
+ }
2075
+
2076
+ return this.packet(packet);
2077
+ };
2078
+
2079
+ /**
2080
+ * Emits an event
2081
+ *
2082
+ * @api public
2083
+ */
2084
+
2085
+ SocketNamespace.prototype.emit = function (name) {
2086
+ var args = Array.prototype.slice.call(arguments, 1)
2087
+ , lastArg = args[args.length - 1]
2088
+ , packet = {
2089
+ type: 'event'
2090
+ , name: name
2091
+ };
2092
+
2093
+ if ('function' == typeof lastArg) {
2094
+ packet.id = ++this.ackPackets;
2095
+ packet.ack = 'data';
2096
+ this.acks[packet.id] = lastArg;
2097
+ args = args.slice(0, args.length - 1);
2098
+ }
2099
+
2100
+ packet.args = args;
2101
+
2102
+ return this.packet(packet);
2103
+ };
2104
+
2105
+ /**
2106
+ * Disconnects the namespace
2107
+ *
2108
+ * @api private
2109
+ */
2110
+
2111
+ SocketNamespace.prototype.disconnect = function () {
2112
+ if (this.name === '') {
2113
+ this.socket.disconnect();
2114
+ } else {
2115
+ this.packet({ type: 'disconnect' });
2116
+ this.$emit('disconnect');
2117
+ }
2118
+
2119
+ return this;
2120
+ };
2121
+
2122
+ /**
2123
+ * Handles a packet
2124
+ *
2125
+ * @api private
2126
+ */
2127
+
2128
+ SocketNamespace.prototype.onPacket = function (packet) {
2129
+ var self = this;
2130
+
2131
+ function ack () {
2132
+ self.packet({
2133
+ type: 'ack'
2134
+ , args: io.util.toArray(arguments)
2135
+ , ackId: packet.id
2136
+ });
2137
+ };
2138
+
2139
+ switch (packet.type) {
2140
+ case 'connect':
2141
+ this.$emit('connect');
2142
+ break;
2143
+
2144
+ case 'disconnect':
2145
+ if (this.name === '') {
2146
+ this.socket.onDisconnect(packet.reason || 'booted');
2147
+ } else {
2148
+ this.$emit('disconnect', packet.reason);
2149
+ }
2150
+ break;
2151
+
2152
+ case 'message':
2153
+ case 'json':
2154
+ var params = ['message', packet.data];
2155
+
2156
+ if (packet.ack == 'data') {
2157
+ params.push(ack);
2158
+ } else if (packet.ack) {
2159
+ this.packet({ type: 'ack', ackId: packet.id });
2160
+ }
2161
+
2162
+ this.$emit.apply(this, params);
2163
+ break;
2164
+
2165
+ case 'event':
2166
+ var params = [packet.name].concat(packet.args);
2167
+
2168
+ if (packet.ack == 'data')
2169
+ params.push(ack);
2170
+
2171
+ this.$emit.apply(this, params);
2172
+ break;
2173
+
2174
+ case 'ack':
2175
+ if (this.acks[packet.ackId]) {
2176
+ this.acks[packet.ackId].apply(this, packet.args);
2177
+ delete this.acks[packet.ackId];
2178
+ }
2179
+ break;
2180
+
2181
+ case 'error':
2182
+ if (packet.advice){
2183
+ this.socket.onError(packet);
2184
+ } else {
2185
+ if (packet.reason == 'unauthorized') {
2186
+ this.$emit('connect_failed', packet.reason);
2187
+ } else {
2188
+ this.$emit('error', packet.reason);
2189
+ }
2190
+ }
2191
+ break;
2192
+ }
2193
+ };
2194
+
2195
+ /**
2196
+ * Flag interface.
2197
+ *
2198
+ * @api private
2199
+ */
2200
+
2201
+ function Flag (nsp, name) {
2202
+ this.namespace = nsp;
2203
+ this.name = name;
2204
+ };
2205
+
2206
+ /**
2207
+ * Send a message
2208
+ *
2209
+ * @api public
2210
+ */
2211
+
2212
+ Flag.prototype.send = function () {
2213
+ this.namespace.flags[this.name] = true;
2214
+ this.namespace.send.apply(this.namespace, arguments);
2215
+ };
2216
+
2217
+ /**
2218
+ * Emit an event
2219
+ *
2220
+ * @api public
2221
+ */
2222
+
2223
+ Flag.prototype.emit = function () {
2224
+ this.namespace.flags[this.name] = true;
2225
+ this.namespace.emit.apply(this.namespace, arguments);
2226
+ };
2227
+
2228
+ })(
2229
+ 'undefined' != typeof io ? io : module.exports
2230
+ , 'undefined' != typeof io ? io : module.parent.exports
2231
+ );
2232
+
2233
+ /**
2234
+ * socket.io
2235
+ * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
2236
+ * MIT Licensed
2237
+ */
2238
+
2239
+ (function (exports, io, global) {
2240
+
2241
+ /**
2242
+ * Expose constructor.
2243
+ */
2244
+
2245
+ exports.websocket = WS;
2246
+
2247
+ /**
2248
+ * The WebSocket transport uses the HTML5 WebSocket API to establish an
2249
+ * persistent connection with the Socket.IO server. This transport will also
2250
+ * be inherited by the FlashSocket fallback as it provides a API compatible
2251
+ * polyfill for the WebSockets.
2252
+ *
2253
+ * @constructor
2254
+ * @extends {io.Transport}
2255
+ * @api public
2256
+ */
2257
+
2258
+ function WS (socket) {
2259
+ io.Transport.apply(this, arguments);
2260
+ };
2261
+
2262
+ /**
2263
+ * Inherits from Transport.
2264
+ */
2265
+
2266
+ io.util.inherit(WS, io.Transport);
2267
+
2268
+ /**
2269
+ * Transport name
2270
+ *
2271
+ * @api public
2272
+ */
2273
+
2274
+ WS.prototype.name = 'websocket';
2275
+
2276
+ /**
2277
+ * Initializes a new `WebSocket` connection with the Socket.IO server. We attach
2278
+ * all the appropriate listeners to handle the responses from the server.
2279
+ *
2280
+ * @returns {Transport}
2281
+ * @api public
2282
+ */
2283
+
2284
+ WS.prototype.open = function () {
2285
+ var query = io.util.query(this.socket.options.query)
2286
+ , self = this
2287
+ , Socket
2288
+
2289
+
2290
+ if (!Socket) {
2291
+ Socket = global.MozWebSocket || global.WebSocket;
2292
+ }
2293
+
2294
+ this.websocket = new Socket(this.prepareUrl() + query);
2295
+
2296
+ this.websocket.onopen = function () {
2297
+ self.onOpen();
2298
+ self.socket.setBuffer(false);
2299
+ };
2300
+ this.websocket.onmessage = function (ev) {
2301
+ self.onData(ev.data);
2302
+ };
2303
+ this.websocket.onclose = function () {
2304
+ self.onClose();
2305
+ self.socket.setBuffer(true);
2306
+ };
2307
+ this.websocket.onerror = function (e) {
2308
+ self.onError(e);
2309
+ };
2310
+
2311
+ return this;
2312
+ };
2313
+
2314
+ /**
2315
+ * Send a message to the Socket.IO server. The message will automatically be
2316
+ * encoded in the correct message format.
2317
+ *
2318
+ * @returns {Transport}
2319
+ * @api public
2320
+ */
2321
+
2322
+ WS.prototype.send = function (data) {
2323
+ this.websocket.send(data);
2324
+ return this;
2325
+ };
2326
+
2327
+ /**
2328
+ * Payload
2329
+ *
2330
+ * @api private
2331
+ */
2332
+
2333
+ WS.prototype.payload = function (arr) {
2334
+ for (var i = 0, l = arr.length; i < l; i++) {
2335
+ this.packet(arr[i]);
2336
+ }
2337
+ return this;
2338
+ };
2339
+
2340
+ /**
2341
+ * Disconnect the established `WebSocket` connection.
2342
+ *
2343
+ * @returns {Transport}
2344
+ * @api public
2345
+ */
2346
+
2347
+ WS.prototype.close = function () {
2348
+ this.websocket.close();
2349
+ return this;
2350
+ };
2351
+
2352
+ /**
2353
+ * Handle the errors that `WebSocket` might be giving when we
2354
+ * are attempting to connect or send messages.
2355
+ *
2356
+ * @param {Error} e The error.
2357
+ * @api private
2358
+ */
2359
+
2360
+ WS.prototype.onError = function (e) {
2361
+ this.socket.onError(e);
2362
+ };
2363
+
2364
+ /**
2365
+ * Returns the appropriate scheme for the URI generation.
2366
+ *
2367
+ * @api private
2368
+ */
2369
+ WS.prototype.scheme = function () {
2370
+ return this.socket.options.secure ? 'wss' : 'ws';
2371
+ };
2372
+
2373
+ /**
2374
+ * Checks if the browser has support for native `WebSockets` and that
2375
+ * it's not the polyfill created for the FlashSocket transport.
2376
+ *
2377
+ * @return {Boolean}
2378
+ * @api public
2379
+ */
2380
+
2381
+ WS.check = function () {
2382
+ return ('WebSocket' in global && !('__addTask' in WebSocket))
2383
+ || 'MozWebSocket' in global;
2384
+ };
2385
+
2386
+ /**
2387
+ * Check if the `WebSocket` transport support cross domain communications.
2388
+ *
2389
+ * @returns {Boolean}
2390
+ * @api public
2391
+ */
2392
+
2393
+ WS.xdomainCheck = function () {
2394
+ return true;
2395
+ };
2396
+
2397
+ /**
2398
+ * Add the transport to your public io.transports array.
2399
+ *
2400
+ * @api private
2401
+ */
2402
+
2403
+ io.transports.push('websocket');
2404
+
2405
+ })(
2406
+ 'undefined' != typeof io ? io.Transport : module.exports
2407
+ , 'undefined' != typeof io ? io : module.parent.exports
2408
+ , this
2409
+ );
2410
+
2411
+ /**
2412
+ * socket.io
2413
+ * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
2414
+ * MIT Licensed
2415
+ */
2416
+
2417
+ (function (exports, io, global) {
2418
+
2419
+ /**
2420
+ * Expose constructor.
2421
+ *
2422
+ * @api public
2423
+ */
2424
+
2425
+ exports.XHR = XHR;
2426
+
2427
+ /**
2428
+ * XHR constructor
2429
+ *
2430
+ * @costructor
2431
+ * @api public
2432
+ */
2433
+
2434
+ function XHR (socket) {
2435
+ if (!socket) return;
2436
+
2437
+ io.Transport.apply(this, arguments);
2438
+ this.sendBuffer = [];
2439
+ };
2440
+
2441
+ /**
2442
+ * Inherits from Transport.
2443
+ */
2444
+
2445
+ io.util.inherit(XHR, io.Transport);
2446
+
2447
+ /**
2448
+ * Establish a connection
2449
+ *
2450
+ * @returns {Transport}
2451
+ * @api public
2452
+ */
2453
+
2454
+ XHR.prototype.open = function () {
2455
+ this.socket.setBuffer(false);
2456
+ this.onOpen();
2457
+ this.get();
2458
+
2459
+ // we need to make sure the request succeeds since we have no indication
2460
+ // whether the request opened or not until it succeeded.
2461
+ this.setCloseTimeout();
2462
+
2463
+ return this;
2464
+ };
2465
+
2466
+ /**
2467
+ * Check if we need to send data to the Socket.IO server, if we have data in our
2468
+ * buffer we encode it and forward it to the `post` method.
2469
+ *
2470
+ * @api private
2471
+ */
2472
+
2473
+ XHR.prototype.payload = function (payload) {
2474
+ var msgs = [];
2475
+
2476
+ for (var i = 0, l = payload.length; i < l; i++) {
2477
+ msgs.push(io.parser.encodePacket(payload[i]));
2478
+ }
2479
+
2480
+ this.send(io.parser.encodePayload(msgs));
2481
+ };
2482
+
2483
+ /**
2484
+ * Send data to the Socket.IO server.
2485
+ *
2486
+ * @param data The message
2487
+ * @returns {Transport}
2488
+ * @api public
2489
+ */
2490
+
2491
+ XHR.prototype.send = function (data) {
2492
+ this.post(data);
2493
+ return this;
2494
+ };
2495
+
2496
+ /**
2497
+ * Posts a encoded message to the Socket.IO server.
2498
+ *
2499
+ * @param {String} data A encoded message.
2500
+ * @api private
2501
+ */
2502
+
2503
+ function empty () { };
2504
+
2505
+ XHR.prototype.post = function (data) {
2506
+ var self = this;
2507
+ this.socket.setBuffer(true);
2508
+
2509
+ function stateChange () {
2510
+ if (this.readyState == 4) {
2511
+ this.onreadystatechange = empty;
2512
+ self.posting = false;
2513
+
2514
+ if (this.status == 200){
2515
+ self.socket.setBuffer(false);
2516
+ } else {
2517
+ self.onClose();
2518
+ }
2519
+ }
2520
+ }
2521
+
2522
+ function onload () {
2523
+ this.onload = empty;
2524
+ self.socket.setBuffer(false);
2525
+ };
2526
+
2527
+ this.sendXHR = this.request('POST');
2528
+
2529
+ if (global.XDomainRequest && this.sendXHR instanceof XDomainRequest) {
2530
+ this.sendXHR.onload = this.sendXHR.onerror = onload;
2531
+ } else {
2532
+ this.sendXHR.onreadystatechange = stateChange;
2533
+ }
2534
+
2535
+ this.sendXHR.send(data);
2536
+ };
2537
+
2538
+ /**
2539
+ * Disconnects the established `XHR` connection.
2540
+ *
2541
+ * @returns {Transport}
2542
+ * @api public
2543
+ */
2544
+
2545
+ XHR.prototype.close = function () {
2546
+ this.onClose();
2547
+ return this;
2548
+ };
2549
+
2550
+ /**
2551
+ * Generates a configured XHR request
2552
+ *
2553
+ * @param {String} url The url that needs to be requested.
2554
+ * @param {String} method The method the request should use.
2555
+ * @returns {XMLHttpRequest}
2556
+ * @api private
2557
+ */
2558
+
2559
+ XHR.prototype.request = function (method) {
2560
+ var req = io.util.request(this.socket.isXDomain())
2561
+ , query = io.util.query(this.socket.options.query, 't=' + +new Date);
2562
+
2563
+ req.open(method || 'GET', this.prepareUrl() + query, true);
2564
+
2565
+ if (method == 'POST') {
2566
+ try {
2567
+ if (req.setRequestHeader) {
2568
+ req.setRequestHeader('Content-type', 'text/plain;charset=UTF-8');
2569
+ } else {
2570
+ // XDomainRequest
2571
+ req.contentType = 'text/plain';
2572
+ }
2573
+ } catch (e) {}
2574
+ }
2575
+
2576
+ return req;
2577
+ };
2578
+
2579
+ /**
2580
+ * Returns the scheme to use for the transport URLs.
2581
+ *
2582
+ * @api private
2583
+ */
2584
+
2585
+ XHR.prototype.scheme = function () {
2586
+ return this.socket.options.secure ? 'https' : 'http';
2587
+ };
2588
+
2589
+ /**
2590
+ * Check if the XHR transports are supported
2591
+ *
2592
+ * @param {Boolean} xdomain Check if we support cross domain requests.
2593
+ * @returns {Boolean}
2594
+ * @api public
2595
+ */
2596
+
2597
+ XHR.check = function (socket, xdomain) {
2598
+ try {
2599
+ if (io.util.request(xdomain)) {
2600
+ return true;
2601
+ }
2602
+ } catch(e) {}
2603
+
2604
+ return false;
2605
+ };
2606
+
2607
+ /**
2608
+ * Check if the XHR transport supports corss domain requests.
2609
+ *
2610
+ * @returns {Boolean}
2611
+ * @api public
2612
+ */
2613
+
2614
+ XHR.xdomainCheck = function () {
2615
+ return XHR.check(null, true);
2616
+ };
2617
+
2618
+ })(
2619
+ 'undefined' != typeof io ? io.Transport : module.exports
2620
+ , 'undefined' != typeof io ? io : module.parent.exports
2621
+ , this
2622
+ );
2623
+
2624
+ /**
2625
+ * socket.io
2626
+ * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
2627
+ * MIT Licensed
2628
+ */
2629
+
2630
+ (function (exports, io) {
2631
+
2632
+ /**
2633
+ * Expose constructor.
2634
+ */
2635
+
2636
+ exports.htmlfile = HTMLFile;
2637
+
2638
+ /**
2639
+ * The HTMLFile transport creates a `forever iframe` based transport
2640
+ * for Internet Explorer. Regular forever iframe implementations will
2641
+ * continuously trigger the browsers buzy indicators. If the forever iframe
2642
+ * is created inside a `htmlfile` these indicators will not be trigged.
2643
+ *
2644
+ * @constructor
2645
+ * @extends {io.Transport.XHR}
2646
+ * @api public
2647
+ */
2648
+
2649
+ function HTMLFile (socket) {
2650
+ io.Transport.XHR.apply(this, arguments);
2651
+ };
2652
+
2653
+ /**
2654
+ * Inherits from XHR transport.
2655
+ */
2656
+
2657
+ io.util.inherit(HTMLFile, io.Transport.XHR);
2658
+
2659
+ /**
2660
+ * Transport name
2661
+ *
2662
+ * @api public
2663
+ */
2664
+
2665
+ HTMLFile.prototype.name = 'htmlfile';
2666
+
2667
+ /**
2668
+ * Creates a new ActiveX `htmlfile` with a forever loading iframe
2669
+ * that can be used to listen to messages. Inside the generated
2670
+ * `htmlfile` a reference will be made to the HTMLFile transport.
2671
+ *
2672
+ * @api private
2673
+ */
2674
+
2675
+ HTMLFile.prototype.get = function () {
2676
+ this.doc = new ActiveXObject('htmlfile');
2677
+ this.doc.open();
2678
+ this.doc.write('<html></html>');
2679
+ this.doc.close();
2680
+ this.doc.parentWindow.s = this;
2681
+
2682
+ var iframeC = this.doc.createElement('div');
2683
+ iframeC.className = 'socketio';
2684
+
2685
+ this.doc.body.appendChild(iframeC);
2686
+ this.iframe = this.doc.createElement('iframe');
2687
+
2688
+ iframeC.appendChild(this.iframe);
2689
+
2690
+ var self = this
2691
+ , query = io.util.query(this.socket.options.query, 't='+ +new Date);
2692
+
2693
+ this.iframe.src = this.prepareUrl() + query;
2694
+
2695
+ io.util.on(window, 'unload', function () {
2696
+ self.destroy();
2697
+ });
2698
+ };
2699
+
2700
+ /**
2701
+ * The Socket.IO server will write script tags inside the forever
2702
+ * iframe, this function will be used as callback for the incoming
2703
+ * information.
2704
+ *
2705
+ * @param {String} data The message
2706
+ * @param {document} doc Reference to the context
2707
+ * @api private
2708
+ */
2709
+
2710
+ HTMLFile.prototype._ = function (data, doc) {
2711
+ this.onData(data);
2712
+ try {
2713
+ var script = doc.getElementsByTagName('script')[0];
2714
+ script.parentNode.removeChild(script);
2715
+ } catch (e) { }
2716
+ };
2717
+
2718
+ /**
2719
+ * Destroy the established connection, iframe and `htmlfile`.
2720
+ * And calls the `CollectGarbage` function of Internet Explorer
2721
+ * to release the memory.
2722
+ *
2723
+ * @api private
2724
+ */
2725
+
2726
+ HTMLFile.prototype.destroy = function () {
2727
+ if (this.iframe){
2728
+ try {
2729
+ this.iframe.src = 'about:blank';
2730
+ } catch(e){}
2731
+
2732
+ this.doc = null;
2733
+ this.iframe.parentNode.removeChild(this.iframe);
2734
+ this.iframe = null;
2735
+
2736
+ CollectGarbage();
2737
+ }
2738
+ };
2739
+
2740
+ /**
2741
+ * Disconnects the established connection.
2742
+ *
2743
+ * @returns {Transport} Chaining.
2744
+ * @api public
2745
+ */
2746
+
2747
+ HTMLFile.prototype.close = function () {
2748
+ this.destroy();
2749
+ return io.Transport.XHR.prototype.close.call(this);
2750
+ };
2751
+
2752
+ /**
2753
+ * Checks if the browser supports this transport. The browser
2754
+ * must have an `ActiveXObject` implementation.
2755
+ *
2756
+ * @return {Boolean}
2757
+ * @api public
2758
+ */
2759
+
2760
+ HTMLFile.check = function () {
2761
+ if ('ActiveXObject' in window){
2762
+ try {
2763
+ var a = new ActiveXObject('htmlfile');
2764
+ return a && io.Transport.XHR.check();
2765
+ } catch(e){}
2766
+ }
2767
+ return false;
2768
+ };
2769
+
2770
+ /**
2771
+ * Check if cross domain requests are supported.
2772
+ *
2773
+ * @returns {Boolean}
2774
+ * @api public
2775
+ */
2776
+
2777
+ HTMLFile.xdomainCheck = function () {
2778
+ // we can probably do handling for sub-domains, we should
2779
+ // test that it's cross domain but a subdomain here
2780
+ return false;
2781
+ };
2782
+
2783
+ /**
2784
+ * Add the transport to your public io.transports array.
2785
+ *
2786
+ * @api private
2787
+ */
2788
+
2789
+ io.transports.push('htmlfile');
2790
+
2791
+ })(
2792
+ 'undefined' != typeof io ? io.Transport : module.exports
2793
+ , 'undefined' != typeof io ? io : module.parent.exports
2794
+ );
2795
+
2796
+ /**
2797
+ * socket.io
2798
+ * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
2799
+ * MIT Licensed
2800
+ */
2801
+
2802
+ (function (exports, io, global) {
2803
+
2804
+ /**
2805
+ * Expose constructor.
2806
+ */
2807
+
2808
+ exports['xhr-polling'] = XHRPolling;
2809
+
2810
+ /**
2811
+ * The XHR-polling transport uses long polling XHR requests to create a
2812
+ * "persistent" connection with the server.
2813
+ *
2814
+ * @constructor
2815
+ * @api public
2816
+ */
2817
+
2818
+ function XHRPolling () {
2819
+ io.Transport.XHR.apply(this, arguments);
2820
+ };
2821
+
2822
+ /**
2823
+ * Inherits from XHR transport.
2824
+ */
2825
+
2826
+ io.util.inherit(XHRPolling, io.Transport.XHR);
2827
+
2828
+ /**
2829
+ * Merge the properties from XHR transport
2830
+ */
2831
+
2832
+ io.util.merge(XHRPolling, io.Transport.XHR);
2833
+
2834
+ /**
2835
+ * Transport name
2836
+ *
2837
+ * @api public
2838
+ */
2839
+
2840
+ XHRPolling.prototype.name = 'xhr-polling';
2841
+
2842
+ /**
2843
+ * Establish a connection, for iPhone and Android this will be done once the page
2844
+ * is loaded.
2845
+ *
2846
+ * @returns {Transport} Chaining.
2847
+ * @api public
2848
+ */
2849
+
2850
+ XHRPolling.prototype.open = function () {
2851
+ var self = this;
2852
+
2853
+ io.Transport.XHR.prototype.open.call(self);
2854
+ return false;
2855
+ };
2856
+
2857
+ /**
2858
+ * Starts a XHR request to wait for incoming messages.
2859
+ *
2860
+ * @api private
2861
+ */
2862
+
2863
+ function empty () {};
2864
+
2865
+ XHRPolling.prototype.get = function () {
2866
+ if (!this.open) return;
2867
+
2868
+ var self = this;
2869
+
2870
+ function stateChange () {
2871
+ if (this.readyState == 4) {
2872
+ this.onreadystatechange = empty;
2873
+
2874
+ if (this.status == 200) {
2875
+ self.onData(this.responseText);
2876
+ self.get();
2877
+ } else {
2878
+ self.onClose();
2879
+ }
2880
+ }
2881
+ };
2882
+
2883
+ function onload () {
2884
+ this.onload = empty;
2885
+ self.onData(this.responseText);
2886
+ self.get();
2887
+ };
2888
+
2889
+ this.xhr = this.request();
2890
+
2891
+ if (global.XDomainRequest && this.xhr instanceof XDomainRequest) {
2892
+ this.xhr.onload = this.xhr.onerror = onload;
2893
+ } else {
2894
+ this.xhr.onreadystatechange = stateChange;
2895
+ }
2896
+
2897
+ this.xhr.send(null);
2898
+ };
2899
+
2900
+ /**
2901
+ * Handle the unclean close behavior.
2902
+ *
2903
+ * @api private
2904
+ */
2905
+
2906
+ XHRPolling.prototype.onClose = function () {
2907
+ io.Transport.XHR.prototype.onClose.call(this);
2908
+
2909
+ if (this.xhr) {
2910
+ this.xhr.onreadystatechange = this.xhr.onload = empty;
2911
+ try {
2912
+ this.xhr.abort();
2913
+ } catch(e){}
2914
+ this.xhr = null;
2915
+ }
2916
+ };
2917
+
2918
+ /**
2919
+ * Webkit based browsers show a infinit spinner when you start a XHR request
2920
+ * before the browsers onload event is called so we need to defer opening of
2921
+ * the transport until the onload event is called. Wrapping the cb in our
2922
+ * defer method solve this.
2923
+ *
2924
+ * @param {Socket} socket The socket instance that needs a transport
2925
+ * @param {Function} fn The callback
2926
+ * @api private
2927
+ */
2928
+
2929
+ XHRPolling.prototype.ready = function (socket, fn) {
2930
+ var self = this;
2931
+
2932
+ io.util.defer(function () {
2933
+ fn.call(self);
2934
+ });
2935
+ };
2936
+
2937
+ /**
2938
+ * Add the transport to your public io.transports array.
2939
+ *
2940
+ * @api private
2941
+ */
2942
+
2943
+ io.transports.push('xhr-polling');
2944
+
2945
+ })(
2946
+ 'undefined' != typeof io ? io.Transport : module.exports
2947
+ , 'undefined' != typeof io ? io : module.parent.exports
2948
+ , this
2949
+ );
2950
+
2951
+ /**
2952
+ * socket.io
2953
+ * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
2954
+ * MIT Licensed
2955
+ */
2956
+
2957
+ (function (exports, io, global) {
2958
+ /**
2959
+ * There is a way to hide the loading indicator in Firefox. If you create and
2960
+ * remove a iframe it will stop showing the current loading indicator.
2961
+ * Unfortunately we can't feature detect that and UA sniffing is evil.
2962
+ *
2963
+ * @api private
2964
+ */
2965
+
2966
+ var indicator = global.document && "MozAppearance" in
2967
+ global.document.documentElement.style;
2968
+
2969
+ /**
2970
+ * Expose constructor.
2971
+ */
2972
+
2973
+ exports['jsonp-polling'] = JSONPPolling;
2974
+
2975
+ /**
2976
+ * The JSONP transport creates an persistent connection by dynamically
2977
+ * inserting a script tag in the page. This script tag will receive the
2978
+ * information of the Socket.IO server. When new information is received
2979
+ * it creates a new script tag for the new data stream.
2980
+ *
2981
+ * @constructor
2982
+ * @extends {io.Transport.xhr-polling}
2983
+ * @api public
2984
+ */
2985
+
2986
+ function JSONPPolling (socket) {
2987
+ io.Transport['xhr-polling'].apply(this, arguments);
2988
+
2989
+ this.index = io.j.length;
2990
+
2991
+ var self = this;
2992
+
2993
+ io.j.push(function (msg) {
2994
+ self._(msg);
2995
+ });
2996
+ };
2997
+
2998
+ /**
2999
+ * Inherits from XHR polling transport.
3000
+ */
3001
+
3002
+ io.util.inherit(JSONPPolling, io.Transport['xhr-polling']);
3003
+
3004
+ /**
3005
+ * Transport name
3006
+ *
3007
+ * @api public
3008
+ */
3009
+
3010
+ JSONPPolling.prototype.name = 'jsonp-polling';
3011
+
3012
+ /**
3013
+ * Posts a encoded message to the Socket.IO server using an iframe.
3014
+ * The iframe is used because script tags can create POST based requests.
3015
+ * The iframe is positioned outside of the view so the user does not
3016
+ * notice it's existence.
3017
+ *
3018
+ * @param {String} data A encoded message.
3019
+ * @api private
3020
+ */
3021
+
3022
+ JSONPPolling.prototype.post = function (data) {
3023
+ var self = this
3024
+ , query = io.util.query(
3025
+ this.socket.options.query
3026
+ , 't='+ (+new Date) + '&i=' + this.index
3027
+ );
3028
+
3029
+ if (!this.form) {
3030
+ var form = document.createElement('form')
3031
+ , area = document.createElement('textarea')
3032
+ , id = this.iframeId = 'socketio_iframe_' + this.index
3033
+ , iframe;
3034
+
3035
+ form.className = 'socketio';
3036
+ form.style.position = 'absolute';
3037
+ form.style.top = '-1000px';
3038
+ form.style.left = '-1000px';
3039
+ form.target = id;
3040
+ form.method = 'POST';
3041
+ form.setAttribute('accept-charset', 'utf-8');
3042
+ area.name = 'd';
3043
+ form.appendChild(area);
3044
+ document.body.appendChild(form);
3045
+
3046
+ this.form = form;
3047
+ this.area = area;
3048
+ }
3049
+
3050
+ this.form.action = this.prepareUrl() + query;
3051
+
3052
+ function complete () {
3053
+ initIframe();
3054
+ self.socket.setBuffer(false);
3055
+ };
3056
+
3057
+ function initIframe () {
3058
+ if (self.iframe) {
3059
+ self.form.removeChild(self.iframe);
3060
+ }
3061
+
3062
+ try {
3063
+ // ie6 dynamic iframes with target="" support (thanks Chris Lambacher)
3064
+ iframe = document.createElement('<iframe name="'+ self.iframeId +'">');
3065
+ } catch (e) {
3066
+ iframe = document.createElement('iframe');
3067
+ iframe.name = self.iframeId;
3068
+ }
3069
+
3070
+ iframe.id = self.iframeId;
3071
+
3072
+ self.form.appendChild(iframe);
3073
+ self.iframe = iframe;
3074
+ };
3075
+
3076
+ initIframe();
3077
+
3078
+ // we temporarily stringify until we figure out how to prevent
3079
+ // browsers from turning `\n` into `\r\n` in form inputs
3080
+ this.area.value = io.JSON.stringify(data);
3081
+
3082
+ try {
3083
+ this.form.submit();
3084
+ } catch(e) {}
3085
+
3086
+ if (this.iframe.attachEvent) {
3087
+ iframe.onreadystatechange = function () {
3088
+ if (self.iframe.readyState == 'complete') {
3089
+ complete();
3090
+ }
3091
+ };
3092
+ } else {
3093
+ this.iframe.onload = complete;
3094
+ }
3095
+
3096
+ this.socket.setBuffer(true);
3097
+ };
3098
+
3099
+ /**
3100
+ * Creates a new JSONP poll that can be used to listen
3101
+ * for messages from the Socket.IO server.
3102
+ *
3103
+ * @api private
3104
+ */
3105
+
3106
+ JSONPPolling.prototype.get = function () {
3107
+ var self = this
3108
+ , script = document.createElement('script')
3109
+ , query = io.util.query(
3110
+ this.socket.options.query
3111
+ , 't='+ (+new Date) + '&i=' + this.index
3112
+ );
3113
+
3114
+ if (this.script) {
3115
+ this.script.parentNode.removeChild(this.script);
3116
+ this.script = null;
3117
+ }
3118
+
3119
+ script.async = true;
3120
+ script.src = this.prepareUrl() + query;
3121
+ script.onerror = function () {
3122
+ self.onClose();
3123
+ };
3124
+
3125
+ var insertAt = document.getElementsByTagName('script')[0]
3126
+ insertAt.parentNode.insertBefore(script, insertAt);
3127
+ this.script = script;
3128
+
3129
+ if (indicator) {
3130
+ setTimeout(function () {
3131
+ var iframe = document.createElement('iframe');
3132
+ document.body.appendChild(iframe);
3133
+ document.body.removeChild(iframe);
3134
+ }, 100);
3135
+ }
3136
+ };
3137
+
3138
+ /**
3139
+ * Callback function for the incoming message stream from the Socket.IO server.
3140
+ *
3141
+ * @param {String} data The message
3142
+ * @api private
3143
+ */
3144
+
3145
+ JSONPPolling.prototype._ = function (msg) {
3146
+ this.onData(msg);
3147
+ if (this.open) {
3148
+ this.get();
3149
+ }
3150
+ return this;
3151
+ };
3152
+
3153
+ /**
3154
+ * The indicator hack only works after onload
3155
+ *
3156
+ * @param {Socket} socket The socket instance that needs a transport
3157
+ * @param {Function} fn The callback
3158
+ * @api private
3159
+ */
3160
+
3161
+ JSONPPolling.prototype.ready = function (socket, fn) {
3162
+ var self = this;
3163
+ if (!indicator) return fn.call(this);
3164
+
3165
+ io.util.load(function () {
3166
+ fn.call(self);
3167
+ });
3168
+ };
3169
+
3170
+ /**
3171
+ * Checks if browser supports this transport.
3172
+ *
3173
+ * @return {Boolean}
3174
+ * @api public
3175
+ */
3176
+
3177
+ JSONPPolling.check = function () {
3178
+ return 'document' in global;
3179
+ };
3180
+
3181
+ /**
3182
+ * Check if cross domain requests are supported
3183
+ *
3184
+ * @returns {Boolean}
3185
+ * @api public
3186
+ */
3187
+
3188
+ JSONPPolling.xdomainCheck = function () {
3189
+ return true;
3190
+ };
3191
+
3192
+ /**
3193
+ * Add the transport to your public io.transports array.
3194
+ *
3195
+ * @api private
3196
+ */
3197
+
3198
+ io.transports.push('jsonp-polling');
3199
+
3200
+ })(
3201
+ 'undefined' != typeof io ? io.Transport : module.exports
3202
+ , 'undefined' != typeof io ? io : module.parent.exports
3203
+ , this
3204
+ );