webmate 0.1.1 → 0.1.2

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