UNPKG

93.9 kBJavaScriptView Raw
1;(function(){
2
3
4/**
5 * hasOwnProperty.
6 */
7
8var has = Object.prototype.hasOwnProperty;
9
10/**
11 * Require the given path.
12 *
13 * @param {String} path
14 * @return {Object} exports
15 * @api public
16 */
17
18function require(path, parent, orig) {
19 var resolved = require.resolve(path);
20
21 // lookup failed
22 if (null == resolved) {
23 orig = orig || path;
24 parent = parent || 'root';
25 var err = new Error('Failed to require "' + orig + '" from "' + parent + '"');
26 err.path = orig;
27 err.parent = parent;
28 err.require = true;
29 throw err;
30 }
31
32 var module = require.modules[resolved];
33
34 // perform real require()
35 // by invoking the module's
36 // registered function
37 if (!module.exports) {
38 module.exports = {};
39 module.client = module.component = true;
40 module.call(this, module.exports, require.relative(resolved), module);
41 }
42
43 return module.exports;
44}
45
46/**
47 * Registered modules.
48 */
49
50require.modules = {};
51
52/**
53 * Registered aliases.
54 */
55
56require.aliases = {};
57
58/**
59 * Resolve `path`.
60 *
61 * Lookup:
62 *
63 * - PATH/index.js
64 * - PATH.js
65 * - PATH
66 *
67 * @param {String} path
68 * @return {String} path or null
69 * @api private
70 */
71
72require.resolve = function(path) {
73 if (path.charAt(0) === '/') path = path.slice(1);
74 var index = path + '/index.js';
75
76 var paths = [
77 path,
78 path + '.js',
79 path + '.json',
80 path + '/index.js',
81 path + '/index.json'
82 ];
83
84 for (var i = 0; i < paths.length; i++) {
85 var path = paths[i];
86 if (has.call(require.modules, path)) return path;
87 }
88
89 if (has.call(require.aliases, index)) {
90 return require.aliases[index];
91 }
92};
93
94/**
95 * Normalize `path` relative to the current path.
96 *
97 * @param {String} curr
98 * @param {String} path
99 * @return {String}
100 * @api private
101 */
102
103require.normalize = function(curr, path) {
104 var segs = [];
105
106 if ('.' != path.charAt(0)) return path;
107
108 curr = curr.split('/');
109 path = path.split('/');
110
111 for (var i = 0; i < path.length; ++i) {
112 if ('..' == path[i]) {
113 curr.pop();
114 } else if ('.' != path[i] && '' != path[i]) {
115 segs.push(path[i]);
116 }
117 }
118
119 return curr.concat(segs).join('/');
120};
121
122/**
123 * Register module at `path` with callback `definition`.
124 *
125 * @param {String} path
126 * @param {Function} definition
127 * @api private
128 */
129
130require.register = function(path, definition) {
131 require.modules[path] = definition;
132};
133
134/**
135 * Alias a module definition.
136 *
137 * @param {String} from
138 * @param {String} to
139 * @api private
140 */
141
142require.alias = function(from, to) {
143 if (!has.call(require.modules, from)) {
144 throw new Error('Failed to alias "' + from + '", it does not exist');
145 }
146 require.aliases[to] = from;
147};
148
149/**
150 * Return a require function relative to the `parent` path.
151 *
152 * @param {String} parent
153 * @return {Function}
154 * @api private
155 */
156
157require.relative = function(parent) {
158 var p = require.normalize(parent, '..');
159
160 /**
161 * lastIndexOf helper.
162 */
163
164 function lastIndexOf(arr, obj) {
165 var i = arr.length;
166 while (i--) {
167 if (arr[i] === obj) return i;
168 }
169 return -1;
170 }
171
172 /**
173 * The relative require() itself.
174 */
175
176 function localRequire(path) {
177 var resolved = localRequire.resolve(path);
178 return require(resolved, parent, path);
179 }
180
181 /**
182 * Resolve relative to the parent.
183 */
184
185 localRequire.resolve = function(path) {
186 var c = path.charAt(0);
187 if ('/' == c) return path.slice(1);
188 if ('.' == c) return require.normalize(p, path);
189
190 // resolve deps by returning
191 // the dep in the nearest "deps"
192 // directory
193 var segs = parent.split('/');
194 var i = lastIndexOf(segs, 'deps') + 1;
195 if (!i) i = 0;
196 path = segs.slice(0, i + 1).join('/') + '/deps/' + path;
197 return path;
198 };
199
200 /**
201 * Check if module is defined at `path`.
202 */
203
204 localRequire.exists = function(path) {
205 return has.call(require.modules, localRequire.resolve(path));
206 };
207
208 return localRequire;
209};
210require.register("LearnBoost-engine.io-protocol/lib/index.js", function(exports, require, module){
211/**
212 * Module dependencies.
213 */
214
215var keys = require('./keys')
216
217/**
218 * Packet types.
219 */
220
221var packets = exports.packets = {
222 open: 0 // non-ws
223 , close: 1 // non-ws
224 , ping: 2
225 , pong: 3
226 , message: 4
227 , upgrade: 5
228 , noop: 6
229};
230
231var packetslist = keys(packets);
232
233/**
234 * Premade error packet.
235 */
236
237var err = { type: 'error', data: 'parser error' }
238
239/**
240 * Encodes a packet.
241 *
242 * <packet type id> [ `:` <data> ]
243 *
244 * Example:
245 *
246 * 5:hello world
247 * 3
248 * 4
249 *
250 * @api private
251 */
252
253exports.encodePacket = function (packet) {
254 var encoded = packets[packet.type];
255
256 // data fragment is optional
257 if (undefined !== packet.data) {
258 encoded += String(packet.data);
259 }
260
261 return '' + encoded;
262};
263
264/**
265 * Decodes a packet.
266 *
267 * @return {Object} with `type` and `data` (if any)
268 * @api private
269 */
270
271exports.decodePacket = function (data) {
272 var type = data.charAt(0);
273
274 if (Number(type) != type || !packetslist[type]) {
275 return err;
276 }
277
278 if (data.length > 1) {
279 return { type: packetslist[type], data: data.substring(1) };
280 } else {
281 return { type: packetslist[type] };
282 }
283};
284
285/**
286 * Encodes multiple messages (payload).
287 *
288 * <length>:data
289 *
290 * Example:
291 *
292 * 11:hello world2:hi
293 *
294 * @param {Array} packets
295 * @api private
296 */
297
298exports.encodePayload = function (packets) {
299 if (!packets.length) {
300 return '0:';
301 }
302
303 var encoded = ''
304 , message
305
306 for (var i = 0, l = packets.length; i < l; i++) {
307 message = exports.encodePacket(packets[i]);
308 encoded += message.length + ':' + message;
309 }
310
311 return encoded;
312};
313
314/*
315 * Decodes data when a payload is maybe expected.
316 *
317 * @param {String} data, callback method
318 * @return {NaN}
319 * @api public
320 */
321
322exports.decodePayload = function (data, callback) {
323 var packet;
324 if (data == '') {
325 // parser error - ignoring payload
326 return callback(err, 0, 1);
327 }
328
329 var length = ''
330 , n, msg;
331
332 for (var i = 0, l = data.length; i < l; i++) {
333 var chr = data.charAt(i);
334
335 if (':' != chr) {
336 length += chr;
337 } else {
338 if ('' == length || (length != (n = Number(length)))) {
339 // parser error - ignoring payload
340 return callback(err, 0, 1);
341 }
342
343 msg = data.substr(i + 1, n);
344
345 if (length != msg.length) {
346 // parser error - ignoring payload
347 return callback(err, 0, 1);
348 }
349
350 if (msg.length) {
351 packet = exports.decodePacket(msg);
352
353 if (err.type == packet.type && err.data == packet.data) {
354 // parser error in individual packet - ignoring payload
355 return callback(err, 0, 1);
356 }
357
358 callback(packet, i + n, l);
359 }
360
361 // advance cursor
362 i += n;
363 length = '';
364 }
365 }
366
367 if (length != '') {
368 // parser error - ignoring payload
369 return callback(err, 0, 1);
370 }
371
372};
373
374});
375require.register("LearnBoost-engine.io-protocol/lib/keys.js", function(exports, require, module){
376
377/**
378 * Gets the keys for an object.
379 *
380 * @return {Array} keys
381 * @api private
382 */
383
384module.exports = Object.keys || function keys (obj){
385 var arr = [];
386 var has = Object.prototype.hasOwnProperty;
387
388 for (var i in obj) {
389 if (has.call(obj, i)) {
390 arr.push(i);
391 }
392 }
393 return arr;
394};
395
396});
397require.register("visionmedia-debug/index.js", function(exports, require, module){
398if ('undefined' == typeof window) {
399 module.exports = require('./lib/debug');
400} else {
401 module.exports = require('./debug');
402}
403
404});
405require.register("visionmedia-debug/debug.js", function(exports, require, module){
406
407/**
408 * Expose `debug()` as the module.
409 */
410
411module.exports = debug;
412
413/**
414 * Create a debugger with the given `name`.
415 *
416 * @param {String} name
417 * @return {Type}
418 * @api public
419 */
420
421function debug(name) {
422 if (!debug.enabled(name)) return function(){};
423
424 return function(fmt){
425 var curr = new Date;
426 var ms = curr - (debug[name] || curr);
427 debug[name] = curr;
428
429 fmt = name
430 + ' '
431 + fmt
432 + ' +' + debug.humanize(ms);
433
434 // This hackery is required for IE8
435 // where `console.log` doesn't have 'apply'
436 window.console
437 && console.log
438 && Function.prototype.apply.call(console.log, console, arguments);
439 }
440}
441
442/**
443 * The currently active debug mode names.
444 */
445
446debug.names = [];
447debug.skips = [];
448
449/**
450 * Enables a debug mode by name. This can include modes
451 * separated by a colon and wildcards.
452 *
453 * @param {String} name
454 * @api public
455 */
456
457debug.enable = function(name) {
458 try {
459 localStorage.debug = name;
460 } catch(e){}
461
462 var split = (name || '').split(/[\s,]+/)
463 , len = split.length;
464
465 for (var i = 0; i < len; i++) {
466 name = split[i].replace('*', '.*?');
467 if (name[0] === '-') {
468 debug.skips.push(new RegExp('^' + name.substr(1) + '$'));
469 }
470 else {
471 debug.names.push(new RegExp('^' + name + '$'));
472 }
473 }
474};
475
476/**
477 * Disable debug output.
478 *
479 * @api public
480 */
481
482debug.disable = function(){
483 debug.enable('');
484};
485
486/**
487 * Humanize the given `ms`.
488 *
489 * @param {Number} m
490 * @return {String}
491 * @api private
492 */
493
494debug.humanize = function(ms) {
495 var sec = 1000
496 , min = 60 * 1000
497 , hour = 60 * min;
498
499 if (ms >= hour) return (ms / hour).toFixed(1) + 'h';
500 if (ms >= min) return (ms / min).toFixed(1) + 'm';
501 if (ms >= sec) return (ms / sec | 0) + 's';
502 return ms + 'ms';
503};
504
505/**
506 * Returns true if the given mode name is enabled, false otherwise.
507 *
508 * @param {String} name
509 * @return {Boolean}
510 * @api public
511 */
512
513debug.enabled = function(name) {
514 for (var i = 0, len = debug.skips.length; i < len; i++) {
515 if (debug.skips[i].test(name)) {
516 return false;
517 }
518 }
519 for (var i = 0, len = debug.names.length; i < len; i++) {
520 if (debug.names[i].test(name)) {
521 return true;
522 }
523 }
524 return false;
525};
526
527// persist
528
529if (window.localStorage) debug.enable(localStorage.debug);
530
531});
532require.register("LearnBoost-engine.io-client/lib/index.js", function(exports, require, module){
533
534module.exports = require('./socket');
535
536/**
537 * Exports parser
538 *
539 * @api public
540 *
541 */
542module.exports.parser = require('engine.io-parser');
543
544});
545require.register("LearnBoost-engine.io-client/lib/socket.js", function(exports, require, module){
546/**
547 * Module dependencies.
548 */
549
550var util = require('./util')
551 , transports = require('./transports')
552 , Emitter = require('./emitter')
553 , debug = require('debug')('engine-client:socket');
554
555/**
556 * Module exports.
557 */
558
559module.exports = Socket;
560
561/**
562 * Global reference.
563 */
564
565var global = util.global();
566
567/**
568 * Socket constructor.
569 *
570 * @param {String|Object} uri or options
571 * @param {Object} options
572 * @api public
573 */
574
575function Socket(uri, opts){
576 if (!(this instanceof Socket)) return new Socket(uri, opts);
577
578 opts = opts || {};
579
580 if ('object' == typeof uri) {
581 opts = uri;
582 uri = null;
583 }
584
585 if (uri) {
586 uri = util.parseUri(uri);
587 opts.host = uri.host;
588 opts.secure = uri.protocol == 'https' || uri.protocol == 'wss';
589 opts.port = uri.port;
590 }
591
592 this.secure = null != opts.secure ? opts.secure :
593 (global.location && 'https:' == location.protocol);
594
595 if (opts.host) {
596 var pieces = opts.host.split(':');
597 opts.hostname = pieces.shift();
598 if (pieces.length) opts.port = pieces.pop();
599 }
600
601 this.hostname = opts.hostname ||
602 (global.location ? location.hostname : 'localhost');
603 this.port = opts.port || (global.location && location.port ?
604 location.port :
605 (this.secure ? 443 : 80));
606 this.query = opts.query || {};
607 this.upgrade = false !== opts.upgrade;
608 this.path = (opts.path || '/engine.io').replace(/\/$/, '') + '/';
609 this.forceJSONP = !!opts.forceJSONP;
610 this.timestampParam = opts.timestampParam || 't';
611 this.timestampRequests = !!opts.timestampRequests;
612 this.flashPath = opts.flashPath || '';
613 this.transports = opts.transports || ['polling', 'websocket', 'flashsocket'];
614 this.readyState = '';
615 this.writeBuffer = [];
616 this.policyPort = opts.policyPort || 843;
617 this.open();
618
619 Socket.sockets.push(this);
620 Socket.sockets.evs.emit('add', this);
621};
622
623/**
624 * Mix in `Emitter`.
625 */
626
627Emitter(Socket.prototype);
628
629/**
630 * Protocol version.
631 *
632 * @api public
633 */
634
635Socket.protocol = 1;
636
637/**
638 * Static EventEmitter.
639 */
640
641Socket.sockets = [];
642Socket.sockets.evs = new Emitter;
643
644/**
645 * Expose deps for legacy compatibility
646 * and standalone browser access.
647 */
648
649Socket.Socket = Socket;
650Socket.Transport = require('./transport');
651Socket.Emitter = require('./emitter');
652Socket.transports = require('./transports');
653Socket.util = require('./util');
654Socket.parser = require('engine.io-parser');
655
656/**
657 * Creates transport of the given type.
658 *
659 * @param {String} transport name
660 * @return {Transport}
661 * @api private
662 */
663
664Socket.prototype.createTransport = function (name) {
665 debug('creating transport "%s"', name);
666 var query = clone(this.query);
667 query.transport = name;
668
669 if (this.id) {
670 query.sid = this.id;
671 }
672
673 var transport = new transports[name]({
674 hostname: this.hostname,
675 port: this.port,
676 secure: this.secure,
677 path: this.path,
678 query: query,
679 forceJSONP: this.forceJSONP,
680 timestampRequests: this.timestampRequests,
681 timestampParam: this.timestampParam,
682 flashPath: this.flashPath,
683 policyPort: this.policyPort
684 });
685
686 return transport;
687};
688
689function clone (obj) {
690 var o = {};
691 for (var i in obj) {
692 if (obj.hasOwnProperty(i)) {
693 o[i] = obj[i];
694 }
695 }
696 return o;
697}
698
699/**
700 * Initializes transport to use and starts probe.
701 *
702 * @api private
703 */
704
705Socket.prototype.open = function () {
706 this.readyState = 'opening';
707 var transport = this.createTransport(this.transports[0]);
708 transport.open();
709 this.setTransport(transport);
710};
711
712/**
713 * Sets the current transport. Disables the existing one (if any).
714 *
715 * @api private
716 */
717
718Socket.prototype.setTransport = function (transport) {
719 var self = this;
720
721 if (this.transport) {
722 debug('clearing existing transport');
723 this.transport.removeAllListeners();
724 }
725
726 // set up transport
727 this.transport = transport;
728
729 // set up transport listeners
730 transport
731 .on('drain', function () {
732 self.flush();
733 })
734 .on('packet', function (packet) {
735 self.onPacket(packet);
736 })
737 .on('error', function (e) {
738 self.onError(e);
739 })
740 .on('close', function () {
741 self.onClose('transport close');
742 });
743};
744
745/**
746 * Probes a transport.
747 *
748 * @param {String} transport name
749 * @api private
750 */
751
752Socket.prototype.probe = function (name) {
753 debug('probing transport "%s"', name);
754 var transport = this.createTransport(name, { probe: 1 })
755 , failed = false
756 , self = this;
757
758 transport.once('open', function () {
759 if (failed) return;
760
761 debug('probe transport "%s" opened', name);
762 transport.send([{ type: 'ping', data: 'probe' }]);
763 transport.once('packet', function (msg) {
764 if (failed) return;
765 if ('pong' == msg.type && 'probe' == msg.data) {
766 debug('probe transport "%s" pong', name);
767 self.upgrading = true;
768 self.emit('upgrading', transport);
769
770 debug('pausing current transport "%s"', self.transport.name);
771 self.transport.pause(function () {
772 if (failed) return;
773 if ('closed' == self.readyState || 'closing' == self.readyState) {
774 return;
775 }
776 debug('changing transport and sending upgrade packet');
777 transport.removeListener('error', onerror);
778 self.emit('upgrade', transport);
779 self.setTransport(transport);
780 transport.send([{ type: 'upgrade' }]);
781 transport = null;
782 self.upgrading = false;
783 self.flush();
784 });
785 } else {
786 debug('probe transport "%s" failed', name);
787 var err = new Error('probe error');
788 err.transport = transport.name;
789 self.emit('error', err);
790 }
791 });
792 });
793
794 transport.once('error', onerror);
795 function onerror(err) {
796 if (failed) return;
797
798 // Any callback called by transport should be ignored since now
799 failed = true;
800
801 var error = new Error('probe error: ' + err);
802 error.transport = transport.name;
803
804 transport.close();
805 transport = null;
806
807 debug('probe transport "%s" failed because of error: %s', name, err);
808
809 self.emit('error', error);
810 };
811
812 transport.open();
813
814 this.once('close', function () {
815 if (transport) {
816 debug('socket closed prematurely - aborting probe');
817 failed = true;
818 transport.close();
819 transport = null;
820 }
821 });
822
823 this.once('upgrading', function (to) {
824 if (transport && to.name != transport.name) {
825 debug('"%s" works - aborting "%s"', to.name, transport.name);
826 transport.close();
827 transport = null;
828 }
829 });
830};
831
832/**
833 * Called when connection is deemed open.
834 *
835 * @api public
836 */
837
838Socket.prototype.onOpen = function () {
839 debug('socket open');
840 this.readyState = 'open';
841 this.emit('open');
842 this.onopen && this.onopen.call(this);
843 this.flush();
844
845 // we check for `readyState` in case an `open`
846 // listener alreay closed the socket
847 if ('open' == this.readyState && this.upgrade && this.transport.pause) {
848 debug('starting upgrade probes');
849 for (var i = 0, l = this.upgrades.length; i < l; i++) {
850 this.probe(this.upgrades[i]);
851 }
852 }
853};
854
855/**
856 * Handles a packet.
857 *
858 * @api private
859 */
860
861Socket.prototype.onPacket = function (packet) {
862 if ('opening' == this.readyState || 'open' == this.readyState) {
863 debug('socket receive: type "%s", data "%s"', packet.type, packet.data);
864
865 this.emit('packet', packet);
866
867 // Socket is live - any packet counts
868 this.emit('heartbeat');
869
870 switch (packet.type) {
871 case 'open':
872 this.onHandshake(util.parseJSON(packet.data));
873 break;
874
875 case 'pong':
876 this.ping();
877 break;
878
879 case 'error':
880 var err = new Error('server error');
881 err.code = packet.data;
882 this.emit('error', err);
883 break;
884
885 case 'message':
886 this.emit('data', packet.data);
887 this.emit('message', packet.data);
888 var event = { data: packet.data };
889 event.toString = function () {
890 return packet.data;
891 };
892 this.onmessage && this.onmessage.call(this, event);
893 break;
894 }
895 } else {
896 debug('packet received with socket readyState "%s"', this.readyState);
897 }
898};
899
900/**
901 * Called upon handshake completion.
902 *
903 * @param {Object} handshake obj
904 * @api private
905 */
906
907Socket.prototype.onHandshake = function (data) {
908 this.emit('handshake', data);
909 this.id = data.sid;
910 this.transport.query.sid = data.sid;
911 this.upgrades = this.filterUpgrades(data.upgrades);
912 this.pingInterval = data.pingInterval;
913 this.pingTimeout = data.pingTimeout;
914 this.onOpen();
915 this.ping();
916
917 // Prolong liveness of socket on heartbeat
918 this.removeListener('heartbeat', this.onHeartbeat);
919 this.on('heartbeat', this.onHeartbeat);
920};
921
922/**
923 * Resets ping timeout.
924 *
925 * @api private
926 */
927
928Socket.prototype.onHeartbeat = function (timeout) {
929 clearTimeout(this.pingTimeoutTimer);
930 var self = this;
931 self.pingTimeoutTimer = setTimeout(function () {
932 if ('closed' == self.readyState) return;
933 self.onClose('ping timeout');
934 }, timeout || (self.pingInterval + self.pingTimeout));
935};
936
937/**
938 * Pings server every `this.pingInterval` and expects response
939 * within `this.pingTimeout` or closes connection.
940 *
941 * @api private
942 */
943
944Socket.prototype.ping = function () {
945 var self = this;
946 clearTimeout(self.pingIntervalTimer);
947 self.pingIntervalTimer = setTimeout(function () {
948 debug('writing ping packet - expecting pong within %sms', self.pingTimeout);
949 self.sendPacket('ping');
950 self.onHeartbeat(self.pingTimeout);
951 }, self.pingInterval);
952};
953
954/**
955 * Flush write buffers.
956 *
957 * @api private
958 */
959
960Socket.prototype.flush = function () {
961 if ('closed' != this.readyState && this.transport.writable &&
962 !this.upgrading && this.writeBuffer.length) {
963 debug('flushing %d packets in socket', this.writeBuffer.length);
964 this.transport.send(this.writeBuffer);
965 this.writeBuffer = [];
966 }
967};
968
969/**
970 * Sends a message.
971 *
972 * @param {String} message.
973 * @return {Socket} for chaining.
974 * @api public
975 */
976
977Socket.prototype.write =
978Socket.prototype.send = function (msg) {
979 this.sendPacket('message', msg);
980 return this;
981};
982
983/**
984 * Sends a packet.
985 *
986 * @param {String} packet type.
987 * @param {String} data.
988 * @api private
989 */
990
991Socket.prototype.sendPacket = function (type, data) {
992 var packet = { type: type, data: data };
993 this.emit('packetCreate', packet);
994 this.writeBuffer.push(packet);
995 this.flush();
996};
997
998/**
999 * Closes the connection.
1000 *
1001 * @api private
1002 */
1003
1004Socket.prototype.close = function () {
1005 if ('opening' == this.readyState || 'open' == this.readyState) {
1006 this.onClose('forced close');
1007 debug('socket closing - telling transport to close');
1008 this.transport.close();
1009 this.transport.removeAllListeners();
1010 }
1011
1012 return this;
1013};
1014
1015/**
1016 * Called upon transport error
1017 *
1018 * @api private
1019 */
1020
1021Socket.prototype.onError = function (err) {
1022 debug('socket error %j', err);
1023 this.emit('error', err);
1024 this.onClose('transport error', err);
1025};
1026
1027/**
1028 * Called upon transport close.
1029 *
1030 * @api private
1031 */
1032
1033Socket.prototype.onClose = function (reason, desc) {
1034 if ('opening' == this.readyState || 'open' == this.readyState) {
1035 debug('socket close with reason: "%s"', reason);
1036 clearTimeout(this.pingIntervalTimer);
1037 clearTimeout(this.pingTimeoutTimer);
1038 this.readyState = 'closed';
1039 this.emit('close', reason, desc);
1040 this.onclose && this.onclose.call(this);
1041 this.id = null;
1042 }
1043};
1044
1045/**
1046 * Filters upgrades, returning only those matching client transports.
1047 *
1048 * @param {Array} server upgrades
1049 * @api private
1050 *
1051 */
1052
1053Socket.prototype.filterUpgrades = function (upgrades) {
1054 var filteredUpgrades = [];
1055 for (var i = 0, j = upgrades.length; i<j; i++) {
1056 if (~this.transports.indexOf(upgrades[i])) filteredUpgrades.push(upgrades[i]);
1057 }
1058 return filteredUpgrades;
1059};
1060});
1061require.register("LearnBoost-engine.io-client/lib/transport.js", function(exports, require, module){
1062
1063/**
1064 * Module dependencies.
1065 */
1066
1067var util = require('./util')
1068 , parser = require('engine.io-parser')
1069 , Emitter = require('./emitter');
1070
1071/**
1072 * Module exports.
1073 */
1074
1075module.exports = Transport;
1076
1077/**
1078 * Transport abstract constructor.
1079 *
1080 * @param {Object} options.
1081 * @api private
1082 */
1083
1084function Transport (opts) {
1085 this.path = opts.path;
1086 this.hostname = opts.hostname;
1087 this.port = opts.port;
1088 this.secure = opts.secure;
1089 this.query = opts.query;
1090 this.timestampParam = opts.timestampParam;
1091 this.timestampRequests = opts.timestampRequests;
1092 this.readyState = '';
1093};
1094
1095/**
1096 * Mix in `Emitter`.
1097 */
1098
1099Emitter(Transport.prototype);
1100
1101/**
1102 * Emits an error.
1103 *
1104 * @param {String} str
1105 * @return {Transport} for chaining
1106 * @api public
1107 */
1108
1109Transport.prototype.onError = function (msg, desc) {
1110 var err = new Error(msg);
1111 err.type = 'TransportError';
1112 err.description = desc;
1113 this.emit('error', err);
1114 return this;
1115};
1116
1117/**
1118 * Opens the transport.
1119 *
1120 * @api public
1121 */
1122
1123Transport.prototype.open = function () {
1124 if ('closed' == this.readyState || '' == this.readyState) {
1125 this.readyState = 'opening';
1126 this.doOpen();
1127 }
1128
1129 return this;
1130};
1131
1132/**
1133 * Closes the transport.
1134 *
1135 * @api private
1136 */
1137
1138Transport.prototype.close = function () {
1139 if ('opening' == this.readyState || 'open' == this.readyState) {
1140 this.doClose();
1141 this.onClose();
1142 }
1143
1144 return this;
1145};
1146
1147/**
1148 * Sends multiple packets.
1149 *
1150 * @param {Array} packets
1151 * @api private
1152 */
1153
1154Transport.prototype.send = function(packets){
1155 if ('open' == this.readyState) {
1156 this.write(packets);
1157 } else {
1158 throw new Error('Transport not open');
1159 }
1160};
1161
1162/**
1163 * Called upon open
1164 *
1165 * @api private
1166 */
1167
1168Transport.prototype.onOpen = function () {
1169 this.readyState = 'open';
1170 this.writable = true;
1171 this.emit('open');
1172};
1173
1174/**
1175 * Called with data.
1176 *
1177 * @param {String} data
1178 * @api private
1179 */
1180
1181Transport.prototype.onData = function (data) {
1182 this.onPacket(parser.decodePacket(data));
1183};
1184
1185/**
1186 * Called with a decoded packet.
1187 */
1188
1189Transport.prototype.onPacket = function (packet) {
1190 this.emit('packet', packet);
1191};
1192
1193/**
1194 * Called upon close.
1195 *
1196 * @api private
1197 */
1198
1199Transport.prototype.onClose = function () {
1200 this.readyState = 'closed';
1201 this.emit('close');
1202};
1203
1204});
1205require.register("LearnBoost-engine.io-client/lib/emitter.js", function(exports, require, module){
1206
1207/**
1208 * Module dependencies.
1209 */
1210
1211var Emitter;
1212
1213try {
1214 Emitter = require('emitter');
1215} catch(e){
1216 Emitter = require('emitter-component');
1217}
1218
1219/**
1220 * Module exports.
1221 */
1222
1223module.exports = Emitter;
1224
1225/**
1226 * Compatibility with `WebSocket#addEventListener`.
1227 *
1228 * @api public
1229 */
1230
1231Emitter.prototype.addEventListener = Emitter.prototype.on;
1232
1233/**
1234 * Compatibility with `WebSocket#removeEventListener`.
1235 *
1236 * @api public
1237 */
1238
1239Emitter.prototype.removeEventListener = Emitter.prototype.off;
1240
1241/**
1242 * Node-compatible `EventEmitter#removeListener`
1243 *
1244 * @api public
1245 */
1246
1247Emitter.prototype.removeListener = Emitter.prototype.off;
1248
1249/**
1250 * Node-compatible `EventEmitter#removeAllListeners`
1251 *
1252 * @api public
1253 */
1254
1255Emitter.prototype.removeAllListeners = function(){
1256 this._callbacks = {};
1257};
1258
1259});
1260require.register("LearnBoost-engine.io-client/lib/util.js", function(exports, require, module){
1261/**
1262 * Status of page load.
1263 */
1264
1265var pageLoaded = false;
1266
1267/**
1268 * Returns the global object
1269 *
1270 * @api private
1271 */
1272
1273exports.global = function () {
1274 return 'undefined' != typeof window ? window : global;
1275};
1276
1277/**
1278 * Inheritance.
1279 *
1280 * @param {Function} ctor a
1281 * @param {Function} ctor b
1282 * @api private
1283 */
1284
1285exports.inherits = function inherits (a, b) {
1286 function c () { }
1287 c.prototype = b.prototype;
1288 a.prototype = new c;
1289};
1290
1291/**
1292 * Object.keys
1293 */
1294
1295exports.keys = Object.keys || function (obj) {
1296 var ret = [];
1297 var has = Object.prototype.hasOwnProperty;
1298
1299 for (var i in obj) {
1300 if (has.call(obj, i)) {
1301 ret.push(i);
1302 }
1303 }
1304
1305 return ret;
1306};
1307
1308/**
1309 * Adds an event.
1310 *
1311 * @api private
1312 */
1313
1314exports.on = function (element, event, fn, capture) {
1315 if (element.attachEvent) {
1316 element.attachEvent('on' + event, fn);
1317 } else if (element.addEventListener) {
1318 element.addEventListener(event, fn, capture);
1319 }
1320};
1321
1322/**
1323 * Load utility.
1324 *
1325 * @api private
1326 */
1327
1328exports.load = function (fn) {
1329 var global = exports.global();
1330 if (global.document && document.readyState === 'complete' || pageLoaded) {
1331 return fn();
1332 }
1333
1334 exports.on(global, 'load', fn, false);
1335};
1336
1337/**
1338 * Change the internal pageLoaded value.
1339 */
1340
1341if ('undefined' != typeof window) {
1342 exports.load(function () {
1343 pageLoaded = true;
1344 });
1345}
1346
1347/**
1348 * Defers a function to ensure a spinner is not displayed by the browser.
1349 *
1350 * @param {Function} fn
1351 * @api private
1352 */
1353
1354exports.defer = function (fn) {
1355 if (!exports.ua.webkit || 'undefined' != typeof importScripts) {
1356 return fn();
1357 }
1358
1359 exports.load(function () {
1360 setTimeout(fn, 100);
1361 });
1362};
1363
1364/**
1365 * JSON parse.
1366 *
1367 * @see Based on jQuery#parseJSON (MIT) and JSON2
1368 * @api private
1369 */
1370
1371var rvalidchars = /^[\],:{}\s]*$/
1372 , rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g
1373 , rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g
1374 , rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g
1375 , rtrimLeft = /^\s+/
1376 , rtrimRight = /\s+$/
1377
1378exports.parseJSON = function (data) {
1379 var global = exports.global();
1380
1381 if ('string' != typeof data || !data) {
1382 return null;
1383 }
1384
1385 data = data.replace(rtrimLeft, '').replace(rtrimRight, '');
1386
1387 // Attempt to parse using the native JSON parser first
1388 if (global.JSON && JSON.parse) {
1389 return JSON.parse(data);
1390 }
1391
1392 if (rvalidchars.test(data.replace(rvalidescape, '@')
1393 .replace(rvalidtokens, ']')
1394 .replace(rvalidbraces, ''))) {
1395 return (new Function('return ' + data))();
1396 }
1397};
1398
1399/**
1400 * UA / engines detection namespace.
1401 *
1402 * @namespace
1403 */
1404
1405exports.ua = {};
1406
1407/**
1408 * Whether the UA supports CORS for XHR.
1409 *
1410 * @api private
1411 */
1412
1413exports.ua.hasCORS = 'undefined' != typeof XMLHttpRequest && (function () {
1414 try {
1415 var a = new XMLHttpRequest();
1416 } catch (e) {
1417 return false;
1418 }
1419
1420 return a.withCredentials != undefined;
1421})();
1422
1423/**
1424 * Detect webkit.
1425 *
1426 * @api private
1427 */
1428
1429exports.ua.webkit = 'undefined' != typeof navigator &&
1430 /webkit/i.test(navigator.userAgent);
1431
1432/**
1433 * Detect gecko.
1434 *
1435 * @api private
1436 */
1437
1438exports.ua.gecko = 'undefined' != typeof navigator &&
1439 /gecko/i.test(navigator.userAgent);
1440
1441/**
1442 * Detect android;
1443 */
1444
1445exports.ua.android = 'undefined' != typeof navigator &&
1446 /android/i.test(navigator.userAgent);
1447
1448/**
1449 * Detect iOS.
1450 */
1451
1452exports.ua.ios = 'undefined' != typeof navigator &&
1453 /^(iPad|iPhone|iPod)$/.test(navigator.platform);
1454exports.ua.ios6 = exports.ua.ios && /OS 6_/.test(navigator.userAgent);
1455
1456/**
1457 * XHR request helper.
1458 *
1459 * @param {Boolean} whether we need xdomain
1460 * @api private
1461 */
1462
1463exports.request = function request (xdomain) {
1464 if ('undefined' == typeof window) {
1465 var _XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;
1466 return new _XMLHttpRequest();
1467 }
1468
1469 if (xdomain && 'undefined' != typeof XDomainRequest && !exports.ua.hasCORS) {
1470 return new XDomainRequest();
1471 }
1472
1473 // XMLHttpRequest can be disabled on IE
1474 try {
1475 if ('undefined' != typeof XMLHttpRequest && (!xdomain || exports.ua.hasCORS)) {
1476 return new XMLHttpRequest();
1477 }
1478 } catch (e) { }
1479
1480 if (!xdomain) {
1481 try {
1482 return new ActiveXObject('Microsoft.XMLHTTP');
1483 } catch(e) { }
1484 }
1485};
1486
1487/**
1488 * Parses an URI
1489 *
1490 * @author Steven Levithan <stevenlevithan.com> (MIT license)
1491 * @api private
1492 */
1493
1494var re = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
1495
1496var parts = [
1497 'source', 'protocol', 'authority', 'userInfo', 'user', 'password', 'host'
1498 , 'port', 'relative', 'path', 'directory', 'file', 'query', 'anchor'
1499];
1500
1501exports.parseUri = function (str) {
1502 var m = re.exec(str || '')
1503 , uri = {}
1504 , i = 14;
1505
1506 while (i--) {
1507 uri[parts[i]] = m[i] || '';
1508 }
1509
1510 return uri;
1511};
1512
1513/**
1514 * Compiles a querystring
1515 *
1516 * @param {Object}
1517 * @api private
1518 */
1519
1520exports.qs = function (obj) {
1521 var str = '';
1522
1523 for (var i in obj) {
1524 if (obj.hasOwnProperty(i)) {
1525 if (str.length) str += '&';
1526 str += i + '=' + encodeURIComponent(obj[i]);
1527 }
1528 }
1529
1530 return str;
1531};
1532
1533});
1534require.register("LearnBoost-engine.io-client/lib/transports/index.js", function(exports, require, module){
1535
1536/**
1537 * Module dependencies
1538 */
1539
1540var XHR = require('./polling-xhr')
1541 , JSONP = require('./polling-jsonp')
1542 , websocket = require('./websocket')
1543 , flashsocket = require('./flashsocket')
1544 , util = require('../util');
1545
1546/**
1547 * Export transports.
1548 */
1549
1550exports.polling = polling;
1551exports.websocket = websocket;
1552exports.flashsocket = flashsocket;
1553
1554/**
1555 * Global reference.
1556 */
1557
1558var global = util.global()
1559
1560/**
1561 * Polling transport polymorphic constructor.
1562 * Decides on xhr vs jsonp based on feature detection.
1563 *
1564 * @api private
1565 */
1566
1567function polling (opts) {
1568 var xhr
1569 , xd = false
1570 , isXProtocol = false;
1571
1572 if (global.location) {
1573 var isSSL = 'https:' == location.protocol;
1574 var port = location.port;
1575
1576 // some user agents have empty `location.port`
1577 if (Number(port) != port) {
1578 port = isSSL ? 443 : 80;
1579 }
1580
1581 xd = opts.host != location.hostname || port != opts.port;
1582 isXProtocol = opts.secure != isSSL;
1583 }
1584
1585 xhr = util.request(xd);
1586 /* See #7 at http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx */
1587 if (isXProtocol && global.XDomainRequest && xhr instanceof global.XDomainRequest) {
1588 return new JSONP(opts);
1589 }
1590
1591 if (xhr && !opts.forceJSONP) {
1592 return new XHR(opts);
1593 } else {
1594 return new JSONP(opts);
1595 }
1596};
1597
1598});
1599require.register("LearnBoost-engine.io-client/lib/transports/polling.js", function(exports, require, module){
1600/**
1601 * Module dependencies.
1602 */
1603
1604var Transport = require('../transport')
1605 , util = require('../util')
1606 , parser = require('engine.io-parser')
1607 , debug = require('debug')('engine.io-client:polling');
1608
1609/**
1610 * Module exports.
1611 */
1612
1613module.exports = Polling;
1614
1615/**
1616 * Global reference.
1617 */
1618
1619var global = util.global();
1620
1621/**
1622 * Polling interface.
1623 *
1624 * @param {Object} opts
1625 * @api private
1626 */
1627
1628function Polling(opts){
1629 Transport.call(this, opts);
1630}
1631
1632/**
1633 * Inherits from Transport.
1634 */
1635
1636util.inherits(Polling, Transport);
1637
1638/**
1639 * Transport name.
1640 */
1641
1642Polling.prototype.name = 'polling';
1643
1644/**
1645 * Opens the socket (triggers polling). We write a PING message to determine
1646 * when the transport is open.
1647 *
1648 * @api private
1649 */
1650
1651Polling.prototype.doOpen = function(){
1652 this.poll();
1653};
1654
1655/**
1656 * Pauses polling.
1657 *
1658 * @param {Function} callback upon buffers are flushed and transport is paused
1659 * @api private
1660 */
1661
1662Polling.prototype.pause = function(onPause){
1663 var pending = 0;
1664 var self = this;
1665
1666 this.readyState = 'pausing';
1667
1668 function pause(){
1669 debug('paused');
1670 self.readyState = 'paused';
1671 onPause();
1672 }
1673
1674 if (this.polling || !this.writable) {
1675 var total = 0;
1676
1677 if (this.polling) {
1678 debug('we are currently polling - waiting to pause');
1679 total++;
1680 this.once('pollComplete', function(){
1681 debug('pre-pause polling complete');
1682 --total || pause();
1683 });
1684 }
1685
1686 if (!this.writable) {
1687 debug('we are currently writing - waiting to pause');
1688 total++;
1689 this.once('drain', function(){
1690 debug('pre-pause writing complete');
1691 --total || pause();
1692 });
1693 }
1694 } else {
1695 pause();
1696 }
1697};
1698
1699/**
1700 * Starts polling cycle.
1701 *
1702 * @api public
1703 */
1704
1705Polling.prototype.poll = function(){
1706 debug('polling');
1707 this.polling = true;
1708 this.doPoll();
1709 this.emit('poll');
1710};
1711
1712/**
1713 * Overloads onData to detect payloads.
1714 *
1715 * @api private
1716 */
1717
1718Polling.prototype.onData = function(data){
1719 var self = this;
1720 debug('polling got data %s', data);
1721 // decode payload
1722 parser.decodePayload(data, function(packet, index, total) {self.onDataCallback(packet, index, total)});
1723};
1724
1725/**
1726 * Callback function for payloads
1727 *
1728 * @api private
1729 */
1730
1731Polling.prototype.onDataCallback = function(packet, index, total){
1732 // if its the first message we consider the transport open
1733 if ('opening' == this.readyState) {
1734 this.onOpen();
1735 }
1736
1737 // if its a close packet, we close the ongoing requests
1738 if ('close' == packet.type) {
1739 this.onClose();
1740 return;
1741 }
1742
1743 // otherwise bypass onData and handle the message
1744 this.onPacket(packet);
1745
1746 // if we got data we're not polling
1747 this.polling = false;
1748 this.emit('pollComplete');
1749
1750 if ('open' == this.readyState) {
1751 this.poll();
1752 } else {
1753 debug('ignoring poll - transport state "%s"', this.readyState);
1754 }
1755};
1756
1757/**
1758 * For polling, send a close packet.
1759 *
1760 * @api private
1761 */
1762
1763Polling.prototype.doClose = function(){
1764 debug('sending close packet');
1765 this.send([{ type: 'close' }]);
1766};
1767
1768/**
1769 * Writes a packets payload.
1770 *
1771 * @param {Array} data packets
1772 * @param {Function} drain callback
1773 * @api private
1774 */
1775
1776Polling.prototype.write = function(packets){
1777 var self = this;
1778 this.writable = false;
1779 this.doWrite(parser.encodePayload(packets), function(){
1780 self.writable = true;
1781 self.emit('drain');
1782 });
1783};
1784
1785/**
1786 * Generates uri for connection.
1787 *
1788 * @api private
1789 */
1790
1791Polling.prototype.uri = function(){
1792 var query = this.query || {};
1793 var schema = this.secure ? 'https' : 'http';
1794 var port = '';
1795
1796 // cache busting is forced for IE / android / iOS6 ಠ_ಠ
1797 if (global.ActiveXObject || util.ua.android || util.ua.ios6 ||
1798 this.timestampRequests) {
1799 query[this.timestampParam] = +new Date;
1800 }
1801
1802 query = util.qs(query);
1803
1804 // avoid port if default for schema
1805 if (this.port && (('https' == schema && this.port != 443) ||
1806 ('http' == schema && this.port != 80))) {
1807 port = ':' + this.port;
1808 }
1809
1810 // prepend ? to query
1811 if (query.length) {
1812 query = '?' + query;
1813 }
1814
1815 return schema + '://' + this.hostname + port + this.path + query;
1816};
1817
1818});
1819require.register("LearnBoost-engine.io-client/lib/transports/polling-xhr.js", function(exports, require, module){
1820/**
1821 * Module requirements.
1822 */
1823
1824var Polling = require('./polling')
1825 , util = require('../util')
1826 , Emitter = require('../emitter')
1827 , debug = require('debug')('engine.io-client:polling-xhr');
1828
1829/**
1830 * Module exports.
1831 */
1832
1833module.exports = XHR;
1834module.exports.Request = Request;
1835
1836/**
1837 * Global reference.
1838 */
1839
1840var global = util.global();
1841
1842
1843/**
1844 * Obfuscated key for Blue Coat.
1845 */
1846
1847var xobject = global[['Active'].concat('Object').join('X')];
1848
1849/**
1850 * Empty function
1851 */
1852
1853function empty(){}
1854
1855/**
1856 * XHR Polling constructor.
1857 *
1858 * @param {Object} opts
1859 * @api public
1860 */
1861
1862function XHR(opts){
1863 Polling.call(this, opts);
1864
1865 if (global.location) {
1866 this.xd = opts.host != global.location.hostname ||
1867 global.location.port != opts.port;
1868 }
1869};
1870
1871/**
1872 * Inherits from Polling.
1873 */
1874
1875util.inherits(XHR, Polling);
1876
1877/**
1878 * Opens the socket
1879 *
1880 * @api private
1881 */
1882
1883XHR.prototype.doOpen = function(){
1884 var self = this;
1885 util.defer(function(){
1886 Polling.prototype.doOpen.call(self);
1887 });
1888};
1889
1890/**
1891 * Creates a request.
1892 *
1893 * @param {String} method
1894 * @api private
1895 */
1896
1897XHR.prototype.request = function(opts){
1898 opts = opts || {};
1899 opts.uri = this.uri();
1900 opts.xd = this.xd;
1901 return new Request(opts);
1902};
1903
1904/**
1905 * Sends data.
1906 *
1907 * @param {String} data to send.
1908 * @param {Function} called upon flush.
1909 * @api private
1910 */
1911
1912XHR.prototype.doWrite = function(data, fn){
1913 var req = this.request({ method: 'POST', data: data });
1914 var self = this;
1915 req.on('success', fn);
1916 req.on('error', function(err){
1917 self.onError('xhr post error', err);
1918 });
1919 this.sendXhr = req;
1920};
1921
1922/**
1923 * Starts a poll cycle.
1924 *
1925 * @api private
1926 */
1927
1928XHR.prototype.doPoll = function(){
1929 debug('xhr poll');
1930 var req = this.request();
1931 var self = this;
1932 req.on('data', function(data){
1933 self.onData(data);
1934 });
1935 req.on('error', function(err){
1936 self.onError('xhr poll error', err);
1937 });
1938 this.pollXhr = req;
1939};
1940
1941/**
1942 * Request constructor
1943 *
1944 * @param {Object} options
1945 * @api public
1946 */
1947
1948function Request(opts){
1949 this.method = opts.method || 'GET';
1950 this.uri = opts.uri;
1951 this.xd = !!opts.xd;
1952 this.async = false !== opts.async;
1953 this.data = undefined != opts.data ? opts.data : null;
1954 this.create();
1955}
1956
1957/**
1958 * Mix in `Emitter`.
1959 */
1960
1961Emitter(Request.prototype);
1962
1963/**
1964 * Creates the XHR object and sends the request.
1965 *
1966 * @api private
1967 */
1968
1969Request.prototype.create = function(){
1970 var xhr = this.xhr = util.request(this.xd);
1971 var self = this;
1972
1973 xhr.open(this.method, this.uri, this.async);
1974
1975 if ('POST' == this.method) {
1976 try {
1977 if (xhr.setRequestHeader) {
1978 // xmlhttprequest
1979 xhr.setRequestHeader('Content-type', 'text/plain;charset=UTF-8');
1980 } else {
1981 // xdomainrequest
1982 xhr.contentType = 'text/plain';
1983 }
1984 } catch (e) {}
1985 }
1986
1987 if (this.xd && global.XDomainRequest && xhr instanceof XDomainRequest) {
1988 xhr.onerror = function(e){
1989 self.onError(e);
1990 };
1991 xhr.onload = function(){
1992 self.onData(xhr.responseText);
1993 };
1994 xhr.onprogress = empty;
1995 } else {
1996 // ie6 check
1997 if ('withCredentials' in xhr) {
1998 xhr.withCredentials = true;
1999 }
2000
2001 xhr.onreadystatechange = function(){
2002 var data;
2003
2004 try {
2005 if (4 != xhr.readyState) return;
2006 if (200 == xhr.status || 1223 == xhr.status) {
2007 data = xhr.responseText;
2008 } else {
2009 self.onError(xhr.status);
2010 }
2011 } catch (e) {
2012 self.onError(e);
2013 }
2014
2015 if (undefined !== data) {
2016 self.onData(data);
2017 }
2018 };
2019 }
2020
2021 debug('sending xhr with url %s | data %s', this.uri, this.data);
2022 xhr.send(this.data);
2023
2024 if (xobject) {
2025 this.index = Request.requestsCount++;
2026 Request.requests[this.index] = this;
2027 }
2028};
2029
2030/**
2031 * Called upon successful response.
2032 *
2033 * @api private
2034 */
2035
2036Request.prototype.onSuccess = function(){
2037 this.emit('success');
2038 this.cleanup();
2039};
2040
2041/**
2042 * Called if we have data.
2043 *
2044 * @api private
2045 */
2046
2047Request.prototype.onData = function(data){
2048 this.emit('data', data);
2049 this.onSuccess();
2050};
2051
2052/**
2053 * Called upon error.
2054 *
2055 * @api private
2056 */
2057
2058Request.prototype.onError = function(err){
2059 this.emit('error', err);
2060 this.cleanup();
2061};
2062
2063/**
2064 * Cleans up house.
2065 *
2066 * @api private
2067 */
2068
2069Request.prototype.cleanup = function(){
2070 // xmlhttprequest
2071 this.xhr.onreadystatechange = empty;
2072
2073 // xdomainrequest
2074 this.xhr.onload = this.xhr.onerror = empty;
2075
2076 try {
2077 this.xhr.abort();
2078 } catch(e) {}
2079
2080 if (xobject) {
2081 delete Request.requests[this.index];
2082 }
2083
2084 this.xhr = null;
2085};
2086
2087/**
2088 * Aborts the request.
2089 *
2090 * @api public
2091 */
2092
2093Request.prototype.abort = function(){
2094 this.cleanup();
2095};
2096
2097if (xobject) {
2098 Request.requestsCount = 0;
2099 Request.requests = {};
2100
2101 global.attachEvent('onunload', function(){
2102 for (var i in Request.requests) {
2103 if (Request.requests.hasOwnProperty(i)) {
2104 Request.requests[i].abort();
2105 }
2106 }
2107 });
2108}
2109
2110});
2111require.register("LearnBoost-engine.io-client/lib/transports/polling-jsonp.js", function(exports, require, module){
2112
2113/**
2114 * Module requirements.
2115 */
2116
2117var Polling = require('./polling')
2118 , util = require('../util');
2119
2120/**
2121 * Module exports.
2122 */
2123
2124module.exports = JSONPPolling;
2125
2126/**
2127 * Global reference.
2128 */
2129
2130var global = util.global();
2131
2132/**
2133 * Cached regular expressions.
2134 */
2135
2136var rNewline = /\n/g;
2137
2138/**
2139 * Global JSONP callbacks.
2140 */
2141
2142var callbacks;
2143
2144/**
2145 * Callbacks count.
2146 */
2147
2148var index = 0;
2149
2150/**
2151 * Noop.
2152 */
2153
2154function empty () { }
2155
2156/**
2157 * JSONP Polling constructor.
2158 *
2159 * @param {Object} opts.
2160 * @api public
2161 */
2162
2163function JSONPPolling (opts) {
2164 Polling.call(this, opts);
2165
2166 // define global callbacks array if not present
2167 // we do this here (lazily) to avoid unneeded global pollution
2168 if (!callbacks) {
2169 // we need to consider multiple engines in the same page
2170 if (!global.___eio) global.___eio = [];
2171 callbacks = global.___eio;
2172 }
2173
2174 // callback identifier
2175 this.index = callbacks.length;
2176
2177 // add callback to jsonp global
2178 var self = this;
2179 callbacks.push(function (msg) {
2180 self.onData(msg);
2181 });
2182
2183 // append to query string
2184 this.query.j = this.index;
2185};
2186
2187/**
2188 * Inherits from Polling.
2189 */
2190
2191util.inherits(JSONPPolling, Polling);
2192
2193/**
2194 * Opens the socket.
2195 *
2196 * @api private
2197 */
2198
2199JSONPPolling.prototype.doOpen = function () {
2200 var self = this;
2201 util.defer(function () {
2202 Polling.prototype.doOpen.call(self);
2203 });
2204};
2205
2206/**
2207 * Closes the socket
2208 *
2209 * @api private
2210 */
2211
2212JSONPPolling.prototype.doClose = function () {
2213 if (this.script) {
2214 this.script.parentNode.removeChild(this.script);
2215 this.script = null;
2216 }
2217
2218 if (this.form) {
2219 this.form.parentNode.removeChild(this.form);
2220 this.form = null;
2221 }
2222
2223 Polling.prototype.doClose.call(this);
2224};
2225
2226/**
2227 * Starts a poll cycle.
2228 *
2229 * @api private
2230 */
2231
2232JSONPPolling.prototype.doPoll = function () {
2233 var self = this;
2234 var script = document.createElement('script');
2235
2236 if (this.script) {
2237 this.script.parentNode.removeChild(this.script);
2238 this.script = null;
2239 }
2240
2241 script.async = true;
2242 script.src = this.uri();
2243 script.onerror = function(e){
2244 self.onError('jsonp poll error',e);
2245 }
2246
2247 var insertAt = document.getElementsByTagName('script')[0];
2248 insertAt.parentNode.insertBefore(script, insertAt);
2249 this.script = script;
2250
2251
2252 if (util.ua.gecko) {
2253 setTimeout(function () {
2254 var iframe = document.createElement('iframe');
2255 document.body.appendChild(iframe);
2256 document.body.removeChild(iframe);
2257 }, 100);
2258 }
2259};
2260
2261/**
2262 * Writes with a hidden iframe.
2263 *
2264 * @param {String} data to send
2265 * @param {Function} called upon flush.
2266 * @api private
2267 */
2268
2269JSONPPolling.prototype.doWrite = function (data, fn) {
2270 var self = this;
2271
2272 if (!this.form) {
2273 var form = document.createElement('form');
2274 var area = document.createElement('textarea');
2275 var id = this.iframeId = 'eio_iframe_' + this.index;
2276 var iframe;
2277
2278 form.className = 'socketio';
2279 form.style.position = 'absolute';
2280 form.style.top = '-1000px';
2281 form.style.left = '-1000px';
2282 form.target = id;
2283 form.method = 'POST';
2284 form.setAttribute('accept-charset', 'utf-8');
2285 area.name = 'd';
2286 form.appendChild(area);
2287 document.body.appendChild(form);
2288
2289 this.form = form;
2290 this.area = area;
2291 }
2292
2293 this.form.action = this.uri();
2294
2295 function complete () {
2296 initIframe();
2297 fn();
2298 };
2299
2300 function initIframe () {
2301 if (self.iframe) {
2302 try {
2303 self.form.removeChild(self.iframe);
2304 } catch (e) {
2305 self.onError('jsonp polling iframe removal error', e);
2306 }
2307 }
2308
2309 try {
2310 // ie6 dynamic iframes with target="" support (thanks Chris Lambacher)
2311 var html = '<iframe src="javascript:0" name="'+ self.iframeId +'">';
2312 iframe = document.createElement(html);
2313 } catch (e) {
2314 iframe = document.createElement('iframe');
2315 iframe.name = self.iframeId;
2316 iframe.src = 'javascript:0';
2317 }
2318
2319 iframe.id = self.iframeId;
2320
2321 self.form.appendChild(iframe);
2322 self.iframe = iframe;
2323 };
2324
2325 initIframe();
2326
2327 // escape \n to prevent it from being converted into \r\n by some UAs
2328 this.area.value = data.replace(rNewline, '\\n');
2329
2330 try {
2331 this.form.submit();
2332 } catch(e) {}
2333
2334 if (this.iframe.attachEvent) {
2335 this.iframe.onreadystatechange = function(){
2336 if (self.iframe.readyState == 'complete') {
2337 complete();
2338 }
2339 };
2340 } else {
2341 this.iframe.onload = complete;
2342 }
2343};
2344
2345});
2346require.register("LearnBoost-engine.io-client/lib/transports/websocket.js", function(exports, require, module){
2347
2348/**
2349 * Module dependencies.
2350 */
2351
2352var Transport = require('../transport')
2353 , parser = require('engine.io-parser')
2354 , util = require('../util')
2355 , debug = require('debug')('engine.io-client:websocket');
2356
2357/**
2358 * Module exports.
2359 */
2360
2361module.exports = WS;
2362
2363/**
2364 * Global reference.
2365 */
2366
2367var global = util.global();
2368
2369/**
2370 * WebSocket transport constructor.
2371 *
2372 * @api {Object} connection options
2373 * @api public
2374 */
2375
2376function WS(opts){
2377 Transport.call(this, opts);
2378};
2379
2380/**
2381 * Inherits from Transport.
2382 */
2383
2384util.inherits(WS, Transport);
2385
2386/**
2387 * Transport name.
2388 *
2389 * @api public
2390 */
2391
2392WS.prototype.name = 'websocket';
2393
2394/**
2395 * Opens socket.
2396 *
2397 * @api private
2398 */
2399
2400WS.prototype.doOpen = function(){
2401 if (!this.check()) {
2402 // let probe timeout
2403 return;
2404 }
2405
2406 var self = this;
2407
2408 this.socket = new (ws())(this.uri());
2409 this.socket.onopen = function(){
2410 self.onOpen();
2411 };
2412 this.socket.onclose = function(){
2413 self.onClose();
2414 };
2415 this.socket.onmessage = function(ev){
2416 self.onData(ev.data);
2417 };
2418 this.socket.onerror = function(e){
2419 self.onError('websocket error', e);
2420 };
2421};
2422
2423/**
2424 * Writes data to socket.
2425 *
2426 * @param {Array} array of packets.
2427 * @api private
2428 */
2429
2430WS.prototype.write = function(packets){
2431 for (var i = 0, l = packets.length; i < l; i++) {
2432 this.socket.send(parser.encodePacket(packets[i]));
2433 }
2434};
2435
2436/**
2437 * Closes socket.
2438 *
2439 * @api private
2440 */
2441
2442WS.prototype.doClose = function(){
2443 if (typeof this.socket !== 'undefined') {
2444 this.socket.close();
2445 }
2446};
2447
2448/**
2449 * Generates uri for connection.
2450 *
2451 * @api private
2452 */
2453
2454WS.prototype.uri = function(){
2455 var query = this.query || {};
2456 var schema = this.secure ? 'wss' : 'ws';
2457 var port = '';
2458
2459 // avoid port if default for schema
2460 if (this.port && (('wss' == schema && this.port != 443)
2461 || ('ws' == schema && this.port != 80))) {
2462 port = ':' + this.port;
2463 }
2464
2465 // append timestamp to URI
2466 if (this.timestampRequests) {
2467 query[this.timestampParam] = +new Date;
2468 }
2469
2470 query = util.qs(query);
2471
2472 // prepend ? to query
2473 if (query.length) {
2474 query = '?' + query;
2475 }
2476
2477 return schema + '://' + this.hostname + port + this.path + query;
2478};
2479
2480/**
2481 * Feature detection for WebSocket.
2482 *
2483 * @return {Boolean} whether this transport is available.
2484 * @api public
2485 */
2486
2487WS.prototype.check = function(){
2488 var websocket = ws();
2489 return !!websocket && !('__initialize' in websocket && this.name === WS.prototype.name);
2490};
2491
2492/**
2493 * Getter for WS constructor.
2494 *
2495 * @api private
2496 */
2497
2498function ws(){
2499 if ('undefined' == typeof window) {
2500 return require('ws');
2501 }
2502
2503 return global.WebSocket || global.MozWebSocket;
2504}
2505
2506});
2507require.register("LearnBoost-engine.io-client/lib/transports/flashsocket.js", function(exports, require, module){
2508/**
2509 * Module dependencies.
2510 */
2511
2512var WS = require('./websocket')
2513 , util = require('../util')
2514 , debug = require('debug')('engine.io-client:flashsocket');
2515
2516/**
2517 * Module exports.
2518 */
2519
2520module.exports = FlashWS;
2521
2522/**
2523 * Global reference.
2524 */
2525
2526var global = util.global()
2527
2528/**
2529 * Obfuscated key for Blue Coat.
2530 */
2531
2532var xobject = global[['Active'].concat('Object').join('X')];
2533
2534/**
2535 * FlashWS constructor.
2536 *
2537 * @api public
2538 */
2539
2540function FlashWS (options) {
2541 WS.call(this, options);
2542 this.flashPath = options.flashPath;
2543 this.policyPort = options.policyPort;
2544};
2545
2546/**
2547 * Inherits from WebSocket.
2548 */
2549
2550util.inherits(FlashWS, WS);
2551
2552/**
2553 * Transport name.
2554 *
2555 * @api public
2556 */
2557
2558FlashWS.prototype.name = 'flashsocket';
2559
2560/**
2561 * Opens the transport.
2562 *
2563 * @api public
2564 */
2565
2566FlashWS.prototype.doOpen = function () {
2567 if (!this.check()) {
2568 // let the probe timeout
2569 return;
2570 }
2571
2572 // instrument websocketjs logging
2573 function log (type) {
2574 return function(){
2575 var str = Array.prototype.join.call(arguments, ' ');
2576 debug('[websocketjs %s] %s', type, str);
2577 };
2578 };
2579
2580 WEB_SOCKET_LOGGER = { log: log('debug'), error: log('error') };
2581 WEB_SOCKET_SUPPRESS_CROSS_DOMAIN_SWF_ERROR = true;
2582 WEB_SOCKET_DISABLE_AUTO_INITIALIZATION = true;
2583
2584 if ('undefined' == typeof WEB_SOCKET_SWF_LOCATION) {
2585 WEB_SOCKET_SWF_LOCATION = this.flashPath + 'WebSocketMainInsecure.swf';
2586 }
2587
2588 // dependencies
2589 var deps = [this.flashPath + 'web_socket.js'];
2590
2591 if ('undefined' == typeof swfobject) {
2592 deps.unshift(this.flashPath + 'swfobject.js');
2593 }
2594
2595 var self = this;
2596
2597 load(deps, function () {
2598 self.ready(function () {
2599 WebSocket.__addTask(function () {
2600 WS.prototype.doOpen.call(self);
2601 });
2602 });
2603 });
2604};
2605
2606/**
2607 * Override to prevent closing uninitialized flashsocket.
2608 *
2609 * @api private
2610 */
2611
2612FlashWS.prototype.doClose = function () {
2613 if (!this.socket) return;
2614 var self = this;
2615 WebSocket.__addTask(function() {
2616 WS.prototype.doClose.call(self);
2617 });
2618};
2619
2620/**
2621 * Writes to the Flash socket.
2622 *
2623 * @api private
2624 */
2625
2626FlashWS.prototype.write = function() {
2627 var self = this, args = arguments;
2628 WebSocket.__addTask(function () {
2629 WS.prototype.write.apply(self, args);
2630 });
2631};
2632
2633/**
2634 * Called upon dependencies are loaded.
2635 *
2636 * @api private
2637 */
2638
2639FlashWS.prototype.ready = function (fn) {
2640 if (typeof WebSocket == 'undefined' ||
2641 !('__initialize' in WebSocket) || !swfobject) {
2642 return;
2643 }
2644
2645 if (swfobject.getFlashPlayerVersion().major < 10) {
2646 return;
2647 }
2648
2649 function init () {
2650 // Only start downloading the swf file when the checked that this browser
2651 // actually supports it
2652 if (!FlashWS.loaded) {
2653 if (843 != self.policyPort) {
2654 WebSocket.loadFlashPolicyFile('xmlsocket://' + self.host + ':' + self.policyPort);
2655 }
2656
2657 WebSocket.__initialize();
2658 FlashWS.loaded = true;
2659 }
2660
2661 fn.call(self);
2662 }
2663
2664 var self = this;
2665 if (document.body) {
2666 return init();
2667 }
2668
2669 util.load(init);
2670};
2671
2672/**
2673 * Feature detection for flashsocket.
2674 *
2675 * @return {Boolean} whether this transport is available.
2676 * @api public
2677 */
2678
2679FlashWS.prototype.check = function () {
2680 if ('undefined' == typeof window) {
2681 return false;
2682 }
2683
2684 if (typeof WebSocket != 'undefined' && !('__initialize' in WebSocket)) {
2685 return false;
2686 }
2687
2688 if (xobject) {
2689 var control = null;
2690 try {
2691 control = new xobject('ShockwaveFlash.ShockwaveFlash');
2692 } catch (e) { }
2693 if (control) {
2694 return true;
2695 }
2696 } else {
2697 for (var i = 0, l = navigator.plugins.length; i < l; i++) {
2698 for (var j = 0, m = navigator.plugins[i].length; j < m; j++) {
2699 if (navigator.plugins[i][j].description == 'Shockwave Flash') {
2700 return true;
2701 }
2702 }
2703 }
2704 }
2705
2706 return false;
2707};
2708
2709/**
2710 * Lazy loading of scripts.
2711 * Based on $script by Dustin Diaz - MIT
2712 */
2713
2714var scripts = {};
2715
2716/**
2717 * Injects a script. Keeps tracked of injected ones.
2718 *
2719 * @param {String} path
2720 * @param {Function} callback
2721 * @api private
2722 */
2723
2724function create (path, fn) {
2725 if (scripts[path]) return fn();
2726
2727 var el = document.createElement('script');
2728 var loaded = false;
2729
2730 debug('loading "%s"', path);
2731 el.onload = el.onreadystatechange = function () {
2732 if (loaded || scripts[path]) return;
2733 var rs = el.readyState;
2734 if (!rs || 'loaded' == rs || 'complete' == rs) {
2735 debug('loaded "%s"', path);
2736 el.onload = el.onreadystatechange = null;
2737 loaded = true;
2738 scripts[path] = true;
2739 fn();
2740 }
2741 };
2742
2743 el.async = 1;
2744 el.src = path;
2745
2746 var head = document.getElementsByTagName('head')[0];
2747 head.insertBefore(el, head.firstChild);
2748};
2749
2750/**
2751 * Loads scripts and fires a callback.
2752 *
2753 * @param {Array} paths
2754 * @param {Function} callback
2755 */
2756
2757function load (arr, fn) {
2758 function process (i) {
2759 if (!arr[i]) return fn();
2760 create(arr[i], function () {
2761 process(++i);
2762 });
2763 };
2764
2765 process(0);
2766};
2767
2768});
2769require.register("wearefractal-protosock/dist/main.js", function(exports, require, module){
2770// Generated by CoffeeScript 1.4.0
2771(function() {
2772 var Client, Server, defaultClient, defaultServer, ps, util;
2773
2774 util = require('./util');
2775
2776 Client = require('./Client');
2777
2778 defaultClient = require('./defaultClient');
2779
2780 ps = {
2781 createClientWrapper: function(plugin) {
2782 return function(opt) {
2783 return ps.createClient(plugin, opt);
2784 };
2785 },
2786 createClient: function(plugin, opt) {
2787 var newPlugin;
2788 newPlugin = util.mergePlugins(defaultClient, plugin);
2789 return new Client(newPlugin, opt);
2790 }
2791 };
2792
2793 if (!(typeof window !== "undefined" && window !== null)) {
2794 Server = require('./Server');
2795 defaultServer = require('./defaultServer');
2796 require("http").globalAgent.maxSockets = 999;
2797 ps.createServer = function(httpServer, plugin, opt) {
2798 var newPlugin;
2799 newPlugin = util.mergePlugins(defaultServer, plugin);
2800 return new Server(httpServer, newPlugin, opt);
2801 };
2802 ps.createServerWrapper = function(plugin) {
2803 return function(httpServer, opt) {
2804 return ps.createServer(httpServer, plugin, opt);
2805 };
2806 };
2807 }
2808
2809 module.exports = ps;
2810
2811}).call(this);
2812
2813});
2814require.register("wearefractal-protosock/dist/Socket.js", function(exports, require, module){
2815// Generated by CoffeeScript 1.4.0
2816(function() {
2817 var sock;
2818
2819 sock = {
2820 write: function(msg) {
2821 var _this = this;
2822 this.parent.outbound(this, msg, function(fmt) {
2823 return _this.send(fmt);
2824 });
2825 return this;
2826 },
2827 disconnect: function(r) {
2828 this.close(r);
2829 return this;
2830 }
2831 };
2832
2833 module.exports = sock;
2834
2835}).call(this);
2836
2837});
2838require.register("wearefractal-protosock/dist/util.js", function(exports, require, module){
2839// Generated by CoffeeScript 1.4.0
2840(function() {
2841 var nu, util,
2842 __hasProp = {}.hasOwnProperty,
2843 __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
2844 __slice = [].slice;
2845
2846 nu = require('./Socket');
2847
2848 util = {
2849 extendSocket: function(Socket) {
2850 return __extends(Socket.prototype, nu);
2851 },
2852 mergePlugins: function() {
2853 var args, k, newPlugin, plugin, v, _i, _len;
2854 args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
2855 newPlugin = {};
2856 for (_i = 0, _len = args.length; _i < _len; _i++) {
2857 plugin = args[_i];
2858 for (k in plugin) {
2859 v = plugin[k];
2860 if (typeof v === 'object' && k !== 'server') {
2861 newPlugin[k] = util.mergePlugins(newPlugin[k], v);
2862 } else {
2863 newPlugin[k] = v;
2864 }
2865 }
2866 }
2867 return newPlugin;
2868 }
2869 };
2870
2871 module.exports = util;
2872
2873}).call(this);
2874
2875});
2876require.register("wearefractal-protosock/dist/defaultClient.js", function(exports, require, module){
2877// Generated by CoffeeScript 1.4.0
2878(function() {
2879 var def;
2880
2881 def = {
2882 options: {},
2883 start: function() {},
2884 inbound: function(socket, msg, done) {
2885 var parsed;
2886 try {
2887 parsed = JSON.parse(msg);
2888 } catch (e) {
2889 this.error(socket, e);
2890 }
2891 done(parsed);
2892 },
2893 outbound: function(socket, msg, done) {
2894 var parsed;
2895 try {
2896 parsed = JSON.stringify(msg);
2897 } catch (e) {
2898 this.error(socket, e);
2899 }
2900 done(parsed);
2901 },
2902 validate: function(socket, msg, done) {
2903 return done(true);
2904 },
2905 invalid: function() {},
2906 connect: function() {},
2907 message: function() {},
2908 error: function() {},
2909 close: function() {}
2910 };
2911
2912 if (typeof window !== "undefined" && window !== null) {
2913 def.options = {
2914 host: window.location.hostname,
2915 port: (window.location.port.length > 0 ? parseInt(window.location.port) : 80),
2916 secure: window.location.protocol === 'https:'
2917 };
2918 if (def.options.secure) {
2919 def.options.port = 443;
2920 }
2921 }
2922
2923 module.exports = def;
2924
2925}).call(this);
2926
2927});
2928require.register("wearefractal-protosock/dist/Client.js", function(exports, require, module){
2929// Generated by CoffeeScript 1.4.0
2930(function() {
2931 var Client, EventEmitter, engineClient, getDelay, util,
2932 __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
2933 __hasProp = {}.hasOwnProperty,
2934 __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
2935
2936 util = require('./util');
2937
2938 if (typeof window !== "undefined" && window !== null) {
2939 engineClient = require('engine.io');
2940 EventEmitter = require('emitter');
2941 } else {
2942 engineClient = require('engine.io-client');
2943 EventEmitter = require('events').EventEmitter;
2944 }
2945
2946 util.extendSocket(engineClient.Socket);
2947
2948 getDelay = function(a) {
2949 if (a > 10) {
2950 return 15000;
2951 } else if (a > 5) {
2952 return 5000;
2953 } else if (a > 3) {
2954 return 1000;
2955 }
2956 return 1000;
2957 };
2958
2959 Client = (function(_super) {
2960
2961 __extends(Client, _super);
2962
2963 function Client(plugin, options) {
2964 var eiopts, k, v, _base, _base1, _base2, _ref, _ref1, _ref2;
2965 if (options == null) {
2966 options = {};
2967 }
2968 this.reconnect = __bind(this.reconnect, this);
2969
2970 this.handleClose = __bind(this.handleClose, this);
2971
2972 this.handleError = __bind(this.handleError, this);
2973
2974 this.handleMessage = __bind(this.handleMessage, this);
2975
2976 this.handleConnection = __bind(this.handleConnection, this);
2977
2978 for (k in plugin) {
2979 v = plugin[k];
2980 this[k] = v;
2981 }
2982 for (k in options) {
2983 v = options[k];
2984 this.options[k] = v;
2985 }
2986 if ((_ref = (_base = this.options).reconnect) == null) {
2987 _base.reconnect = true;
2988 }
2989 if ((_ref1 = (_base1 = this.options).reconnectLimit) == null) {
2990 _base1.reconnectLimit = Infinity;
2991 }
2992 if ((_ref2 = (_base2 = this.options).reconnectTimeout) == null) {
2993 _base2.reconnectTimeout = Infinity;
2994 }
2995 this.isServer = false;
2996 this.isClient = true;
2997 this.isBrowser = typeof window !== "undefined" && window !== null;
2998 eiopts = {
2999 host: this.options.host,
3000 port: this.options.port,
3001 secure: this.options.secure,
3002 path: "/" + this.options.namespace,
3003 resource: this.options.resource,
3004 transports: this.options.transports,
3005 upgrade: this.options.upgrade,
3006 flashPath: this.options.flashPath,
3007 policyPort: this.options.policyPort,
3008 forceJSONP: this.options.forceJSONP,
3009 forceBust: this.options.forceBust,
3010 debug: this.options.debug
3011 };
3012 this.ssocket = new engineClient(eiopts);
3013 this.ssocket.parent = this;
3014 this.ssocket.once('open', this.handleConnection);
3015 this.ssocket.on('error', this.handleError);
3016 this.ssocket.on('message', this.handleMessage);
3017 this.ssocket.on('close', this.handleClose);
3018 this.start();
3019 return;
3020 }
3021
3022 Client.prototype.disconnect = function() {
3023 this.ssocket.disconnect();
3024 return this;
3025 };
3026
3027 Client.prototype.destroy = function() {
3028 this.options.reconnect = false;
3029 this.ssocket.disconnect();
3030 this.emit("destroyed");
3031 return this;
3032 };
3033
3034 Client.prototype.handleConnection = function() {
3035 this.emit('connected');
3036 return this.connect(this.ssocket);
3037 };
3038
3039 Client.prototype.handleMessage = function(msg) {
3040 var _this = this;
3041 this.emit('inbound', this.ssocket, msg);
3042 return this.inbound(this.ssocket, msg, function(formatted) {
3043 return _this.validate(_this.ssocket, formatted, function(valid) {
3044 if (valid) {
3045 _this.emit('message', _this.ssocket, formatted);
3046 return _this.message(_this.ssocket, formatted);
3047 } else {
3048 _this.emit('invalid', _this.ssocket, formatted);
3049 return _this.invalid(_this.ssocket, formatted);
3050 }
3051 });
3052 });
3053 };
3054
3055 Client.prototype.handleError = function(err) {
3056 if (typeof err === 'string') {
3057 err = new Error(err);
3058 }
3059 return this.error(this.ssocket, err);
3060 };
3061
3062 Client.prototype.handleClose = function(reason) {
3063 var _this = this;
3064 if (this.ssocket.reconnecting) {
3065 return;
3066 }
3067 if (this.options.reconnect) {
3068 return this.reconnect(function(err) {
3069 if (err == null) {
3070 return;
3071 }
3072 _this.emit('close', _this.ssocket, reason);
3073 return _this.close(_this.ssocket, reason);
3074 });
3075 } else {
3076 this.emit('close', this.ssocket, reason);
3077 return this.close(this.ssocket, reason);
3078 }
3079 };
3080
3081 Client.prototype.reconnect = function(cb) {
3082 var attempts, connect, done, err, maxAttempts, start, timeout,
3083 _this = this;
3084 if (this.ssocket.reconnecting) {
3085 return cb("Already reconnecting");
3086 }
3087 this.ssocket.reconnecting = true;
3088 if (this.ssocket.readyState === 'open') {
3089 this.ssocket.disconnect();
3090 }
3091 start = Date.now();
3092 maxAttempts = this.options.reconnectLimit;
3093 timeout = this.options.reconnectTimeout;
3094 attempts = 0;
3095 done = function() {
3096 _this.ssocket.reconnecting = false;
3097 _this.emit("reconnected");
3098 return cb();
3099 };
3100 err = function(e) {
3101 _this.ssocket.reconnecting = false;
3102 return cb(e);
3103 };
3104 this.ssocket.once('open', done);
3105 connect = function() {
3106 if (!_this.ssocket.reconnecting) {
3107 return;
3108 }
3109 if (attempts >= maxAttempts) {
3110 return err("Exceeded max attempts");
3111 }
3112 if ((Date.now() - start) > timeout) {
3113 return err("Timeout on reconnect");
3114 }
3115 attempts++;
3116 _this.ssocket.open();
3117 return setTimeout(connect, getDelay(attempts));
3118 };
3119 return setTimeout(connect, getDelay(attempts));
3120 };
3121
3122 return Client;
3123
3124 })(EventEmitter);
3125
3126 module.exports = Client;
3127
3128}).call(this);
3129
3130});
3131require.register("component-emitter/index.js", function(exports, require, module){
3132
3133/**
3134 * Expose `Emitter`.
3135 */
3136
3137module.exports = Emitter;
3138
3139/**
3140 * Initialize a new `Emitter`.
3141 *
3142 * @api public
3143 */
3144
3145function Emitter(obj) {
3146 if (obj) return mixin(obj);
3147};
3148
3149/**
3150 * Mixin the emitter properties.
3151 *
3152 * @param {Object} obj
3153 * @return {Object}
3154 * @api private
3155 */
3156
3157function mixin(obj) {
3158 for (var key in Emitter.prototype) {
3159 obj[key] = Emitter.prototype[key];
3160 }
3161 return obj;
3162}
3163
3164/**
3165 * Listen on the given `event` with `fn`.
3166 *
3167 * @param {String} event
3168 * @param {Function} fn
3169 * @return {Emitter}
3170 * @api public
3171 */
3172
3173Emitter.prototype.on = function(event, fn){
3174 this._callbacks = this._callbacks || {};
3175 (this._callbacks[event] = this._callbacks[event] || [])
3176 .push(fn);
3177 return this;
3178};
3179
3180/**
3181 * Adds an `event` listener that will be invoked a single
3182 * time then automatically removed.
3183 *
3184 * @param {String} event
3185 * @param {Function} fn
3186 * @return {Emitter}
3187 * @api public
3188 */
3189
3190Emitter.prototype.once = function(event, fn){
3191 var self = this;
3192 this._callbacks = this._callbacks || {};
3193
3194 function on() {
3195 self.off(event, on);
3196 fn.apply(this, arguments);
3197 }
3198
3199 fn._off = on;
3200 this.on(event, on);
3201 return this;
3202};
3203
3204/**
3205 * Remove the given callback for `event` or all
3206 * registered callbacks.
3207 *
3208 * @param {String} event
3209 * @param {Function} fn
3210 * @return {Emitter}
3211 * @api public
3212 */
3213
3214Emitter.prototype.off =
3215Emitter.prototype.removeListener =
3216Emitter.prototype.removeAllListeners = function(event, fn){
3217 this._callbacks = this._callbacks || {};
3218
3219 // all
3220 if (0 == arguments.length) {
3221 this._callbacks = {};
3222 return this;
3223 }
3224
3225 // specific event
3226 var callbacks = this._callbacks[event];
3227 if (!callbacks) return this;
3228
3229 // remove all handlers
3230 if (1 == arguments.length) {
3231 delete this._callbacks[event];
3232 return this;
3233 }
3234
3235 // remove specific handler
3236 var i = callbacks.indexOf(fn._off || fn);
3237 if (~i) callbacks.splice(i, 1);
3238 return this;
3239};
3240
3241/**
3242 * Emit `event` with the given args.
3243 *
3244 * @param {String} event
3245 * @param {Mixed} ...
3246 * @return {Emitter}
3247 */
3248
3249Emitter.prototype.emit = function(event){
3250 this._callbacks = this._callbacks || {};
3251 var args = [].slice.call(arguments, 1)
3252 , callbacks = this._callbacks[event];
3253
3254 if (callbacks) {
3255 callbacks = callbacks.slice(0);
3256 for (var i = 0, len = callbacks.length; i < len; ++i) {
3257 callbacks[i].apply(this, args);
3258 }
3259 }
3260
3261 return this;
3262};
3263
3264/**
3265 * Return array of callbacks for `event`.
3266 *
3267 * @param {String} event
3268 * @return {Array}
3269 * @api public
3270 */
3271
3272Emitter.prototype.listeners = function(event){
3273 this._callbacks = this._callbacks || {};
3274 return this._callbacks[event] || [];
3275};
3276
3277/**
3278 * Check if this emitter has `event` handlers.
3279 *
3280 * @param {String} event
3281 * @return {Boolean}
3282 * @api public
3283 */
3284
3285Emitter.prototype.hasListeners = function(event){
3286 return !! this.listeners(event).length;
3287};
3288
3289});
3290require.register("holla/dist/holla.js", function(exports, require, module){
3291// Generated by CoffeeScript 1.6.1
3292(function() {
3293 var Call, ProtoSock, client, holla, shims;
3294
3295 Call = require('./Call');
3296
3297 shims = require('./shims');
3298
3299 ProtoSock = require('protosock');
3300
3301 client = {
3302 options: {
3303 namespace: 'holla',
3304 resource: 'default',
3305 debug: false
3306 },
3307 register: function(name, cb) {
3308 var _this = this;
3309 this.ssocket.write({
3310 type: "register",
3311 args: {
3312 name: name
3313 }
3314 });
3315 return this.once("register", function(worked) {
3316 if (worked) {
3317 _this.user = name;
3318 _this.emit("authorized");
3319 }
3320 _this.authorized = worked;
3321 return typeof cb === "function" ? cb(worked) : void 0;
3322 });
3323 },
3324 call: function(user) {
3325 return new Call(this, user, true);
3326 },
3327 chat: function(user, msg) {
3328 this.ssocket.write({
3329 type: "chat",
3330 to: user,
3331 args: {
3332 message: msg
3333 }
3334 });
3335 return this;
3336 },
3337 ready: function(fn) {
3338 if (this.authorized) {
3339 fn();
3340 } else {
3341 this.once('authorized', fn);
3342 }
3343 return this;
3344 },
3345 validate: function(socket, msg, done) {
3346 if (this.options.debug) {
3347 console.log(msg);
3348 }
3349 if (typeof msg !== 'object') {
3350 return done(false);
3351 }
3352 if (typeof msg.type !== 'string') {
3353 return done(false);
3354 }
3355 if (msg.type === "register") {
3356 if (typeof msg.args !== 'object') {
3357 return done(false);
3358 }
3359 if (typeof msg.args.result !== 'boolean') {
3360 return done(false);
3361 }
3362 } else if (msg.type === "offer") {
3363 if (typeof msg.from !== 'string') {
3364 return done(false);
3365 }
3366 } else if (msg.type === "answer") {
3367 if (typeof msg.args !== 'object') {
3368 return done(false);
3369 }
3370 if (typeof msg.from !== 'string') {
3371 return done(false);
3372 }
3373 if (typeof msg.args.accepted !== 'boolean') {
3374 return done(false);
3375 }
3376 } else if (msg.type === "sdp") {
3377 if (typeof msg.args !== 'object') {
3378 return done(false);
3379 }
3380 if (typeof msg.from !== 'string') {
3381 return done(false);
3382 }
3383 if (!msg.args.sdp) {
3384 return done(false);
3385 }
3386 if (!msg.args.type) {
3387 return done(false);
3388 }
3389 } else if (msg.type === "candidate") {
3390 if (typeof msg.args !== 'object') {
3391 return done(false);
3392 }
3393 if (typeof msg.from !== 'string') {
3394 return done(false);
3395 }
3396 if (typeof msg.args.candidate !== 'object') {
3397 return done(false);
3398 }
3399 } else if (msg.type === "chat") {
3400 if (typeof msg.args !== 'object') {
3401 return done(false);
3402 }
3403 if (typeof msg.from !== 'string') {
3404 return done(false);
3405 }
3406 if (typeof msg.args.message !== 'string') {
3407 return done(false);
3408 }
3409 } else if (msg.type === "hangup") {
3410 if (typeof msg.from !== 'string') {
3411 return done(false);
3412 }
3413 } else if (msg.type === "presence") {
3414 if (typeof msg.args !== 'object') {
3415 return done(false);
3416 }
3417 if (typeof msg.args.name !== 'string') {
3418 return done(false);
3419 }
3420 if (typeof msg.args.online !== 'boolean') {
3421 return done(false);
3422 }
3423 } else {
3424 return done(false);
3425 }
3426 return done(true);
3427 },
3428 error: function(socket, err) {
3429 return this.emit('error', err, socket);
3430 },
3431 message: function(socket, msg) {
3432 var c;
3433 switch (msg.type) {
3434 case "register":
3435 return this.emit("register", msg.args.result);
3436 case "offer":
3437 c = new Call(this, msg.from, false);
3438 return this.emit("call", c);
3439 case "presence":
3440 this.emit("presence", msg.args);
3441 return this.emit("presence." + msg.args.name, msg.args.online);
3442 case "chat":
3443 this.emit("chat", {
3444 from: msg.from,
3445 message: msg.args.message
3446 });
3447 return this.emit("chat." + msg.from, msg.args.message);
3448 case "hangup":
3449 this.emit("hangup", {
3450 from: msg.from
3451 });
3452 return this.emit("hangup." + msg.from);
3453 case "answer":
3454 this.emit("answer", {
3455 from: msg.from,
3456 accepted: msg.args.accepted
3457 });
3458 return this.emit("answer." + msg.from, msg.args.accepted);
3459 case "candidate":
3460 this.emit("candidate", {
3461 from: msg.from,
3462 candidate: msg.args.candidate
3463 });
3464 return this.emit("candidate." + msg.from, msg.args.candidate);
3465 case "sdp":
3466 this.emit("sdp", {
3467 from: msg.from,
3468 sdp: msg.args.sdp,
3469 type: msg.args.type
3470 });
3471 return this.emit("sdp." + msg.from, msg.args);
3472 }
3473 }
3474 };
3475
3476 holla = {
3477 createClient: ProtoSock.createClientWrapper(client),
3478 Call: Call,
3479 supported: shims.supported,
3480 config: shims.PeerConnConfig,
3481 streamToBlob: function(s) {
3482 return shims.URL.createObjectURL(s);
3483 },
3484 pipe: function(stream, el) {
3485 var uri;
3486 uri = holla.streamToBlob(stream);
3487 return shims.attachStream(uri, el);
3488 },
3489 record: shims.recordVideo,
3490 createStream: function(opt, cb) {
3491 var err, succ;
3492 if (shims.getUserMedia == null) {
3493 return cb("Missing getUserMedia");
3494 }
3495 err = cb;
3496 succ = function(s) {
3497 return cb(null, s);
3498 };
3499 shims.getUserMedia(opt, succ, err);
3500 return holla;
3501 },
3502 createFullStream: function(cb) {
3503 return holla.createStream({
3504 video: true,
3505 audio: true
3506 }, cb);
3507 },
3508 createVideoStream: function(cb) {
3509 return holla.createStream({
3510 video: true,
3511 audio: false
3512 }, cb);
3513 },
3514 createAudioStream: function(cb) {
3515 return holla.createStream({
3516 video: false,
3517 audio: true
3518 }, cb);
3519 }
3520 };
3521
3522 module.exports = holla;
3523
3524}).call(this);
3525
3526});
3527require.register("holla/dist/Call.js", function(exports, require, module){
3528// Generated by CoffeeScript 1.6.1
3529(function() {
3530 var Call, EventEmitter, shims,
3531 __hasProp = {}.hasOwnProperty,
3532 __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
3533
3534 shims = require('./shims');
3535
3536 EventEmitter = require('emitter');
3537
3538 Call = (function(_super) {
3539
3540 __extends(Call, _super);
3541
3542 function Call(parent, user, isCaller) {
3543 var _this = this;
3544 this.parent = parent;
3545 this.user = user;
3546 this.isCaller = isCaller;
3547 this.startTime = new Date;
3548 this.socket = this.parent.ssocket;
3549 this.pc = this.createConnection();
3550 if (this.isCaller) {
3551 this.socket.write({
3552 type: "offer",
3553 to: this.user
3554 });
3555 }
3556 this.emit("calling");
3557 this.parent.on("answer." + this.user, function(accepted) {
3558 if (!accepted) {
3559 return _this.emit("rejected");
3560 }
3561 _this.emit("answered");
3562 return _this.initSDP();
3563 });
3564 this.parent.on("candidate." + this.user, function(candidate) {
3565 return _this.pc.addIceCandidate(new shims.IceCandidate(candidate));
3566 });
3567 this.parent.on("sdp." + this.user, function(desc) {
3568 var err, succ;
3569 desc.sdp = shims.processSDPIn(desc.sdp);
3570 err = function(e) {
3571 throw e;
3572 };
3573 succ = function() {
3574 if (!_this.isCaller) {
3575 _this.initSDP();
3576 }
3577 return _this.emit("sdp");
3578 };
3579 return _this.pc.setRemoteDescription(new shims.SessionDescription(desc), succ, err);
3580 });
3581 this.parent.on("hangup." + this.user, function() {
3582 return _this.emit("hangup");
3583 });
3584 this.parent.on("chat." + this.user, function(msg) {
3585 return _this.emit("chat", msg);
3586 });
3587 }
3588
3589 Call.prototype.createConnection = function() {
3590 var pc,
3591 _this = this;
3592 pc = new shims.PeerConnection(shims.PeerConnConfig, shims.constraints);
3593 pc.onconnecting = function() {
3594 _this.emit('connecting');
3595 };
3596 pc.onopen = function() {
3597 _this.emit('connected');
3598 };
3599 pc.onicecandidate = function(evt) {
3600 if (evt.candidate) {
3601 _this.socket.write({
3602 type: "candidate",
3603 to: _this.user,
3604 args: {
3605 candidate: evt.candidate
3606 }
3607 });
3608 }
3609 };
3610 pc.onaddstream = function(evt) {
3611 _this.remoteStream = evt.stream;
3612 _this._ready = true;
3613 _this.emit("ready", _this.remoteStream);
3614 };
3615 pc.onremovestream = function(evt) {
3616 console.log("removestream", evt);
3617 };
3618 return pc;
3619 };
3620
3621 Call.prototype.addStream = function(s) {
3622 this.pc.addStream(s);
3623 return this;
3624 };
3625
3626 Call.prototype.ready = function(fn) {
3627 if (this._ready) {
3628 fn(this.remoteStream);
3629 } else {
3630 this.once('ready', fn);
3631 }
3632 return this;
3633 };
3634
3635 Call.prototype.duration = function() {
3636 var e, s;
3637 if (this.endTime != null) {
3638 s = this.endTime.getTime();
3639 }
3640 if (s == null) {
3641 s = Date.now();
3642 }
3643 e = this.startTime.getTime();
3644 return (s - e) / 1000;
3645 };
3646
3647 Call.prototype.chat = function(msg) {
3648 this.parent.chat(this.user, msg);
3649 return this;
3650 };
3651
3652 Call.prototype.answer = function() {
3653 this.startTime = new Date;
3654 this.socket.write({
3655 type: "answer",
3656 to: this.user,
3657 args: {
3658 accepted: true
3659 }
3660 });
3661 return this;
3662 };
3663
3664 Call.prototype.decline = function() {
3665 this.socket.write({
3666 type: "answer",
3667 to: this.user,
3668 args: {
3669 accepted: false
3670 }
3671 });
3672 return this;
3673 };
3674
3675 Call.prototype.end = function() {
3676 this.endTime = new Date;
3677 try {
3678 this.pc.close();
3679 } catch (_error) {}
3680 this.socket.write({
3681 type: "hangup",
3682 to: this.user
3683 });
3684 this.emit("hangup");
3685 return this;
3686 };
3687
3688 Call.prototype.initSDP = function() {
3689 var done, err,
3690 _this = this;
3691 done = function(desc) {
3692 desc.sdp = shims.processSDPOut(desc.sdp);
3693 _this.pc.setLocalDescription(desc);
3694 return _this.socket.write({
3695 type: "sdp",
3696 to: _this.user,
3697 args: desc
3698 });
3699 };
3700 err = function(e) {
3701 throw e;
3702 };
3703 if (this.isCaller) {
3704 return this.pc.createOffer(done, err, shims.constraints);
3705 }
3706 if (this.pc.remoteDescription) {
3707 return this.pc.createAnswer(done, err, shims.constraints);
3708 }
3709 return this.once("sdp", function() {
3710 return _this.pc.createAnswer(done, err);
3711 });
3712 };
3713
3714 return Call;
3715
3716 })(EventEmitter);
3717
3718 module.exports = Call;
3719
3720}).call(this);
3721
3722});
3723require.register("holla/dist/shims.js", function(exports, require, module){
3724// Generated by CoffeeScript 1.6.1
3725(function() {
3726 var IceCandidate, MediaStream, PeerConnection, SessionDescription, URL, attachStream, browser, extract, getUserMedia, loadBlob, processSDPIn, processSDPOut, recordVideo, removeCN, replaceCodec, saveBlob, shim, supported, useOPUS;
3727
3728 PeerConnection = window.mozRTCPeerConnection || window.PeerConnection || window.webkitPeerConnection00 || window.webkitRTCPeerConnection;
3729
3730 IceCandidate = window.mozRTCIceCandidate || window.RTCIceCandidate;
3731
3732 SessionDescription = window.mozRTCSessionDescription || window.RTCSessionDescription;
3733
3734 MediaStream = window.MediaStream || window.webkitMediaStream;
3735
3736 getUserMedia = navigator.mozGetUserMedia || navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.msGetUserMedia;
3737
3738 URL = window.URL || window.webkitURL || window.msURL || window.oURL;
3739
3740 getUserMedia = getUserMedia.bind(navigator);
3741
3742 browser = (navigator.mozGetUserMedia ? 'firefox' : 'chrome');
3743
3744 supported = (PeerConnection != null) && (getUserMedia != null);
3745
3746 extract = function(str, reg) {
3747 var match;
3748 match = str.match(reg);
3749 return (match != null ? match[1] : null);
3750 };
3751
3752 replaceCodec = function(line, codec) {
3753 var el, els, idx, out, _i, _len;
3754 els = line.split(' ');
3755 out = [];
3756 for (idx = _i = 0, _len = els.length; _i < _len; idx = ++_i) {
3757 el = els[idx];
3758 if (idx === 3) {
3759 out[idx++] = codec;
3760 }
3761 if (el !== codec) {
3762 out[idx++] = el;
3763 }
3764 }
3765 return out.join(' ');
3766 };
3767
3768 removeCN = function(lines, mLineIdx) {
3769 var cnPos, idx, line, mLineEls, payload, _i, _len;
3770 mLineEls = lines[mLineIdx].split(' ');
3771 for (idx = _i = 0, _len = lines.length; _i < _len; idx = ++_i) {
3772 line = lines[idx];
3773 if (!(line != null)) {
3774 continue;
3775 }
3776 payload = extract(line, /a=rtpmap:(\d+) CN\/\d+/i);
3777 if (payload != null) {
3778 cnPos = mLineEls.indexOf(payload);
3779 if (cnPos !== -1) {
3780 mLineEls.splice(cnPos, 1);
3781 }
3782 lines.splice(idx, 1);
3783 }
3784 }
3785 lines[mLineIdx] = mLineEls.join(' ');
3786 return lines;
3787 };
3788
3789 useOPUS = function(sdp) {
3790 var idx, line, lines, mLineIdx, payload, _i, _len;
3791 lines = sdp.split('\r\n');
3792 mLineIdx = ((function() {
3793 var _i, _len, _results;
3794 _results = [];
3795 for (idx = _i = 0, _len = lines.length; _i < _len; idx = ++_i) {
3796 line = lines[idx];
3797 if (line.indexOf('m=audio') !== -1) {
3798 _results.push(idx);
3799 }
3800 }
3801 return _results;
3802 })())[0];
3803 if (mLineIdx == null) {
3804 return sdp;
3805 }
3806 for (idx = _i = 0, _len = lines.length; _i < _len; idx = ++_i) {
3807 line = lines[idx];
3808 if (!(line.indexOf('opus/48000') !== -1)) {
3809 continue;
3810 }
3811 payload = extract(line, /:(\d+) opus\/48000/i);
3812 if (payload != null) {
3813 lines[mLineIdx] = replaceCodec(lines[mLineIdx], payload);
3814 }
3815 break;
3816 }
3817 lines = removeCN(lines, mLineIdx);
3818 return lines.join('\r\n');
3819 };
3820
3821 processSDPOut = function(sdp) {
3822 var addCrypto, line, out, _i, _j, _len, _len1, _ref, _ref1;
3823 out = [];
3824 if (browser === 'firefox') {
3825 addCrypto = "a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:BAADBAADBAADBAADBAADBAADBAADBAADBAADBAAD";
3826 _ref = sdp.split('\r\n');
3827 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
3828 line = _ref[_i];
3829 out.push(line);
3830 if (line.indexOf('m=') === 0) {
3831 out.push(addCrypto);
3832 }
3833 }
3834 } else {
3835 _ref1 = sdp.split('\r\n');
3836 for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
3837 line = _ref1[_j];
3838 if (line.indexOf("a=ice-options:google-ice") === -1) {
3839 out.push(line);
3840 }
3841 }
3842 }
3843 return useOPUS(out.join('\r\n'));
3844 };
3845
3846 processSDPIn = function(sdp) {
3847 return sdp;
3848 };
3849
3850 attachStream = function(uri, el) {
3851 var e, _i, _len;
3852 if (typeof el === "string") {
3853 return attachStream(uri, document.getElementById(el));
3854 } else if (el.jquery) {
3855 el.attr('src', uri);
3856 for (_i = 0, _len = el.length; _i < _len; _i++) {
3857 e = el[_i];
3858 e.play();
3859 }
3860 } else {
3861 el.src = uri;
3862 el.play();
3863 }
3864 return el;
3865 };
3866
3867 saveBlob = function(file, blob) {
3868 var evt, link;
3869 link = document.createElement("a");
3870 link.href = blob;
3871 link.target = "_blank";
3872 link.download = file;
3873 evt = document.createEvent("Event");
3874 evt.initEvent("click", true, true);
3875 link.dispatchEvent(evt);
3876 URL.revokeObjectURL(link.href);
3877 };
3878
3879 loadBlob = function(blob, cb) {
3880 var reader;
3881 reader = new FileReader;
3882 reader.readAsDataURL(blob);
3883 return reader.onload = function(event) {
3884 return cb(event.target.result);
3885 };
3886 };
3887
3888 recordVideo = function(el) {
3889 var can, ctrl, ctx, end, frames, getBlob, grab, h, requested, save, w;
3890 if (el.jquery) {
3891 h = el.height();
3892 w = el.width();
3893 el = el[0];
3894 } else {
3895 h = el.height;
3896 w = el.width;
3897 }
3898 can = document.createElement('canvas');
3899 ctx = can.getContext('2d');
3900 can.width = w;
3901 can.height = h;
3902 frames = [];
3903 grab = function() {
3904 var requested;
3905 requested = requestAnimationFrame(grab);
3906 ctx.drawImage(el, 0, 0, w, h);
3907 frames.push(can.toDataURL('image/webp', 1));
3908 };
3909 getBlob = function(cb) {
3910 var blob;
3911 blob = Whammy.fromImageArray(frames, 1000 / 60);
3912 loadBlob(blob, cb);
3913 return ctrl;
3914 };
3915 save = function(file) {
3916 if (file == null) {
3917 file = "recording.webp";
3918 }
3919 getBlob(function(blob) {
3920 return saveBlob(file, blob);
3921 });
3922 return ctrl;
3923 };
3924 end = function(cb) {
3925 cancelAnimationFrame(requested);
3926 return ctrl;
3927 };
3928 requested = requestAnimationFrame(grab);
3929 ctrl = {
3930 save: save,
3931 getBlob: getBlob,
3932 end: end
3933 };
3934 return ctrl;
3935 };
3936
3937 shim = function() {
3938 var PeerConnConfig, mediaConstraints, out;
3939 if (!supported) {
3940 return;
3941 }
3942 if (browser === 'firefox') {
3943 PeerConnConfig = {
3944 iceServers: [
3945 {
3946 url: "stun:23.21.150.121"
3947 }
3948 ]
3949 };
3950 mediaConstraints = {
3951 mandatory: {
3952 OfferToReceiveAudio: true,
3953 OfferToReceiveVideo: true,
3954 MozDontOfferDataChannel: true
3955 }
3956 };
3957 MediaStream.prototype.getVideoTracks = function() {
3958 return [];
3959 };
3960 MediaStream.prototype.getAudioTracks = function() {
3961 return [];
3962 };
3963 } else {
3964 PeerConnConfig = {
3965 iceServers: [
3966 {
3967 url: "stun:stun.l.google.com:19302"
3968 }
3969 ]
3970 };
3971 mediaConstraints = {
3972 mandatory: {
3973 OfferToReceiveAudio: true,
3974 OfferToReceiveVideo: true
3975 },
3976 optional: [
3977 {
3978 DtlsSrtpKeyAgreement: true
3979 }
3980 ]
3981 };
3982 if (!MediaStream.prototype.getVideoTracks) {
3983 MediaStream.prototype.getVideoTracks = function() {
3984 return this.videoTracks;
3985 };
3986 MediaStream.prototype.getAudioTracks = function() {
3987 return this.audioTracks;
3988 };
3989 }
3990 if (!PeerConnection.prototype.getLocalStreams) {
3991 PeerConnection.prototype.getLocalStreams = function() {
3992 return this.localStreams;
3993 };
3994 PeerConnection.prototype.getRemoteStreams = function() {
3995 return this.remoteStreams;
3996 };
3997 }
3998 }
3999 out = {
4000 PeerConnection: PeerConnection,
4001 IceCandidate: IceCandidate,
4002 SessionDescription: SessionDescription,
4003 MediaStream: MediaStream,
4004 getUserMedia: getUserMedia,
4005 URL: URL,
4006 attachStream: attachStream,
4007 processSDPIn: processSDPIn,
4008 processSDPOut: processSDPOut,
4009 PeerConnConfig: PeerConnConfig,
4010 browser: browser,
4011 supported: supported,
4012 constraints: mediaConstraints,
4013 recordVideo: recordVideo,
4014 loadBlob: loadBlob,
4015 saveBlob: saveBlob
4016 };
4017 return out;
4018 };
4019
4020
4021(function() {
4022 var lastTime = 0;
4023 var vendors = ['ms', 'moz', 'webkit', 'o'];
4024 for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
4025 window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
4026 window.cancelAnimationFrame =
4027 window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
4028 }
4029
4030 if (!window.requestAnimationFrame)
4031 window.requestAnimationFrame = function(callback, element) {
4032 var currTime = new Date().getTime();
4033 var timeToCall = Math.max(0, 16 - (currTime - lastTime));
4034 var id = window.setTimeout(function() { callback(currTime + timeToCall); },
4035 timeToCall);
4036 lastTime = currTime + timeToCall;
4037 return id;
4038 };
4039
4040 if (!window.cancelAnimationFrame)
4041 window.cancelAnimationFrame = function(id) {
4042 clearTimeout(id);
4043 };
4044}());
4045/* https://github.com/antimatter15/whammy */
4046var Whammy=function(){function g(a){for(var b=a[0].width,e=a[0].height,c=a[0].duration,d=1;d<a.length;d++){if(a[d].width!=b)throw"Frame "+(d+1)+" has a different width";if(a[d].height!=e)throw"Frame "+(d+1)+" has a different height";if(0>a[d].duration)throw"Frame "+(d+1)+" has a weird duration";c+=a[d].duration}var f=0,a=[{id:440786851,data:[{data:1,id:17030},{data:1,id:17143},{data:4,id:17138},{data:8,id:17139},{data:"webm",id:17026},{data:2,id:17031},{data:2,id:17029}]},{id:408125543,data:[{id:357149030,
4047data:[{data:1E6,id:2807729},{data:"whammy",id:19840},{data:"whammy",id:22337},{data:[].slice.call(new Uint8Array((new Float64Array([c])).buffer),0).map(function(a){return String.fromCharCode(a)}).reverse().join(""),id:17545}]},{id:374648427,data:[{id:174,data:[{data:1,id:215},{data:1,id:25541},{data:0,id:156},{data:"und",id:2274716},{data:"V_VP8",id:134},{data:"VP8",id:2459272},{data:1,id:131},{id:224,data:[{data:b,id:176},{data:e,id:186}]}]}]},{id:524531317,data:[{data:0,id:231}].concat(a.map(function(a){var b;
4048b=a.data.slice(4);var c=Math.round(f);b=[129,c>>8,c&255,128].map(function(a){return String.fromCharCode(a)}).join("")+b;f+=a.duration;return{data:b,id:163}}))}]}];return j(a)}function m(a){for(var b=[];0<a;)b.push(a&255),a>>=8;return new Uint8Array(b.reverse())}function k(a){for(var b=[],a=(a.length%8?Array(9-a.length%8).join("0"):"")+a,e=0;e<a.length;e+=8)b.push(parseInt(a.substr(e,8),2));return new Uint8Array(b)}function j(a){for(var b=[],e=0;e<a.length;e++){var c=a[e].data;"object"==typeof c&&
4049(c=j(c));"number"==typeof c&&(c=k(c.toString(2)));if("string"==typeof c){for(var d=new Uint8Array(c.length),f=0;f<c.length;f++)d[f]=c.charCodeAt(f);c=d}f=c.size||c.byteLength;d=Math.ceil(Math.ceil(Math.log(f)/Math.log(2))/8);f=f.toString(2);f=Array(7*d+8-f.length).join("0")+f;d=Array(d).join("0")+"1"+f;b.push(m(a[e].id));b.push(k(d));b.push(c)}return new Blob(b,{type:"video/webm"})}function l(a){for(var b=a.RIFF[0].WEBP[0],e=b.indexOf("\u009d\u0001*"),c=0,d=[];4>c;c++)d[c]=b.charCodeAt(e+3+c);c=d[1]<<
40508|d[0];e=c&16383;c=d[3]<<8|d[2];return{width:e,height:c&16383,data:b,riff:a}}function h(a){for(var b=0,e={};b<a.length;){var c=a.substr(b,4),d=parseInt(a.substr(b+4,4).split("").map(function(a){a=a.charCodeAt(0).toString(2);return Array(8-a.length+1).join("0")+a}).join(""),2),f=a.substr(b+4+4,d),b=b+(8+d);e[c]=e[c]||[];"RIFF"==c||"LIST"==c?e[c].push(h(f)):e[c].push(f)}return e}function i(a,b){this.frames=[];this.duration=1E3/a;this.quality=b||0.8}i.prototype.add=function(a,b){if("undefined"!=typeof b&&
4051this.duration)throw"you can't pass a duration if the fps is set";if("undefined"==typeof b&&!this.duration)throw"if you don't have the fps set, you ned to have durations here.";a.canvas&&(a=a.canvas);if(a.toDataURL)a=a.toDataURL("image/webp",this.quality);else if("string"!=typeof a)throw"frame must be a a HTMLCanvasElement, a CanvasRenderingContext2D or a DataURI formatted string";if(!/^data:image\/webp;base64,/ig.test(a))throw"Input must be formatted properly as a base64 encoded DataURI of type image/webp";
4052this.frames.push({image:a,duration:b||this.duration})};i.prototype.compile=function(){return new g(this.frames.map(function(a){var b=l(h(atob(a.image.slice(23))));b.duration=a.duration;return b}))};return{Video:i,fromImageArray:function(a,b){return g(a.map(function(a){a=l(h(atob(a.slice(23))));a.duration=1E3/b;return a}))},toWebM:g}}();
4053;
4054
4055 module.exports = shim();
4056
4057}).call(this);
4058
4059});
4060require.alias("wearefractal-protosock/dist/main.js", "holla/deps/protosock/dist/main.js");
4061require.alias("wearefractal-protosock/dist/Socket.js", "holla/deps/protosock/dist/Socket.js");
4062require.alias("wearefractal-protosock/dist/util.js", "holla/deps/protosock/dist/util.js");
4063require.alias("wearefractal-protosock/dist/defaultClient.js", "holla/deps/protosock/dist/defaultClient.js");
4064require.alias("wearefractal-protosock/dist/Client.js", "holla/deps/protosock/dist/Client.js");
4065require.alias("wearefractal-protosock/dist/main.js", "holla/deps/protosock/index.js");
4066require.alias("component-emitter/index.js", "wearefractal-protosock/deps/emitter/index.js");
4067
4068require.alias("LearnBoost-engine.io-client/lib/index.js", "wearefractal-protosock/deps/engine.io/lib/index.js");
4069require.alias("LearnBoost-engine.io-client/lib/socket.js", "wearefractal-protosock/deps/engine.io/lib/socket.js");
4070require.alias("LearnBoost-engine.io-client/lib/transport.js", "wearefractal-protosock/deps/engine.io/lib/transport.js");
4071require.alias("LearnBoost-engine.io-client/lib/emitter.js", "wearefractal-protosock/deps/engine.io/lib/emitter.js");
4072require.alias("LearnBoost-engine.io-client/lib/util.js", "wearefractal-protosock/deps/engine.io/lib/util.js");
4073require.alias("LearnBoost-engine.io-client/lib/transports/index.js", "wearefractal-protosock/deps/engine.io/lib/transports/index.js");
4074require.alias("LearnBoost-engine.io-client/lib/transports/polling.js", "wearefractal-protosock/deps/engine.io/lib/transports/polling.js");
4075require.alias("LearnBoost-engine.io-client/lib/transports/polling-xhr.js", "wearefractal-protosock/deps/engine.io/lib/transports/polling-xhr.js");
4076require.alias("LearnBoost-engine.io-client/lib/transports/polling-jsonp.js", "wearefractal-protosock/deps/engine.io/lib/transports/polling-jsonp.js");
4077require.alias("LearnBoost-engine.io-client/lib/transports/websocket.js", "wearefractal-protosock/deps/engine.io/lib/transports/websocket.js");
4078require.alias("LearnBoost-engine.io-client/lib/transports/flashsocket.js", "wearefractal-protosock/deps/engine.io/lib/transports/flashsocket.js");
4079require.alias("LearnBoost-engine.io-client/lib/index.js", "wearefractal-protosock/deps/engine.io/index.js");
4080require.alias("component-emitter/index.js", "LearnBoost-engine.io-client/deps/emitter/index.js");
4081
4082require.alias("LearnBoost-engine.io-protocol/lib/index.js", "LearnBoost-engine.io-client/deps/engine.io-parser/lib/index.js");
4083require.alias("LearnBoost-engine.io-protocol/lib/keys.js", "LearnBoost-engine.io-client/deps/engine.io-parser/lib/keys.js");
4084require.alias("LearnBoost-engine.io-protocol/lib/index.js", "LearnBoost-engine.io-client/deps/engine.io-parser/index.js");
4085require.alias("LearnBoost-engine.io-protocol/lib/index.js", "LearnBoost-engine.io-protocol/index.js");
4086
4087require.alias("visionmedia-debug/index.js", "LearnBoost-engine.io-client/deps/debug/index.js");
4088require.alias("visionmedia-debug/debug.js", "LearnBoost-engine.io-client/deps/debug/debug.js");
4089
4090require.alias("LearnBoost-engine.io-client/lib/index.js", "LearnBoost-engine.io-client/index.js");
4091
4092require.alias("wearefractal-protosock/dist/main.js", "wearefractal-protosock/index.js");
4093
4094require.alias("component-emitter/index.js", "holla/deps/emitter/index.js");
4095
4096require.alias("holla/dist/holla.js", "holla/index.js");
4097
4098if (typeof exports == "object") {
4099 module.exports = require("holla");
4100} else if (typeof define == "function" && define.amd) {
4101 define(function(){ return require("holla"); });
4102} else {
4103 window["holla"] = require("holla");
4104}})();
\No newline at end of file