rhet-butler 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/bin/rhet-butler +5 -0
  2. data/default-configuration/assets/apple-touch-icon-precomposed.png +0 -0
  3. data/default-configuration/assets/apple-touch-icon.png +0 -0
  4. data/default-configuration/assets/favicon.ico +0 -0
  5. data/default-configuration/assets/fonts/opensans/v6/MTP_ySUJH_bn48VBG8sNSonF5uFdDttMLvmWuJdhhgs.ttf +0 -0
  6. data/default-configuration/assets/fonts/opensans/v6/PRmiXeptR36kaC0GEAetxi8cqLH4MEiSE0ROcU-qHOA.ttf +0 -0
  7. data/default-configuration/assets/fonts/opensans/v6/cJZKeOuBrn4kERxqtaUH3aCWcynf_cDxXwCLxiixG1c.ttf +0 -0
  8. data/default-configuration/assets/fonts/opensans/v6/xjAJXh38I15wypJXxuGMBp0EAVxt0G0biEntp43Qt6E.ttf +0 -0
  9. data/default-configuration/assets/fonts/ptsans/v5/0XxGQsSc1g4rdRdjJKZrNC3USBnSvpkopQaUR-2r7iU.ttf +0 -0
  10. data/default-configuration/assets/fonts/ptsans/v5/FUDHvzEKSJww3kCxuiAo2A.ttf +0 -0
  11. data/default-configuration/assets/fonts/ptsans/v5/PIPMHY90P7jtyjpXuZ2cLKCWcynf_cDxXwCLxiixG1c.ttf +0 -0
  12. data/default-configuration/assets/fonts/ptsans/v5/lILlYDvubYemzYzN7GbLkInF5uFdDttMLvmWuJdhhgs.ttf +0 -0
  13. data/default-configuration/assets/fonts/ptserif/v5/03aPdn7fFF3H6ngCgAlQzC3USBnSvpkopQaUR-2r7iU.ttf +0 -0
  14. data/default-configuration/assets/fonts/ptserif/v5/EgBlzoNBIHxNPCMwXaAhYPesZW2xOQ-xsNqO47m55DA.ttf +0 -0
  15. data/default-configuration/assets/fonts/ptserif/v5/Foydq9xJp--nfYIx2TBz9fEr6Hm6RMS0v1dtXsGir4g.ttf +0 -0
  16. data/default-configuration/assets/fonts/ptserif/v5/QABk9IxT-LFTJ_dQzv7xpJ0EAVxt0G0biEntp43Qt6E.ttf +0 -0
  17. data/default-configuration/assets/javascript/highlight.js/LICENSE +24 -0
  18. data/default-configuration/assets/javascript/highlight.js/README.md +143 -0
  19. data/default-configuration/assets/javascript/highlight.js/README.ru.md +149 -0
  20. data/default-configuration/assets/javascript/highlight.js/classref.txt +568 -0
  21. data/default-configuration/assets/javascript/highlight.pack.js +1 -0
  22. data/default-configuration/assets/javascript/impress.js +800 -0
  23. data/default-configuration/assets/javascript/sockjs-0.2.1.js +2014 -0
  24. data/default-configuration/assets/javascript/sockjs-0.3.js +2314 -0
  25. data/default-configuration/assets/rhet-butler.jpg +0 -0
  26. data/default-configuration/assets/stylesheets/google-open-sans.css +72 -0
  27. data/default-configuration/assets/stylesheets/highlight/solarized_dark.css +88 -0
  28. data/default-configuration/assets/stylesheets/presentation.css +483 -0
  29. data/default-configuration/assets/stylesheets/presenter/presentation.css +477 -0
  30. data/default-configuration/assets/stylesheets/setup.css +0 -0
  31. data/default-configuration/common/config.yaml +4 -0
  32. data/default-configuration/common/templates/header-javascript.html +3 -0
  33. data/default-configuration/common/templates/presentation.html.erb +44 -0
  34. data/default-configuration/common/templates/presenter-qr.html.erb +77 -0
  35. data/default-configuration/common/templates/stylesheets.html.erb +3 -0
  36. data/default-configuration/presenter/config.yaml +7 -0
  37. data/default-configuration/presenter/templates/live-javascript.html.erb +26 -0
  38. data/default-configuration/presenter/templates/slide-notes.html.erb +3 -0
  39. data/default-configuration/presenter/templates/stylesheets.html.erb +3 -0
  40. data/default-configuration/viewer/config.yaml +7 -0
  41. data/default-configuration/viewer/templates/live-javascript.html.erb +16 -0
  42. data/default-configuration/viewer/templates/slide-notes.html.erb +0 -0
  43. data/lib/rhet-butler/arrangement.rb +78 -0
  44. data/lib/rhet-butler/command-line.rb +49 -0
  45. data/lib/rhet-butler/configuration.rb +76 -0
  46. data/lib/rhet-butler/file-manager.rb +126 -0
  47. data/lib/rhet-butler/html-generator.rb +29 -0
  48. data/lib/rhet-butler/layout-rule.rb +57 -0
  49. data/lib/rhet-butler/messaging.rb +58 -0
  50. data/lib/rhet-butler/slide-group.rb +56 -0
  51. data/lib/rhet-butler/slide-includer.rb +34 -0
  52. data/lib/rhet-butler/slide-loader.rb +361 -0
  53. data/lib/rhet-butler/slide.rb +164 -0
  54. data/lib/rhet-butler/static-generator.rb +44 -0
  55. data/lib/rhet-butler/web/assets-app.rb +40 -0
  56. data/lib/rhet-butler/web/main-app.rb +139 -0
  57. data/lib/rhet-butler/web/presentation-app.rb +50 -0
  58. data/lib/rhet-butler/web/qr-display-app.rb +37 -0
  59. data/lib/rhet-butler/yaml-schema.rb +9 -0
  60. data/lib/rhet-butler/yaml-type.rb +23 -0
  61. data/lib/rhet-butler.rb +2 -0
  62. data/spec/arrangements.rb +76 -0
  63. data/spec/html-generation.rb +48 -0
  64. data/spec/presentation-view.rb +72 -0
  65. data/spec/rhet-butler.rb +59 -0
  66. data/spec/slide-loader.rb +51 -0
  67. data/spec/slide-processing.rb +73 -0
  68. data/spec_support/gem_test_suite.rb +17 -0
  69. metadata +324 -0
@@ -0,0 +1,2314 @@
1
+ /* SockJS client, version 0.3.2, http://sockjs.org, MIT License
2
+
3
+ Copyright (c) 2011-2012 VMware, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
22
+ */
23
+
24
+ // JSON2 by Douglas Crockford (minified).
25
+ var JSON;JSON||(JSON={}),function(){function str(a,b){var c,d,e,f,g=gap,h,i=b[a];i&&typeof i=="object"&&typeof i.toJSON=="function"&&(i=i.toJSON(a)),typeof rep=="function"&&(i=rep.call(b,a,i));switch(typeof i){case"string":return quote(i);case"number":return isFinite(i)?String(i):"null";case"boolean":case"null":return String(i);case"object":if(!i)return"null";gap+=indent,h=[];if(Object.prototype.toString.apply(i)==="[object Array]"){f=i.length;for(c=0;c<f;c+=1)h[c]=str(c,i)||"null";e=h.length===0?"[]":gap?"[\n"+gap+h.join(",\n"+gap)+"\n"+g+"]":"["+h.join(",")+"]",gap=g;return e}if(rep&&typeof rep=="object"){f=rep.length;for(c=0;c<f;c+=1)typeof rep[c]=="string"&&(d=rep[c],e=str(d,i),e&&h.push(quote(d)+(gap?": ":":")+e))}else for(d in i)Object.prototype.hasOwnProperty.call(i,d)&&(e=str(d,i),e&&h.push(quote(d)+(gap?": ":":")+e));e=h.length===0?"{}":gap?"{\n"+gap+h.join(",\n"+gap)+"\n"+g+"}":"{"+h.join(",")+"}",gap=g;return e}}function quote(a){escapable.lastIndex=0;return escapable.test(a)?'"'+a.replace(escapable,function(a){var b=meta[a];return typeof b=="string"?b:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+a+'"'}function f(a){return a<10?"0"+a:a}"use strict",typeof Date.prototype.toJSON!="function"&&(Date.prototype.toJSON=function(a){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null},String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(a){return this.valueOf()});var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;typeof JSON.stringify!="function"&&(JSON.stringify=function(a,b,c){var d;gap="",indent="";if(typeof c=="number")for(d=0;d<c;d+=1)indent+=" ";else typeof c=="string"&&(indent=c);rep=b;if(!b||typeof b=="function"||typeof b=="object"&&typeof b.length=="number")return str("",{"":a});throw new Error("JSON.stringify")}),typeof JSON.parse!="function"&&(JSON.parse=function(text,reviver){function walk(a,b){var c,d,e=a[b];if(e&&typeof e=="object")for(c in e)Object.prototype.hasOwnProperty.call(e,c)&&(d=walk(e,c),d!==undefined?e[c]=d:delete e[c]);return reviver.call(a,b,e)}var j;text=String(text),cx.lastIndex=0,cx.test(text)&&(text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)}));if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof reviver=="function"?walk({"":j},""):j}throw new SyntaxError("JSON.parse")})}()
26
+
27
+
28
+ // [*] Including lib/index.js
29
+ // Public object
30
+ SockJS = (function(){
31
+ var _document = document;
32
+ var _window = window;
33
+ var utils = {};
34
+
35
+
36
+ // [*] Including lib/reventtarget.js
37
+ /*
38
+ * ***** BEGIN LICENSE BLOCK *****
39
+ * Copyright (c) 2011-2012 VMware, Inc.
40
+ *
41
+ * For the license see COPYING.
42
+ * ***** END LICENSE BLOCK *****
43
+ */
44
+
45
+ /* Simplified implementation of DOM2 EventTarget.
46
+ * http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventTarget
47
+ */
48
+ var REventTarget = function() {};
49
+ REventTarget.prototype.addEventListener = function (eventType, listener) {
50
+ if(!this._listeners) {
51
+ this._listeners = {};
52
+ }
53
+ if(!(eventType in this._listeners)) {
54
+ this._listeners[eventType] = [];
55
+ }
56
+ var arr = this._listeners[eventType];
57
+ if(utils.arrIndexOf(arr, listener) === -1) {
58
+ arr.push(listener);
59
+ }
60
+ return;
61
+ };
62
+
63
+ REventTarget.prototype.removeEventListener = function (eventType, listener) {
64
+ if(!(this._listeners && (eventType in this._listeners))) {
65
+ return;
66
+ }
67
+ var arr = this._listeners[eventType];
68
+ var idx = utils.arrIndexOf(arr, listener);
69
+ if (idx !== -1) {
70
+ if(arr.length > 1) {
71
+ this._listeners[eventType] = arr.slice(0, idx).concat( arr.slice(idx+1) );
72
+ } else {
73
+ delete this._listeners[eventType];
74
+ }
75
+ return;
76
+ }
77
+ return;
78
+ };
79
+
80
+ REventTarget.prototype.dispatchEvent = function (event) {
81
+ var t = event.type;
82
+ var args = Array.prototype.slice.call(arguments, 0);
83
+ if (this['on'+t]) {
84
+ this['on'+t].apply(this, args);
85
+ }
86
+ if (this._listeners && t in this._listeners) {
87
+ for(var i=0; i < this._listeners[t].length; i++) {
88
+ this._listeners[t][i].apply(this, args);
89
+ }
90
+ }
91
+ };
92
+ // [*] End of lib/reventtarget.js
93
+
94
+
95
+ // [*] Including lib/simpleevent.js
96
+ /*
97
+ * ***** BEGIN LICENSE BLOCK *****
98
+ * Copyright (c) 2011-2012 VMware, Inc.
99
+ *
100
+ * For the license see COPYING.
101
+ * ***** END LICENSE BLOCK *****
102
+ */
103
+
104
+ var SimpleEvent = function(type, obj) {
105
+ this.type = type;
106
+ if (typeof obj !== 'undefined') {
107
+ for(var k in obj) {
108
+ if (!obj.hasOwnProperty(k)) continue;
109
+ this[k] = obj[k];
110
+ }
111
+ }
112
+ };
113
+
114
+ SimpleEvent.prototype.toString = function() {
115
+ var r = [];
116
+ for(var k in this) {
117
+ if (!this.hasOwnProperty(k)) continue;
118
+ var v = this[k];
119
+ if (typeof v === 'function') v = '[function]';
120
+ r.push(k + '=' + v);
121
+ }
122
+ return 'SimpleEvent(' + r.join(', ') + ')';
123
+ };
124
+ // [*] End of lib/simpleevent.js
125
+
126
+
127
+ // [*] Including lib/eventemitter.js
128
+ /*
129
+ * ***** BEGIN LICENSE BLOCK *****
130
+ * Copyright (c) 2011-2012 VMware, Inc.
131
+ *
132
+ * For the license see COPYING.
133
+ * ***** END LICENSE BLOCK *****
134
+ */
135
+
136
+ var EventEmitter = function(events) {
137
+ this.events = events || [];
138
+ };
139
+ EventEmitter.prototype.emit = function(type) {
140
+ var that = this;
141
+ var args = Array.prototype.slice.call(arguments, 1);
142
+ if (!that.nuked && that['on'+type]) {
143
+ that['on'+type].apply(that, args);
144
+ }
145
+ if (utils.arrIndexOf(that.events, type) === -1) {
146
+ utils.log('Event ' + JSON.stringify(type) +
147
+ ' not listed ' + JSON.stringify(that.events) +
148
+ ' in ' + that);
149
+ }
150
+ };
151
+
152
+ EventEmitter.prototype.nuke = function(type) {
153
+ var that = this;
154
+ that.nuked = true;
155
+ for(var i=0; i<that.events.length; i++) {
156
+ delete that[that.events[i]];
157
+ }
158
+ };
159
+ // [*] End of lib/eventemitter.js
160
+
161
+
162
+ // [*] Including lib/utils.js
163
+ /*
164
+ * ***** BEGIN LICENSE BLOCK *****
165
+ * Copyright (c) 2011-2012 VMware, Inc.
166
+ *
167
+ * For the license see COPYING.
168
+ * ***** END LICENSE BLOCK *****
169
+ */
170
+
171
+ var random_string_chars = 'abcdefghijklmnopqrstuvwxyz0123456789_';
172
+ utils.random_string = function(length, max) {
173
+ max = max || random_string_chars.length;
174
+ var i, ret = [];
175
+ for(i=0; i < length; i++) {
176
+ ret.push( random_string_chars.substr(Math.floor(Math.random() * max),1) );
177
+ }
178
+ return ret.join('');
179
+ };
180
+ utils.random_number = function(max) {
181
+ return Math.floor(Math.random() * max);
182
+ };
183
+ utils.random_number_string = function(max) {
184
+ var t = (''+(max - 1)).length;
185
+ var p = Array(t+1).join('0');
186
+ return (p + utils.random_number(max)).slice(-t);
187
+ };
188
+
189
+ // Assuming that url looks like: http://asdasd:111/asd
190
+ utils.getOrigin = function(url) {
191
+ url += '/';
192
+ var parts = url.split('/').slice(0, 3);
193
+ return parts.join('/');
194
+ };
195
+
196
+ utils.isSameOriginUrl = function(url_a, url_b) {
197
+ // location.origin would do, but it's not always available.
198
+ if (!url_b) url_b = _window.location.href;
199
+
200
+ return (url_a.split('/').slice(0,3).join('/')
201
+ ===
202
+ url_b.split('/').slice(0,3).join('/'));
203
+ };
204
+
205
+ utils.getParentDomain = function(url) {
206
+ // ipv4 ip address
207
+ if (/^[0-9.]*$/.test(url)) return url;
208
+ // ipv6 ip address
209
+ if (/^\[/.test(url)) return url;
210
+ // no dots
211
+ if (!(/[.]/.test(url))) return url;
212
+
213
+ var parts = url.split('.').slice(1);
214
+ return parts.join('.');
215
+ };
216
+
217
+ utils.objectExtend = function(dst, src) {
218
+ for(var k in src) {
219
+ if (src.hasOwnProperty(k)) {
220
+ dst[k] = src[k];
221
+ }
222
+ }
223
+ return dst;
224
+ };
225
+
226
+ var WPrefix = '_jp';
227
+
228
+ utils.polluteGlobalNamespace = function() {
229
+ if (!(WPrefix in _window)) {
230
+ _window[WPrefix] = {};
231
+ }
232
+ };
233
+
234
+ utils.closeFrame = function (code, reason) {
235
+ return 'c'+JSON.stringify([code, reason]);
236
+ };
237
+
238
+ utils.userSetCode = function (code) {
239
+ return code === 1000 || (code >= 3000 && code <= 4999);
240
+ };
241
+
242
+ // See: http://www.erg.abdn.ac.uk/~gerrit/dccp/notes/ccid2/rto_estimator/
243
+ // and RFC 2988.
244
+ utils.countRTO = function (rtt) {
245
+ var rto;
246
+ if (rtt > 100) {
247
+ rto = 3 * rtt; // rto > 300msec
248
+ } else {
249
+ rto = rtt + 200; // 200msec < rto <= 300msec
250
+ }
251
+ return rto;
252
+ }
253
+
254
+ utils.log = function() {
255
+ if (_window.console && console.log && console.log.apply) {
256
+ console.log.apply(console, arguments);
257
+ }
258
+ };
259
+
260
+ utils.bind = function(fun, that) {
261
+ if (fun.bind) {
262
+ return fun.bind(that);
263
+ } else {
264
+ return function() {
265
+ return fun.apply(that, arguments);
266
+ };
267
+ }
268
+ };
269
+
270
+ utils.flatUrl = function(url) {
271
+ return url.indexOf('?') === -1 && url.indexOf('#') === -1;
272
+ };
273
+
274
+ utils.amendUrl = function(url) {
275
+ var dl = _document.location;
276
+ if (!url) {
277
+ throw new Error('Wrong url for SockJS');
278
+ }
279
+ if (!utils.flatUrl(url)) {
280
+ throw new Error('Only basic urls are supported in SockJS');
281
+ }
282
+
283
+ // '//abc' --> 'http://abc'
284
+ if (url.indexOf('//') === 0) {
285
+ url = dl.protocol + url;
286
+ }
287
+ // '/abc' --> 'http://localhost:80/abc'
288
+ if (url.indexOf('/') === 0) {
289
+ url = dl.protocol + '//' + dl.host + url;
290
+ }
291
+ // strip trailing slashes
292
+ url = url.replace(/[/]+$/,'');
293
+ return url;
294
+ };
295
+
296
+ // IE doesn't support [].indexOf.
297
+ utils.arrIndexOf = function(arr, obj){
298
+ for(var i=0; i < arr.length; i++){
299
+ if(arr[i] === obj){
300
+ return i;
301
+ }
302
+ }
303
+ return -1;
304
+ };
305
+
306
+ utils.arrSkip = function(arr, obj) {
307
+ var idx = utils.arrIndexOf(arr, obj);
308
+ if (idx === -1) {
309
+ return arr.slice();
310
+ } else {
311
+ var dst = arr.slice(0, idx);
312
+ return dst.concat(arr.slice(idx+1));
313
+ }
314
+ };
315
+
316
+ // Via: https://gist.github.com/1133122/2121c601c5549155483f50be3da5305e83b8c5df
317
+ utils.isArray = Array.isArray || function(value) {
318
+ return {}.toString.call(value).indexOf('Array') >= 0
319
+ };
320
+
321
+ utils.delay = function(t, fun) {
322
+ if(typeof t === 'function') {
323
+ fun = t;
324
+ t = 0;
325
+ }
326
+ return setTimeout(fun, t);
327
+ };
328
+
329
+
330
+ // Chars worth escaping, as defined by Douglas Crockford:
331
+ // https://github.com/douglascrockford/JSON-js/blob/47a9882cddeb1e8529e07af9736218075372b8ac/json2.js#L196
332
+ var json_escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
333
+ json_lookup = {
334
+ "\u0000":"\\u0000","\u0001":"\\u0001","\u0002":"\\u0002","\u0003":"\\u0003",
335
+ "\u0004":"\\u0004","\u0005":"\\u0005","\u0006":"\\u0006","\u0007":"\\u0007",
336
+ "\b":"\\b","\t":"\\t","\n":"\\n","\u000b":"\\u000b","\f":"\\f","\r":"\\r",
337
+ "\u000e":"\\u000e","\u000f":"\\u000f","\u0010":"\\u0010","\u0011":"\\u0011",
338
+ "\u0012":"\\u0012","\u0013":"\\u0013","\u0014":"\\u0014","\u0015":"\\u0015",
339
+ "\u0016":"\\u0016","\u0017":"\\u0017","\u0018":"\\u0018","\u0019":"\\u0019",
340
+ "\u001a":"\\u001a","\u001b":"\\u001b","\u001c":"\\u001c","\u001d":"\\u001d",
341
+ "\u001e":"\\u001e","\u001f":"\\u001f","\"":"\\\"","\\":"\\\\",
342
+ "\u007f":"\\u007f","\u0080":"\\u0080","\u0081":"\\u0081","\u0082":"\\u0082",
343
+ "\u0083":"\\u0083","\u0084":"\\u0084","\u0085":"\\u0085","\u0086":"\\u0086",
344
+ "\u0087":"\\u0087","\u0088":"\\u0088","\u0089":"\\u0089","\u008a":"\\u008a",
345
+ "\u008b":"\\u008b","\u008c":"\\u008c","\u008d":"\\u008d","\u008e":"\\u008e",
346
+ "\u008f":"\\u008f","\u0090":"\\u0090","\u0091":"\\u0091","\u0092":"\\u0092",
347
+ "\u0093":"\\u0093","\u0094":"\\u0094","\u0095":"\\u0095","\u0096":"\\u0096",
348
+ "\u0097":"\\u0097","\u0098":"\\u0098","\u0099":"\\u0099","\u009a":"\\u009a",
349
+ "\u009b":"\\u009b","\u009c":"\\u009c","\u009d":"\\u009d","\u009e":"\\u009e",
350
+ "\u009f":"\\u009f","\u00ad":"\\u00ad","\u0600":"\\u0600","\u0601":"\\u0601",
351
+ "\u0602":"\\u0602","\u0603":"\\u0603","\u0604":"\\u0604","\u070f":"\\u070f",
352
+ "\u17b4":"\\u17b4","\u17b5":"\\u17b5","\u200c":"\\u200c","\u200d":"\\u200d",
353
+ "\u200e":"\\u200e","\u200f":"\\u200f","\u2028":"\\u2028","\u2029":"\\u2029",
354
+ "\u202a":"\\u202a","\u202b":"\\u202b","\u202c":"\\u202c","\u202d":"\\u202d",
355
+ "\u202e":"\\u202e","\u202f":"\\u202f","\u2060":"\\u2060","\u2061":"\\u2061",
356
+ "\u2062":"\\u2062","\u2063":"\\u2063","\u2064":"\\u2064","\u2065":"\\u2065",
357
+ "\u2066":"\\u2066","\u2067":"\\u2067","\u2068":"\\u2068","\u2069":"\\u2069",
358
+ "\u206a":"\\u206a","\u206b":"\\u206b","\u206c":"\\u206c","\u206d":"\\u206d",
359
+ "\u206e":"\\u206e","\u206f":"\\u206f","\ufeff":"\\ufeff","\ufff0":"\\ufff0",
360
+ "\ufff1":"\\ufff1","\ufff2":"\\ufff2","\ufff3":"\\ufff3","\ufff4":"\\ufff4",
361
+ "\ufff5":"\\ufff5","\ufff6":"\\ufff6","\ufff7":"\\ufff7","\ufff8":"\\ufff8",
362
+ "\ufff9":"\\ufff9","\ufffa":"\\ufffa","\ufffb":"\\ufffb","\ufffc":"\\ufffc",
363
+ "\ufffd":"\\ufffd","\ufffe":"\\ufffe","\uffff":"\\uffff"};
364
+
365
+ // Some extra characters that Chrome gets wrong, and substitutes with
366
+ // something else on the wire.
367
+ var extra_escapable = /[\x00-\x1f\ud800-\udfff\ufffe\uffff\u0300-\u0333\u033d-\u0346\u034a-\u034c\u0350-\u0352\u0357-\u0358\u035c-\u0362\u0374\u037e\u0387\u0591-\u05af\u05c4\u0610-\u0617\u0653-\u0654\u0657-\u065b\u065d-\u065e\u06df-\u06e2\u06eb-\u06ec\u0730\u0732-\u0733\u0735-\u0736\u073a\u073d\u073f-\u0741\u0743\u0745\u0747\u07eb-\u07f1\u0951\u0958-\u095f\u09dc-\u09dd\u09df\u0a33\u0a36\u0a59-\u0a5b\u0a5e\u0b5c-\u0b5d\u0e38-\u0e39\u0f43\u0f4d\u0f52\u0f57\u0f5c\u0f69\u0f72-\u0f76\u0f78\u0f80-\u0f83\u0f93\u0f9d\u0fa2\u0fa7\u0fac\u0fb9\u1939-\u193a\u1a17\u1b6b\u1cda-\u1cdb\u1dc0-\u1dcf\u1dfc\u1dfe\u1f71\u1f73\u1f75\u1f77\u1f79\u1f7b\u1f7d\u1fbb\u1fbe\u1fc9\u1fcb\u1fd3\u1fdb\u1fe3\u1feb\u1fee-\u1fef\u1ff9\u1ffb\u1ffd\u2000-\u2001\u20d0-\u20d1\u20d4-\u20d7\u20e7-\u20e9\u2126\u212a-\u212b\u2329-\u232a\u2adc\u302b-\u302c\uaab2-\uaab3\uf900-\ufa0d\ufa10\ufa12\ufa15-\ufa1e\ufa20\ufa22\ufa25-\ufa26\ufa2a-\ufa2d\ufa30-\ufa6d\ufa70-\ufad9\ufb1d\ufb1f\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufb4e\ufff0-\uffff]/g,
368
+ extra_lookup;
369
+
370
+ // JSON Quote string. Use native implementation when possible.
371
+ var JSONQuote = (JSON && JSON.stringify) || function(string) {
372
+ json_escapable.lastIndex = 0;
373
+ if (json_escapable.test(string)) {
374
+ string = string.replace(json_escapable, function(a) {
375
+ return json_lookup[a];
376
+ });
377
+ }
378
+ return '"' + string + '"';
379
+ };
380
+
381
+ // This may be quite slow, so let's delay until user actually uses bad
382
+ // characters.
383
+ var unroll_lookup = function(escapable) {
384
+ var i;
385
+ var unrolled = {}
386
+ var c = []
387
+ for(i=0; i<65536; i++) {
388
+ c.push( String.fromCharCode(i) );
389
+ }
390
+ escapable.lastIndex = 0;
391
+ c.join('').replace(escapable, function (a) {
392
+ unrolled[ a ] = '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
393
+ return '';
394
+ });
395
+ escapable.lastIndex = 0;
396
+ return unrolled;
397
+ };
398
+
399
+ // Quote string, also taking care of unicode characters that browsers
400
+ // often break. Especially, take care of unicode surrogates:
401
+ // http://en.wikipedia.org/wiki/Mapping_of_Unicode_characters#Surrogates
402
+ utils.quote = function(string) {
403
+ var quoted = JSONQuote(string);
404
+
405
+ // In most cases this should be very fast and good enough.
406
+ extra_escapable.lastIndex = 0;
407
+ if(!extra_escapable.test(quoted)) {
408
+ return quoted;
409
+ }
410
+
411
+ if(!extra_lookup) extra_lookup = unroll_lookup(extra_escapable);
412
+
413
+ return quoted.replace(extra_escapable, function(a) {
414
+ return extra_lookup[a];
415
+ });
416
+ }
417
+
418
+ var _all_protocols = ['websocket',
419
+ 'xdr-streaming',
420
+ 'xhr-streaming',
421
+ 'iframe-eventsource',
422
+ 'iframe-htmlfile',
423
+ 'xdr-polling',
424
+ 'xhr-polling',
425
+ 'iframe-xhr-polling',
426
+ 'jsonp-polling'];
427
+
428
+ utils.probeProtocols = function() {
429
+ var probed = {};
430
+ for(var i=0; i<_all_protocols.length; i++) {
431
+ var protocol = _all_protocols[i];
432
+ // User can have a typo in protocol name.
433
+ probed[protocol] = SockJS[protocol] &&
434
+ SockJS[protocol].enabled();
435
+ }
436
+ return probed;
437
+ };
438
+
439
+ utils.detectProtocols = function(probed, protocols_whitelist, info) {
440
+ var pe = {},
441
+ protocols = [];
442
+ if (!protocols_whitelist) protocols_whitelist = _all_protocols;
443
+ for(var i=0; i<protocols_whitelist.length; i++) {
444
+ var protocol = protocols_whitelist[i];
445
+ pe[protocol] = probed[protocol];
446
+ }
447
+ var maybe_push = function(protos) {
448
+ var proto = protos.shift();
449
+ if (pe[proto]) {
450
+ protocols.push(proto);
451
+ } else {
452
+ if (protos.length > 0) {
453
+ maybe_push(protos);
454
+ }
455
+ }
456
+ }
457
+
458
+ // 1. Websocket
459
+ if (info.websocket !== false) {
460
+ maybe_push(['websocket']);
461
+ }
462
+
463
+ // 2. Streaming
464
+ if (pe['xhr-streaming'] && !info.null_origin) {
465
+ protocols.push('xhr-streaming');
466
+ } else {
467
+ if (pe['xdr-streaming'] && !info.cookie_needed && !info.null_origin) {
468
+ protocols.push('xdr-streaming');
469
+ } else {
470
+ maybe_push(['iframe-eventsource',
471
+ 'iframe-htmlfile']);
472
+ }
473
+ }
474
+
475
+ // 3. Polling
476
+ if (pe['xhr-polling'] && !info.null_origin) {
477
+ protocols.push('xhr-polling');
478
+ } else {
479
+ if (pe['xdr-polling'] && !info.cookie_needed && !info.null_origin) {
480
+ protocols.push('xdr-polling');
481
+ } else {
482
+ maybe_push(['iframe-xhr-polling',
483
+ 'jsonp-polling']);
484
+ }
485
+ }
486
+ return protocols;
487
+ }
488
+ // [*] End of lib/utils.js
489
+
490
+
491
+ // [*] Including lib/dom.js
492
+ /*
493
+ * ***** BEGIN LICENSE BLOCK *****
494
+ * Copyright (c) 2011-2012 VMware, Inc.
495
+ *
496
+ * For the license see COPYING.
497
+ * ***** END LICENSE BLOCK *****
498
+ */
499
+
500
+ // May be used by htmlfile jsonp and transports.
501
+ var MPrefix = '_sockjs_global';
502
+ utils.createHook = function() {
503
+ var window_id = 'a' + utils.random_string(8);
504
+ if (!(MPrefix in _window)) {
505
+ var map = {};
506
+ _window[MPrefix] = function(window_id) {
507
+ if (!(window_id in map)) {
508
+ map[window_id] = {
509
+ id: window_id,
510
+ del: function() {delete map[window_id];}
511
+ };
512
+ }
513
+ return map[window_id];
514
+ }
515
+ }
516
+ return _window[MPrefix](window_id);
517
+ };
518
+
519
+
520
+
521
+ utils.attachMessage = function(listener) {
522
+ utils.attachEvent('message', listener);
523
+ };
524
+ utils.attachEvent = function(event, listener) {
525
+ if (typeof _window.addEventListener !== 'undefined') {
526
+ _window.addEventListener(event, listener, false);
527
+ } else {
528
+ // IE quirks.
529
+ // According to: http://stevesouders.com/misc/test-postmessage.php
530
+ // the message gets delivered only to 'document', not 'window'.
531
+ _document.attachEvent("on" + event, listener);
532
+ // I get 'window' for ie8.
533
+ _window.attachEvent("on" + event, listener);
534
+ }
535
+ };
536
+
537
+ utils.detachMessage = function(listener) {
538
+ utils.detachEvent('message', listener);
539
+ };
540
+ utils.detachEvent = function(event, listener) {
541
+ if (typeof _window.addEventListener !== 'undefined') {
542
+ _window.removeEventListener(event, listener, false);
543
+ } else {
544
+ _document.detachEvent("on" + event, listener);
545
+ _window.detachEvent("on" + event, listener);
546
+ }
547
+ };
548
+
549
+
550
+ var on_unload = {};
551
+ // Things registered after beforeunload are to be called immediately.
552
+ var after_unload = false;
553
+
554
+ var trigger_unload_callbacks = function() {
555
+ for(var ref in on_unload) {
556
+ on_unload[ref]();
557
+ delete on_unload[ref];
558
+ };
559
+ };
560
+
561
+ var unload_triggered = function() {
562
+ if(after_unload) return;
563
+ after_unload = true;
564
+ trigger_unload_callbacks();
565
+ };
566
+
567
+ // Onbeforeunload alone is not reliable. We could use only 'unload'
568
+ // but it's not working in opera within an iframe. Let's use both.
569
+ utils.attachEvent('beforeunload', unload_triggered);
570
+ utils.attachEvent('unload', unload_triggered);
571
+
572
+ utils.unload_add = function(listener) {
573
+ var ref = utils.random_string(8);
574
+ on_unload[ref] = listener;
575
+ if (after_unload) {
576
+ utils.delay(trigger_unload_callbacks);
577
+ }
578
+ return ref;
579
+ };
580
+ utils.unload_del = function(ref) {
581
+ if (ref in on_unload)
582
+ delete on_unload[ref];
583
+ };
584
+
585
+
586
+ utils.createIframe = function (iframe_url, error_callback) {
587
+ var iframe = _document.createElement('iframe');
588
+ var tref, unload_ref;
589
+ var unattach = function() {
590
+ clearTimeout(tref);
591
+ // Explorer had problems with that.
592
+ try {iframe.onload = null;} catch (x) {}
593
+ iframe.onerror = null;
594
+ };
595
+ var cleanup = function() {
596
+ if (iframe) {
597
+ unattach();
598
+ // This timeout makes chrome fire onbeforeunload event
599
+ // within iframe. Without the timeout it goes straight to
600
+ // onunload.
601
+ setTimeout(function() {
602
+ if(iframe) {
603
+ iframe.parentNode.removeChild(iframe);
604
+ }
605
+ iframe = null;
606
+ }, 0);
607
+ utils.unload_del(unload_ref);
608
+ }
609
+ };
610
+ var onerror = function(r) {
611
+ if (iframe) {
612
+ cleanup();
613
+ error_callback(r);
614
+ }
615
+ };
616
+ var post = function(msg, origin) {
617
+ try {
618
+ // When the iframe is not loaded, IE raises an exception
619
+ // on 'contentWindow'.
620
+ if (iframe && iframe.contentWindow) {
621
+ iframe.contentWindow.postMessage(msg, origin);
622
+ }
623
+ } catch (x) {};
624
+ };
625
+
626
+ iframe.src = iframe_url;
627
+ iframe.style.display = 'none';
628
+ iframe.style.position = 'absolute';
629
+ iframe.onerror = function(){onerror('onerror');};
630
+ iframe.onload = function() {
631
+ // `onload` is triggered before scripts on the iframe are
632
+ // executed. Give it few seconds to actually load stuff.
633
+ clearTimeout(tref);
634
+ tref = setTimeout(function(){onerror('onload timeout');}, 2000);
635
+ };
636
+ _document.body.appendChild(iframe);
637
+ tref = setTimeout(function(){onerror('timeout');}, 15000);
638
+ unload_ref = utils.unload_add(cleanup);
639
+ return {
640
+ post: post,
641
+ cleanup: cleanup,
642
+ loaded: unattach
643
+ };
644
+ };
645
+
646
+ utils.createHtmlfile = function (iframe_url, error_callback) {
647
+ var doc = new ActiveXObject('htmlfile');
648
+ var tref, unload_ref;
649
+ var iframe;
650
+ var unattach = function() {
651
+ clearTimeout(tref);
652
+ };
653
+ var cleanup = function() {
654
+ if (doc) {
655
+ unattach();
656
+ utils.unload_del(unload_ref);
657
+ iframe.parentNode.removeChild(iframe);
658
+ iframe = doc = null;
659
+ CollectGarbage();
660
+ }
661
+ };
662
+ var onerror = function(r) {
663
+ if (doc) {
664
+ cleanup();
665
+ error_callback(r);
666
+ }
667
+ };
668
+ var post = function(msg, origin) {
669
+ try {
670
+ // When the iframe is not loaded, IE raises an exception
671
+ // on 'contentWindow'.
672
+ if (iframe && iframe.contentWindow) {
673
+ iframe.contentWindow.postMessage(msg, origin);
674
+ }
675
+ } catch (x) {};
676
+ };
677
+
678
+ doc.open();
679
+ doc.write('<html><s' + 'cript>' +
680
+ 'document.domain="' + document.domain + '";' +
681
+ '</s' + 'cript></html>');
682
+ doc.close();
683
+ doc.parentWindow[WPrefix] = _window[WPrefix];
684
+ var c = doc.createElement('div');
685
+ doc.body.appendChild(c);
686
+ iframe = doc.createElement('iframe');
687
+ c.appendChild(iframe);
688
+ iframe.src = iframe_url;
689
+ tref = setTimeout(function(){onerror('timeout');}, 15000);
690
+ unload_ref = utils.unload_add(cleanup);
691
+ return {
692
+ post: post,
693
+ cleanup: cleanup,
694
+ loaded: unattach
695
+ };
696
+ };
697
+ // [*] End of lib/dom.js
698
+
699
+
700
+ // [*] Including lib/dom2.js
701
+ /*
702
+ * ***** BEGIN LICENSE BLOCK *****
703
+ * Copyright (c) 2011-2012 VMware, Inc.
704
+ *
705
+ * For the license see COPYING.
706
+ * ***** END LICENSE BLOCK *****
707
+ */
708
+
709
+ var AbstractXHRObject = function(){};
710
+ AbstractXHRObject.prototype = new EventEmitter(['chunk', 'finish']);
711
+
712
+ AbstractXHRObject.prototype._start = function(method, url, payload, opts) {
713
+ var that = this;
714
+
715
+ try {
716
+ that.xhr = new XMLHttpRequest();
717
+ } catch(x) {};
718
+
719
+ if (!that.xhr) {
720
+ try {
721
+ that.xhr = new _window.ActiveXObject('Microsoft.XMLHTTP');
722
+ } catch(x) {};
723
+ }
724
+ if (_window.ActiveXObject || _window.XDomainRequest) {
725
+ // IE8 caches even POSTs
726
+ url += ((url.indexOf('?') === -1) ? '?' : '&') + 't='+(+new Date);
727
+ }
728
+
729
+ // Explorer tends to keep connection open, even after the
730
+ // tab gets closed: http://bugs.jquery.com/ticket/5280
731
+ that.unload_ref = utils.unload_add(function(){that._cleanup(true);});
732
+ try {
733
+ that.xhr.open(method, url, true);
734
+ } catch(e) {
735
+ // IE raises an exception on wrong port.
736
+ that.emit('finish', 0, '');
737
+ that._cleanup();
738
+ return;
739
+ };
740
+
741
+ if (!opts || !opts.no_credentials) {
742
+ // Mozilla docs says https://developer.mozilla.org/en/XMLHttpRequest :
743
+ // "This never affects same-site requests."
744
+ that.xhr.withCredentials = 'true';
745
+ }
746
+ if (opts && opts.headers) {
747
+ for(var key in opts.headers) {
748
+ that.xhr.setRequestHeader(key, opts.headers[key]);
749
+ }
750
+ }
751
+
752
+ that.xhr.onreadystatechange = function() {
753
+ if (that.xhr) {
754
+ var x = that.xhr;
755
+ switch (x.readyState) {
756
+ case 3:
757
+ // IE doesn't like peeking into responseText or status
758
+ // on Microsoft.XMLHTTP and readystate=3
759
+ try {
760
+ var status = x.status;
761
+ var text = x.responseText;
762
+ } catch (x) {};
763
+ // IE does return readystate == 3 for 404 answers.
764
+ if (text && text.length > 0) {
765
+ that.emit('chunk', status, text);
766
+ }
767
+ break;
768
+ case 4:
769
+ that.emit('finish', x.status, x.responseText);
770
+ that._cleanup(false);
771
+ break;
772
+ }
773
+ }
774
+ };
775
+ that.xhr.send(payload);
776
+ };
777
+
778
+ AbstractXHRObject.prototype._cleanup = function(abort) {
779
+ var that = this;
780
+ if (!that.xhr) return;
781
+ utils.unload_del(that.unload_ref);
782
+
783
+ // IE needs this field to be a function
784
+ that.xhr.onreadystatechange = function(){};
785
+
786
+ if (abort) {
787
+ try {
788
+ that.xhr.abort();
789
+ } catch(x) {};
790
+ }
791
+ that.unload_ref = that.xhr = null;
792
+ };
793
+
794
+ AbstractXHRObject.prototype.close = function() {
795
+ var that = this;
796
+ that.nuke();
797
+ that._cleanup(true);
798
+ };
799
+
800
+ var XHRCorsObject = utils.XHRCorsObject = function() {
801
+ var that = this, args = arguments;
802
+ utils.delay(function(){that._start.apply(that, args);});
803
+ };
804
+ XHRCorsObject.prototype = new AbstractXHRObject();
805
+
806
+ var XHRLocalObject = utils.XHRLocalObject = function(method, url, payload) {
807
+ var that = this;
808
+ utils.delay(function(){
809
+ that._start(method, url, payload, {
810
+ no_credentials: true
811
+ });
812
+ });
813
+ };
814
+ XHRLocalObject.prototype = new AbstractXHRObject();
815
+
816
+
817
+
818
+ // References:
819
+ // http://ajaxian.com/archives/100-line-ajax-wrapper
820
+ // http://msdn.microsoft.com/en-us/library/cc288060(v=VS.85).aspx
821
+ var XDRObject = utils.XDRObject = function(method, url, payload) {
822
+ var that = this;
823
+ utils.delay(function(){that._start(method, url, payload);});
824
+ };
825
+ XDRObject.prototype = new EventEmitter(['chunk', 'finish']);
826
+ XDRObject.prototype._start = function(method, url, payload) {
827
+ var that = this;
828
+ var xdr = new XDomainRequest();
829
+ // IE caches even POSTs
830
+ url += ((url.indexOf('?') === -1) ? '?' : '&') + 't='+(+new Date);
831
+
832
+ var onerror = xdr.ontimeout = xdr.onerror = function() {
833
+ that.emit('finish', 0, '');
834
+ that._cleanup(false);
835
+ };
836
+ xdr.onprogress = function() {
837
+ that.emit('chunk', 200, xdr.responseText);
838
+ };
839
+ xdr.onload = function() {
840
+ that.emit('finish', 200, xdr.responseText);
841
+ that._cleanup(false);
842
+ };
843
+ that.xdr = xdr;
844
+ that.unload_ref = utils.unload_add(function(){that._cleanup(true);});
845
+ try {
846
+ // Fails with AccessDenied if port number is bogus
847
+ that.xdr.open(method, url);
848
+ that.xdr.send(payload);
849
+ } catch(x) {
850
+ onerror();
851
+ }
852
+ };
853
+
854
+ XDRObject.prototype._cleanup = function(abort) {
855
+ var that = this;
856
+ if (!that.xdr) return;
857
+ utils.unload_del(that.unload_ref);
858
+
859
+ that.xdr.ontimeout = that.xdr.onerror = that.xdr.onprogress =
860
+ that.xdr.onload = null;
861
+ if (abort) {
862
+ try {
863
+ that.xdr.abort();
864
+ } catch(x) {};
865
+ }
866
+ that.unload_ref = that.xdr = null;
867
+ };
868
+
869
+ XDRObject.prototype.close = function() {
870
+ var that = this;
871
+ that.nuke();
872
+ that._cleanup(true);
873
+ };
874
+
875
+ // 1. Is natively via XHR
876
+ // 2. Is natively via XDR
877
+ // 3. Nope, but postMessage is there so it should work via the Iframe.
878
+ // 4. Nope, sorry.
879
+ utils.isXHRCorsCapable = function() {
880
+ if (_window.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest()) {
881
+ return 1;
882
+ }
883
+ // XDomainRequest doesn't work if page is served from file://
884
+ if (_window.XDomainRequest && _document.domain) {
885
+ return 2;
886
+ }
887
+ if (IframeTransport.enabled()) {
888
+ return 3;
889
+ }
890
+ return 4;
891
+ };
892
+ // [*] End of lib/dom2.js
893
+
894
+
895
+ // [*] Including lib/sockjs.js
896
+ /*
897
+ * ***** BEGIN LICENSE BLOCK *****
898
+ * Copyright (c) 2011-2012 VMware, Inc.
899
+ *
900
+ * For the license see COPYING.
901
+ * ***** END LICENSE BLOCK *****
902
+ */
903
+
904
+ var SockJS = function(url, dep_protocols_whitelist, options) {
905
+ var that = this, protocols_whitelist;
906
+ that._options = {devel: false, debug: false, protocols_whitelist: [],
907
+ info: undefined, rtt: undefined};
908
+ if (options) {
909
+ utils.objectExtend(that._options, options);
910
+ }
911
+ that._base_url = utils.amendUrl(url);
912
+ that._server = that._options.server || utils.random_number_string(1000);
913
+ if (that._options.protocols_whitelist &&
914
+ that._options.protocols_whitelist.length) {
915
+ protocols_whitelist = that._options.protocols_whitelist;
916
+ } else {
917
+ // Deprecated API
918
+ if (typeof dep_protocols_whitelist === 'string' &&
919
+ dep_protocols_whitelist.length > 0) {
920
+ protocols_whitelist = [dep_protocols_whitelist];
921
+ } else if (utils.isArray(dep_protocols_whitelist)) {
922
+ protocols_whitelist = dep_protocols_whitelist
923
+ } else {
924
+ protocols_whitelist = null;
925
+ }
926
+ if (protocols_whitelist) {
927
+ that._debug('Deprecated API: Use "protocols_whitelist" option ' +
928
+ 'instead of supplying protocol list as a second ' +
929
+ 'parameter to SockJS constructor.');
930
+ }
931
+ }
932
+ that._protocols = [];
933
+ that.protocol = null;
934
+ that.readyState = SockJS.CONNECTING;
935
+ that._ir = createInfoReceiver(that._base_url);
936
+ that._ir.onfinish = function(info, rtt) {
937
+ that._ir = null;
938
+ if (info) {
939
+ if (that._options.info) {
940
+ // Override if user supplies the option
941
+ info = utils.objectExtend(info, that._options.info);
942
+ }
943
+ if (that._options.rtt) {
944
+ rtt = that._options.rtt;
945
+ }
946
+ that._applyInfo(info, rtt, protocols_whitelist);
947
+ that._didClose();
948
+ } else {
949
+ that._didClose(1002, 'Can\'t connect to server', true);
950
+ }
951
+ };
952
+ };
953
+ // Inheritance
954
+ SockJS.prototype = new REventTarget();
955
+
956
+ SockJS.version = "0.3.2";
957
+
958
+ SockJS.CONNECTING = 0;
959
+ SockJS.OPEN = 1;
960
+ SockJS.CLOSING = 2;
961
+ SockJS.CLOSED = 3;
962
+
963
+ SockJS.prototype._debug = function() {
964
+ if (this._options.debug)
965
+ utils.log.apply(utils, arguments);
966
+ };
967
+
968
+ SockJS.prototype._dispatchOpen = function() {
969
+ var that = this;
970
+ if (that.readyState === SockJS.CONNECTING) {
971
+ if (that._transport_tref) {
972
+ clearTimeout(that._transport_tref);
973
+ that._transport_tref = null;
974
+ }
975
+ that.readyState = SockJS.OPEN;
976
+ that.dispatchEvent(new SimpleEvent("open"));
977
+ } else {
978
+ // The server might have been restarted, and lost track of our
979
+ // connection.
980
+ that._didClose(1006, "Server lost session");
981
+ }
982
+ };
983
+
984
+ SockJS.prototype._dispatchMessage = function(data) {
985
+ var that = this;
986
+ if (that.readyState !== SockJS.OPEN)
987
+ return;
988
+ that.dispatchEvent(new SimpleEvent("message", {data: data}));
989
+ };
990
+
991
+ SockJS.prototype._dispatchHeartbeat = function(data) {
992
+ var that = this;
993
+ if (that.readyState !== SockJS.OPEN)
994
+ return;
995
+ that.dispatchEvent(new SimpleEvent('heartbeat', {}));
996
+ };
997
+
998
+ SockJS.prototype._didClose = function(code, reason, force) {
999
+ var that = this;
1000
+ if (that.readyState !== SockJS.CONNECTING &&
1001
+ that.readyState !== SockJS.OPEN &&
1002
+ that.readyState !== SockJS.CLOSING)
1003
+ throw new Error('INVALID_STATE_ERR');
1004
+ if (that._ir) {
1005
+ that._ir.nuke();
1006
+ that._ir = null;
1007
+ }
1008
+
1009
+ if (that._transport) {
1010
+ that._transport.doCleanup();
1011
+ that._transport = null;
1012
+ }
1013
+
1014
+ var close_event = new SimpleEvent("close", {
1015
+ code: code,
1016
+ reason: reason,
1017
+ wasClean: utils.userSetCode(code)});
1018
+
1019
+ if (!utils.userSetCode(code) &&
1020
+ that.readyState === SockJS.CONNECTING && !force) {
1021
+ if (that._try_next_protocol(close_event)) {
1022
+ return;
1023
+ }
1024
+ close_event = new SimpleEvent("close", {code: 2000,
1025
+ reason: "All transports failed",
1026
+ wasClean: false,
1027
+ last_event: close_event});
1028
+ }
1029
+ that.readyState = SockJS.CLOSED;
1030
+
1031
+ utils.delay(function() {
1032
+ that.dispatchEvent(close_event);
1033
+ });
1034
+ };
1035
+
1036
+ SockJS.prototype._didMessage = function(data) {
1037
+ var that = this;
1038
+ var type = data.slice(0, 1);
1039
+ switch(type) {
1040
+ case 'o':
1041
+ that._dispatchOpen();
1042
+ break;
1043
+ case 'a':
1044
+ var payload = JSON.parse(data.slice(1) || '[]');
1045
+ for(var i=0; i < payload.length; i++){
1046
+ that._dispatchMessage(payload[i]);
1047
+ }
1048
+ break;
1049
+ case 'm':
1050
+ var payload = JSON.parse(data.slice(1) || 'null');
1051
+ that._dispatchMessage(payload);
1052
+ break;
1053
+ case 'c':
1054
+ var payload = JSON.parse(data.slice(1) || '[]');
1055
+ that._didClose(payload[0], payload[1]);
1056
+ break;
1057
+ case 'h':
1058
+ that._dispatchHeartbeat();
1059
+ break;
1060
+ }
1061
+ };
1062
+
1063
+ SockJS.prototype._try_next_protocol = function(close_event) {
1064
+ var that = this;
1065
+ if (that.protocol) {
1066
+ that._debug('Closed transport:', that.protocol, ''+close_event);
1067
+ that.protocol = null;
1068
+ }
1069
+ if (that._transport_tref) {
1070
+ clearTimeout(that._transport_tref);
1071
+ that._transport_tref = null;
1072
+ }
1073
+
1074
+ while(1) {
1075
+ var protocol = that.protocol = that._protocols.shift();
1076
+ if (!protocol) {
1077
+ return false;
1078
+ }
1079
+ // Some protocols require access to `body`, what if were in
1080
+ // the `head`?
1081
+ if (SockJS[protocol] &&
1082
+ SockJS[protocol].need_body === true &&
1083
+ (!_document.body ||
1084
+ (typeof _document.readyState !== 'undefined'
1085
+ && _document.readyState !== 'complete'))) {
1086
+ that._protocols.unshift(protocol);
1087
+ that.protocol = 'waiting-for-load';
1088
+ utils.attachEvent('load', function(){
1089
+ that._try_next_protocol();
1090
+ });
1091
+ return true;
1092
+ }
1093
+
1094
+ if (!SockJS[protocol] ||
1095
+ !SockJS[protocol].enabled(that._options)) {
1096
+ that._debug('Skipping transport:', protocol);
1097
+ } else {
1098
+ var roundTrips = SockJS[protocol].roundTrips || 1;
1099
+ var to = ((that._options.rto || 0) * roundTrips) || 5000;
1100
+ that._transport_tref = utils.delay(to, function() {
1101
+ if (that.readyState === SockJS.CONNECTING) {
1102
+ // I can't understand how it is possible to run
1103
+ // this timer, when the state is CLOSED, but
1104
+ // apparently in IE everythin is possible.
1105
+ that._didClose(2007, "Transport timeouted");
1106
+ }
1107
+ });
1108
+
1109
+ var connid = utils.random_string(8);
1110
+ var trans_url = that._base_url + '/' + that._server + '/' + connid;
1111
+ that._debug('Opening transport:', protocol, ' url:'+trans_url,
1112
+ ' RTO:'+that._options.rto);
1113
+ that._transport = new SockJS[protocol](that, trans_url,
1114
+ that._base_url);
1115
+ return true;
1116
+ }
1117
+ }
1118
+ };
1119
+
1120
+ SockJS.prototype.close = function(code, reason) {
1121
+ var that = this;
1122
+ if (code && !utils.userSetCode(code))
1123
+ throw new Error("INVALID_ACCESS_ERR");
1124
+ if(that.readyState !== SockJS.CONNECTING &&
1125
+ that.readyState !== SockJS.OPEN) {
1126
+ return false;
1127
+ }
1128
+ that.readyState = SockJS.CLOSING;
1129
+ that._didClose(code || 1000, reason || "Normal closure");
1130
+ return true;
1131
+ };
1132
+
1133
+ SockJS.prototype.send = function(data) {
1134
+ var that = this;
1135
+ if (that.readyState === SockJS.CONNECTING)
1136
+ throw new Error('INVALID_STATE_ERR');
1137
+ if (that.readyState === SockJS.OPEN) {
1138
+ that._transport.doSend(utils.quote('' + data));
1139
+ }
1140
+ return true;
1141
+ };
1142
+
1143
+ SockJS.prototype._applyInfo = function(info, rtt, protocols_whitelist) {
1144
+ var that = this;
1145
+ that._options.info = info;
1146
+ that._options.rtt = rtt;
1147
+ that._options.rto = utils.countRTO(rtt);
1148
+ that._options.info.null_origin = !_document.domain;
1149
+ var probed = utils.probeProtocols();
1150
+ that._protocols = utils.detectProtocols(probed, protocols_whitelist, info);
1151
+ };
1152
+ // [*] End of lib/sockjs.js
1153
+
1154
+
1155
+ // [*] Including lib/trans-websocket.js
1156
+ /*
1157
+ * ***** BEGIN LICENSE BLOCK *****
1158
+ * Copyright (c) 2011-2012 VMware, Inc.
1159
+ *
1160
+ * For the license see COPYING.
1161
+ * ***** END LICENSE BLOCK *****
1162
+ */
1163
+
1164
+ var WebSocketTransport = SockJS.websocket = function(ri, trans_url) {
1165
+ var that = this;
1166
+ var url = trans_url + '/websocket';
1167
+ if (url.slice(0, 5) === 'https') {
1168
+ url = 'wss' + url.slice(5);
1169
+ } else {
1170
+ url = 'ws' + url.slice(4);
1171
+ }
1172
+ that.ri = ri;
1173
+ that.url = url;
1174
+ var Constructor = _window.WebSocket || _window.MozWebSocket;
1175
+
1176
+ that.ws = new Constructor(that.url);
1177
+ that.ws.onmessage = function(e) {
1178
+ that.ri._didMessage(e.data);
1179
+ };
1180
+ // Firefox has an interesting bug. If a websocket connection is
1181
+ // created after onbeforeunload, it stays alive even when user
1182
+ // navigates away from the page. In such situation let's lie -
1183
+ // let's not open the ws connection at all. See:
1184
+ // https://github.com/sockjs/sockjs-client/issues/28
1185
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=696085
1186
+ that.unload_ref = utils.unload_add(function(){that.ws.close()});
1187
+ that.ws.onclose = function() {
1188
+ that.ri._didMessage(utils.closeFrame(1006, "WebSocket connection broken"));
1189
+ };
1190
+ };
1191
+
1192
+ WebSocketTransport.prototype.doSend = function(data) {
1193
+ this.ws.send('[' + data + ']');
1194
+ };
1195
+
1196
+ WebSocketTransport.prototype.doCleanup = function() {
1197
+ var that = this;
1198
+ var ws = that.ws;
1199
+ if (ws) {
1200
+ ws.onmessage = ws.onclose = null;
1201
+ ws.close();
1202
+ utils.unload_del(that.unload_ref);
1203
+ that.unload_ref = that.ri = that.ws = null;
1204
+ }
1205
+ };
1206
+
1207
+ WebSocketTransport.enabled = function() {
1208
+ return !!(_window.WebSocket || _window.MozWebSocket);
1209
+ };
1210
+
1211
+ // In theory, ws should require 1 round trip. But in chrome, this is
1212
+ // not very stable over SSL. Most likely a ws connection requires a
1213
+ // separate SSL connection, in which case 2 round trips are an
1214
+ // absolute minumum.
1215
+ WebSocketTransport.roundTrips = 2;
1216
+ // [*] End of lib/trans-websocket.js
1217
+
1218
+
1219
+ // [*] Including lib/trans-sender.js
1220
+ /*
1221
+ * ***** BEGIN LICENSE BLOCK *****
1222
+ * Copyright (c) 2011-2012 VMware, Inc.
1223
+ *
1224
+ * For the license see COPYING.
1225
+ * ***** END LICENSE BLOCK *****
1226
+ */
1227
+
1228
+ var BufferedSender = function() {};
1229
+ BufferedSender.prototype.send_constructor = function(sender) {
1230
+ var that = this;
1231
+ that.send_buffer = [];
1232
+ that.sender = sender;
1233
+ };
1234
+ BufferedSender.prototype.doSend = function(message) {
1235
+ var that = this;
1236
+ that.send_buffer.push(message);
1237
+ if (!that.send_stop) {
1238
+ that.send_schedule();
1239
+ }
1240
+ };
1241
+
1242
+ // For polling transports in a situation when in the message callback,
1243
+ // new message is being send. If the sending connection was started
1244
+ // before receiving one, it is possible to saturate the network and
1245
+ // timeout due to the lack of receiving socket. To avoid that we delay
1246
+ // sending messages by some small time, in order to let receiving
1247
+ // connection be started beforehand. This is only a halfmeasure and
1248
+ // does not fix the big problem, but it does make the tests go more
1249
+ // stable on slow networks.
1250
+ BufferedSender.prototype.send_schedule_wait = function() {
1251
+ var that = this;
1252
+ var tref;
1253
+ that.send_stop = function() {
1254
+ that.send_stop = null;
1255
+ clearTimeout(tref);
1256
+ };
1257
+ tref = utils.delay(25, function() {
1258
+ that.send_stop = null;
1259
+ that.send_schedule();
1260
+ });
1261
+ };
1262
+
1263
+ BufferedSender.prototype.send_schedule = function() {
1264
+ var that = this;
1265
+ if (that.send_buffer.length > 0) {
1266
+ var payload = '[' + that.send_buffer.join(',') + ']';
1267
+ that.send_stop = that.sender(that.trans_url,
1268
+ payload,
1269
+ function() {
1270
+ that.send_stop = null;
1271
+ that.send_schedule_wait();
1272
+ });
1273
+ that.send_buffer = [];
1274
+ }
1275
+ };
1276
+
1277
+ BufferedSender.prototype.send_destructor = function() {
1278
+ var that = this;
1279
+ if (that._send_stop) {
1280
+ that._send_stop();
1281
+ }
1282
+ that._send_stop = null;
1283
+ };
1284
+
1285
+ var jsonPGenericSender = function(url, payload, callback) {
1286
+ var that = this;
1287
+
1288
+ if (!('_send_form' in that)) {
1289
+ var form = that._send_form = _document.createElement('form');
1290
+ var area = that._send_area = _document.createElement('textarea');
1291
+ area.name = 'd';
1292
+ form.style.display = 'none';
1293
+ form.style.position = 'absolute';
1294
+ form.method = 'POST';
1295
+ form.enctype = 'application/x-www-form-urlencoded';
1296
+ form.acceptCharset = "UTF-8";
1297
+ form.appendChild(area);
1298
+ _document.body.appendChild(form);
1299
+ }
1300
+ var form = that._send_form;
1301
+ var area = that._send_area;
1302
+ var id = 'a' + utils.random_string(8);
1303
+ form.target = id;
1304
+ form.action = url + '/jsonp_send?i=' + id;
1305
+
1306
+ var iframe;
1307
+ try {
1308
+ // ie6 dynamic iframes with target="" support (thanks Chris Lambacher)
1309
+ iframe = _document.createElement('<iframe name="'+ id +'">');
1310
+ } catch(x) {
1311
+ iframe = _document.createElement('iframe');
1312
+ iframe.name = id;
1313
+ }
1314
+ iframe.id = id;
1315
+ form.appendChild(iframe);
1316
+ iframe.style.display = 'none';
1317
+
1318
+ try {
1319
+ area.value = payload;
1320
+ } catch(e) {
1321
+ utils.log('Your browser is seriously broken. Go home! ' + e.message);
1322
+ }
1323
+ form.submit();
1324
+
1325
+ var completed = function(e) {
1326
+ if (!iframe.onerror) return;
1327
+ iframe.onreadystatechange = iframe.onerror = iframe.onload = null;
1328
+ // Opera mini doesn't like if we GC iframe
1329
+ // immediately, thus this timeout.
1330
+ utils.delay(500, function() {
1331
+ iframe.parentNode.removeChild(iframe);
1332
+ iframe = null;
1333
+ });
1334
+ area.value = '';
1335
+ callback();
1336
+ };
1337
+ iframe.onerror = iframe.onload = completed;
1338
+ iframe.onreadystatechange = function(e) {
1339
+ if (iframe.readyState == 'complete') completed();
1340
+ };
1341
+ return completed;
1342
+ };
1343
+
1344
+ var createAjaxSender = function(AjaxObject) {
1345
+ return function(url, payload, callback) {
1346
+ var xo = new AjaxObject('POST', url + '/xhr_send', payload);
1347
+ xo.onfinish = function(status, text) {
1348
+ callback(status);
1349
+ };
1350
+ return function(abort_reason) {
1351
+ callback(0, abort_reason);
1352
+ };
1353
+ };
1354
+ };
1355
+ // [*] End of lib/trans-sender.js
1356
+
1357
+
1358
+ // [*] Including lib/trans-jsonp-receiver.js
1359
+ /*
1360
+ * ***** BEGIN LICENSE BLOCK *****
1361
+ * Copyright (c) 2011-2012 VMware, Inc.
1362
+ *
1363
+ * For the license see COPYING.
1364
+ * ***** END LICENSE BLOCK *****
1365
+ */
1366
+
1367
+ // Parts derived from Socket.io:
1368
+ // https://github.com/LearnBoost/socket.io/blob/0.6.17/lib/socket.io/transports/jsonp-polling.js
1369
+ // and jQuery-JSONP:
1370
+ // https://code.google.com/p/jquery-jsonp/source/browse/trunk/core/jquery.jsonp.js
1371
+ var jsonPGenericReceiver = function(url, callback) {
1372
+ var tref;
1373
+ var script = _document.createElement('script');
1374
+ var script2; // Opera synchronous load trick.
1375
+ var close_script = function(frame) {
1376
+ if (script2) {
1377
+ script2.parentNode.removeChild(script2);
1378
+ script2 = null;
1379
+ }
1380
+ if (script) {
1381
+ clearTimeout(tref);
1382
+ script.parentNode.removeChild(script);
1383
+ script.onreadystatechange = script.onerror =
1384
+ script.onload = script.onclick = null;
1385
+ script = null;
1386
+ callback(frame);
1387
+ callback = null;
1388
+ }
1389
+ };
1390
+
1391
+ // IE9 fires 'error' event after orsc or before, in random order.
1392
+ var loaded_okay = false;
1393
+ var error_timer = null;
1394
+
1395
+ script.id = 'a' + utils.random_string(8);
1396
+ script.src = url;
1397
+ script.type = 'text/javascript';
1398
+ script.charset = 'UTF-8';
1399
+ script.onerror = function(e) {
1400
+ if (!error_timer) {
1401
+ // Delay firing close_script.
1402
+ error_timer = setTimeout(function() {
1403
+ if (!loaded_okay) {
1404
+ close_script(utils.closeFrame(
1405
+ 1006,
1406
+ "JSONP script loaded abnormally (onerror)"));
1407
+ }
1408
+ }, 1000);
1409
+ }
1410
+ };
1411
+ script.onload = function(e) {
1412
+ close_script(utils.closeFrame(1006, "JSONP script loaded abnormally (onload)"));
1413
+ };
1414
+
1415
+ script.onreadystatechange = function(e) {
1416
+ if (/loaded|closed/.test(script.readyState)) {
1417
+ if (script && script.htmlFor && script.onclick) {
1418
+ loaded_okay = true;
1419
+ try {
1420
+ // In IE, actually execute the script.
1421
+ script.onclick();
1422
+ } catch (x) {}
1423
+ }
1424
+ if (script) {
1425
+ close_script(utils.closeFrame(1006, "JSONP script loaded abnormally (onreadystatechange)"));
1426
+ }
1427
+ }
1428
+ };
1429
+ // IE: event/htmlFor/onclick trick.
1430
+ // One can't rely on proper order for onreadystatechange. In order to
1431
+ // make sure, set a 'htmlFor' and 'event' properties, so that
1432
+ // script code will be installed as 'onclick' handler for the
1433
+ // script object. Later, onreadystatechange, manually execute this
1434
+ // code. FF and Chrome doesn't work with 'event' and 'htmlFor'
1435
+ // set. For reference see:
1436
+ // http://jaubourg.net/2010/07/loading-script-as-onclick-handler-of.html
1437
+ // Also, read on that about script ordering:
1438
+ // http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order
1439
+ if (typeof script.async === 'undefined' && _document.attachEvent) {
1440
+ // According to mozilla docs, in recent browsers script.async defaults
1441
+ // to 'true', so we may use it to detect a good browser:
1442
+ // https://developer.mozilla.org/en/HTML/Element/script
1443
+ if (!/opera/i.test(navigator.userAgent)) {
1444
+ // Naively assume we're in IE
1445
+ try {
1446
+ script.htmlFor = script.id;
1447
+ script.event = "onclick";
1448
+ } catch (x) {}
1449
+ script.async = true;
1450
+ } else {
1451
+ // Opera, second sync script hack
1452
+ script2 = _document.createElement('script');
1453
+ script2.text = "try{var a = document.getElementById('"+script.id+"'); if(a)a.onerror();}catch(x){};";
1454
+ script.async = script2.async = false;
1455
+ }
1456
+ }
1457
+ if (typeof script.async !== 'undefined') {
1458
+ script.async = true;
1459
+ }
1460
+
1461
+ // Fallback mostly for Konqueror - stupid timer, 35 seconds shall be plenty.
1462
+ tref = setTimeout(function() {
1463
+ close_script(utils.closeFrame(1006, "JSONP script loaded abnormally (timeout)"));
1464
+ }, 35000);
1465
+
1466
+ var head = _document.getElementsByTagName('head')[0];
1467
+ head.insertBefore(script, head.firstChild);
1468
+ if (script2) {
1469
+ head.insertBefore(script2, head.firstChild);
1470
+ }
1471
+ return close_script;
1472
+ };
1473
+ // [*] End of lib/trans-jsonp-receiver.js
1474
+
1475
+
1476
+ // [*] Including lib/trans-jsonp-polling.js
1477
+ /*
1478
+ * ***** BEGIN LICENSE BLOCK *****
1479
+ * Copyright (c) 2011-2012 VMware, Inc.
1480
+ *
1481
+ * For the license see COPYING.
1482
+ * ***** END LICENSE BLOCK *****
1483
+ */
1484
+
1485
+ // The simplest and most robust transport, using the well-know cross
1486
+ // domain hack - JSONP. This transport is quite inefficient - one
1487
+ // mssage could use up to one http request. But at least it works almost
1488
+ // everywhere.
1489
+ // Known limitations:
1490
+ // o you will get a spinning cursor
1491
+ // o for Konqueror a dumb timer is needed to detect errors
1492
+
1493
+
1494
+ var JsonPTransport = SockJS['jsonp-polling'] = function(ri, trans_url) {
1495
+ utils.polluteGlobalNamespace();
1496
+ var that = this;
1497
+ that.ri = ri;
1498
+ that.trans_url = trans_url;
1499
+ that.send_constructor(jsonPGenericSender);
1500
+ that._schedule_recv();
1501
+ };
1502
+
1503
+ // Inheritnace
1504
+ JsonPTransport.prototype = new BufferedSender();
1505
+
1506
+ JsonPTransport.prototype._schedule_recv = function() {
1507
+ var that = this;
1508
+ var callback = function(data) {
1509
+ that._recv_stop = null;
1510
+ if (data) {
1511
+ // no data - heartbeat;
1512
+ if (!that._is_closing) {
1513
+ that.ri._didMessage(data);
1514
+ }
1515
+ }
1516
+ // The message can be a close message, and change is_closing state.
1517
+ if (!that._is_closing) {
1518
+ that._schedule_recv();
1519
+ }
1520
+ };
1521
+ that._recv_stop = jsonPReceiverWrapper(that.trans_url + '/jsonp',
1522
+ jsonPGenericReceiver, callback);
1523
+ };
1524
+
1525
+ JsonPTransport.enabled = function() {
1526
+ return true;
1527
+ };
1528
+
1529
+ JsonPTransport.need_body = true;
1530
+
1531
+
1532
+ JsonPTransport.prototype.doCleanup = function() {
1533
+ var that = this;
1534
+ that._is_closing = true;
1535
+ if (that._recv_stop) {
1536
+ that._recv_stop();
1537
+ }
1538
+ that.ri = that._recv_stop = null;
1539
+ that.send_destructor();
1540
+ };
1541
+
1542
+
1543
+ // Abstract away code that handles global namespace pollution.
1544
+ var jsonPReceiverWrapper = function(url, constructReceiver, user_callback) {
1545
+ var id = 'a' + utils.random_string(6);
1546
+ var url_id = url + '?c=' + escape(WPrefix + '.' + id);
1547
+ // Callback will be called exactly once.
1548
+ var callback = function(frame) {
1549
+ delete _window[WPrefix][id];
1550
+ user_callback(frame);
1551
+ };
1552
+
1553
+ var close_script = constructReceiver(url_id, callback);
1554
+ _window[WPrefix][id] = close_script;
1555
+ var stop = function() {
1556
+ if (_window[WPrefix][id]) {
1557
+ _window[WPrefix][id](utils.closeFrame(1000, "JSONP user aborted read"));
1558
+ }
1559
+ };
1560
+ return stop;
1561
+ };
1562
+ // [*] End of lib/trans-jsonp-polling.js
1563
+
1564
+
1565
+ // [*] Including lib/trans-xhr.js
1566
+ /*
1567
+ * ***** BEGIN LICENSE BLOCK *****
1568
+ * Copyright (c) 2011-2012 VMware, Inc.
1569
+ *
1570
+ * For the license see COPYING.
1571
+ * ***** END LICENSE BLOCK *****
1572
+ */
1573
+
1574
+ var AjaxBasedTransport = function() {};
1575
+ AjaxBasedTransport.prototype = new BufferedSender();
1576
+
1577
+ AjaxBasedTransport.prototype.run = function(ri, trans_url,
1578
+ url_suffix, Receiver, AjaxObject) {
1579
+ var that = this;
1580
+ that.ri = ri;
1581
+ that.trans_url = trans_url;
1582
+ that.send_constructor(createAjaxSender(AjaxObject));
1583
+ that.poll = new Polling(ri, Receiver,
1584
+ trans_url + url_suffix, AjaxObject);
1585
+ };
1586
+
1587
+ AjaxBasedTransport.prototype.doCleanup = function() {
1588
+ var that = this;
1589
+ if (that.poll) {
1590
+ that.poll.abort();
1591
+ that.poll = null;
1592
+ }
1593
+ };
1594
+
1595
+ // xhr-streaming
1596
+ var XhrStreamingTransport = SockJS['xhr-streaming'] = function(ri, trans_url) {
1597
+ this.run(ri, trans_url, '/xhr_streaming', XhrReceiver, utils.XHRCorsObject);
1598
+ };
1599
+
1600
+ XhrStreamingTransport.prototype = new AjaxBasedTransport();
1601
+
1602
+ XhrStreamingTransport.enabled = function() {
1603
+ // Support for CORS Ajax aka Ajax2? Opera 12 claims CORS but
1604
+ // doesn't do streaming.
1605
+ return (_window.XMLHttpRequest &&
1606
+ 'withCredentials' in new XMLHttpRequest() &&
1607
+ (!/opera/i.test(navigator.userAgent)));
1608
+ };
1609
+ XhrStreamingTransport.roundTrips = 2; // preflight, ajax
1610
+
1611
+ // Safari gets confused when a streaming ajax request is started
1612
+ // before onload. This causes the load indicator to spin indefinetely.
1613
+ XhrStreamingTransport.need_body = true;
1614
+
1615
+
1616
+ // According to:
1617
+ // http://stackoverflow.com/questions/1641507/detect-browser-support-for-cross-domain-xmlhttprequests
1618
+ // http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/
1619
+
1620
+
1621
+ // xdr-streaming
1622
+ var XdrStreamingTransport = SockJS['xdr-streaming'] = function(ri, trans_url) {
1623
+ this.run(ri, trans_url, '/xhr_streaming', XhrReceiver, utils.XDRObject);
1624
+ };
1625
+
1626
+ XdrStreamingTransport.prototype = new AjaxBasedTransport();
1627
+
1628
+ XdrStreamingTransport.enabled = function() {
1629
+ return !!_window.XDomainRequest;
1630
+ };
1631
+ XdrStreamingTransport.roundTrips = 2; // preflight, ajax
1632
+
1633
+
1634
+
1635
+ // xhr-polling
1636
+ var XhrPollingTransport = SockJS['xhr-polling'] = function(ri, trans_url) {
1637
+ this.run(ri, trans_url, '/xhr', XhrReceiver, utils.XHRCorsObject);
1638
+ };
1639
+
1640
+ XhrPollingTransport.prototype = new AjaxBasedTransport();
1641
+
1642
+ XhrPollingTransport.enabled = XhrStreamingTransport.enabled;
1643
+ XhrPollingTransport.roundTrips = 2; // preflight, ajax
1644
+
1645
+
1646
+ // xdr-polling
1647
+ var XdrPollingTransport = SockJS['xdr-polling'] = function(ri, trans_url) {
1648
+ this.run(ri, trans_url, '/xhr', XhrReceiver, utils.XDRObject);
1649
+ };
1650
+
1651
+ XdrPollingTransport.prototype = new AjaxBasedTransport();
1652
+
1653
+ XdrPollingTransport.enabled = XdrStreamingTransport.enabled;
1654
+ XdrPollingTransport.roundTrips = 2; // preflight, ajax
1655
+ // [*] End of lib/trans-xhr.js
1656
+
1657
+
1658
+ // [*] Including lib/trans-iframe.js
1659
+ /*
1660
+ * ***** BEGIN LICENSE BLOCK *****
1661
+ * Copyright (c) 2011-2012 VMware, Inc.
1662
+ *
1663
+ * For the license see COPYING.
1664
+ * ***** END LICENSE BLOCK *****
1665
+ */
1666
+
1667
+ // Few cool transports do work only for same-origin. In order to make
1668
+ // them working cross-domain we shall use iframe, served form the
1669
+ // remote domain. New browsers, have capabilities to communicate with
1670
+ // cross domain iframe, using postMessage(). In IE it was implemented
1671
+ // from IE 8+, but of course, IE got some details wrong:
1672
+ // http://msdn.microsoft.com/en-us/library/cc197015(v=VS.85).aspx
1673
+ // http://stevesouders.com/misc/test-postmessage.php
1674
+
1675
+ var IframeTransport = function() {};
1676
+
1677
+ IframeTransport.prototype.i_constructor = function(ri, trans_url, base_url) {
1678
+ var that = this;
1679
+ that.ri = ri;
1680
+ that.origin = utils.getOrigin(base_url);
1681
+ that.base_url = base_url;
1682
+ that.trans_url = trans_url;
1683
+
1684
+ var iframe_url = base_url + '/iframe.html';
1685
+ if (that.ri._options.devel) {
1686
+ iframe_url += '?t=' + (+new Date);
1687
+ }
1688
+ that.window_id = utils.random_string(8);
1689
+ iframe_url += '#' + that.window_id;
1690
+
1691
+ that.iframeObj = utils.createIframe(iframe_url, function(r) {
1692
+ that.ri._didClose(1006, "Unable to load an iframe (" + r + ")");
1693
+ });
1694
+
1695
+ that.onmessage_cb = utils.bind(that.onmessage, that);
1696
+ utils.attachMessage(that.onmessage_cb);
1697
+ };
1698
+
1699
+ IframeTransport.prototype.doCleanup = function() {
1700
+ var that = this;
1701
+ if (that.iframeObj) {
1702
+ utils.detachMessage(that.onmessage_cb);
1703
+ try {
1704
+ // When the iframe is not loaded, IE raises an exception
1705
+ // on 'contentWindow'.
1706
+ if (that.iframeObj.iframe.contentWindow) {
1707
+ that.postMessage('c');
1708
+ }
1709
+ } catch (x) {}
1710
+ that.iframeObj.cleanup();
1711
+ that.iframeObj = null;
1712
+ that.onmessage_cb = that.iframeObj = null;
1713
+ }
1714
+ };
1715
+
1716
+ IframeTransport.prototype.onmessage = function(e) {
1717
+ var that = this;
1718
+ if (e.origin !== that.origin) return;
1719
+ var window_id = e.data.slice(0, 8);
1720
+ var type = e.data.slice(8, 9);
1721
+ var data = e.data.slice(9);
1722
+
1723
+ if (window_id !== that.window_id) return;
1724
+
1725
+ switch(type) {
1726
+ case 's':
1727
+ that.iframeObj.loaded();
1728
+ that.postMessage('s', JSON.stringify([SockJS.version, that.protocol, that.trans_url, that.base_url]));
1729
+ break;
1730
+ case 't':
1731
+ that.ri._didMessage(data);
1732
+ break;
1733
+ }
1734
+ };
1735
+
1736
+ IframeTransport.prototype.postMessage = function(type, data) {
1737
+ var that = this;
1738
+ that.iframeObj.post(that.window_id + type + (data || ''), that.origin);
1739
+ };
1740
+
1741
+ IframeTransport.prototype.doSend = function (message) {
1742
+ this.postMessage('m', message);
1743
+ };
1744
+
1745
+ IframeTransport.enabled = function() {
1746
+ // postMessage misbehaves in konqueror 4.6.5 - the messages are delivered with
1747
+ // huge delay, or not at all.
1748
+ var konqueror = navigator && navigator.userAgent && navigator.userAgent.indexOf('Konqueror') !== -1;
1749
+ return ((typeof _window.postMessage === 'function' ||
1750
+ typeof _window.postMessage === 'object') && (!konqueror));
1751
+ };
1752
+ // [*] End of lib/trans-iframe.js
1753
+
1754
+
1755
+ // [*] Including lib/trans-iframe-within.js
1756
+ /*
1757
+ * ***** BEGIN LICENSE BLOCK *****
1758
+ * Copyright (c) 2011-2012 VMware, Inc.
1759
+ *
1760
+ * For the license see COPYING.
1761
+ * ***** END LICENSE BLOCK *****
1762
+ */
1763
+
1764
+ var curr_window_id;
1765
+
1766
+ var postMessage = function (type, data) {
1767
+ if(parent !== _window) {
1768
+ parent.postMessage(curr_window_id + type + (data || ''), '*');
1769
+ } else {
1770
+ utils.log("Can't postMessage, no parent window.", type, data);
1771
+ }
1772
+ };
1773
+
1774
+ var FacadeJS = function() {};
1775
+ FacadeJS.prototype._didClose = function (code, reason) {
1776
+ postMessage('t', utils.closeFrame(code, reason));
1777
+ };
1778
+ FacadeJS.prototype._didMessage = function (frame) {
1779
+ postMessage('t', frame);
1780
+ };
1781
+ FacadeJS.prototype._doSend = function (data) {
1782
+ this._transport.doSend(data);
1783
+ };
1784
+ FacadeJS.prototype._doCleanup = function () {
1785
+ this._transport.doCleanup();
1786
+ };
1787
+
1788
+ utils.parent_origin = undefined;
1789
+
1790
+ SockJS.bootstrap_iframe = function() {
1791
+ var facade;
1792
+ curr_window_id = _document.location.hash.slice(1);
1793
+ var onMessage = function(e) {
1794
+ if(e.source !== parent) return;
1795
+ if(typeof utils.parent_origin === 'undefined')
1796
+ utils.parent_origin = e.origin;
1797
+ if (e.origin !== utils.parent_origin) return;
1798
+
1799
+ var window_id = e.data.slice(0, 8);
1800
+ var type = e.data.slice(8, 9);
1801
+ var data = e.data.slice(9);
1802
+ if (window_id !== curr_window_id) return;
1803
+ switch(type) {
1804
+ case 's':
1805
+ var p = JSON.parse(data);
1806
+ var version = p[0];
1807
+ var protocol = p[1];
1808
+ var trans_url = p[2];
1809
+ var base_url = p[3];
1810
+ if (version !== SockJS.version) {
1811
+ utils.log("Incompatibile SockJS! Main site uses:" +
1812
+ " \"" + version + "\", the iframe:" +
1813
+ " \"" + SockJS.version + "\".");
1814
+ }
1815
+ if (!utils.flatUrl(trans_url) || !utils.flatUrl(base_url)) {
1816
+ utils.log("Only basic urls are supported in SockJS");
1817
+ return;
1818
+ }
1819
+
1820
+ if (!utils.isSameOriginUrl(trans_url) ||
1821
+ !utils.isSameOriginUrl(base_url)) {
1822
+ utils.log("Can't connect to different domain from within an " +
1823
+ "iframe. (" + JSON.stringify([_window.location.href, trans_url, base_url]) +
1824
+ ")");
1825
+ return;
1826
+ }
1827
+ facade = new FacadeJS();
1828
+ facade._transport = new FacadeJS[protocol](facade, trans_url, base_url);
1829
+ break;
1830
+ case 'm':
1831
+ facade._doSend(data);
1832
+ break;
1833
+ case 'c':
1834
+ if (facade)
1835
+ facade._doCleanup();
1836
+ facade = null;
1837
+ break;
1838
+ }
1839
+ };
1840
+
1841
+ // alert('test ticker');
1842
+ // facade = new FacadeJS();
1843
+ // facade._transport = new FacadeJS['w-iframe-xhr-polling'](facade, 'http://host.com:9999/ticker/12/basd');
1844
+
1845
+ utils.attachMessage(onMessage);
1846
+
1847
+ // Start
1848
+ postMessage('s');
1849
+ };
1850
+ // [*] End of lib/trans-iframe-within.js
1851
+
1852
+
1853
+ // [*] Including lib/info.js
1854
+ /*
1855
+ * ***** BEGIN LICENSE BLOCK *****
1856
+ * Copyright (c) 2011-2012 VMware, Inc.
1857
+ *
1858
+ * For the license see COPYING.
1859
+ * ***** END LICENSE BLOCK *****
1860
+ */
1861
+
1862
+ var InfoReceiver = function(base_url, AjaxObject) {
1863
+ var that = this;
1864
+ utils.delay(function(){that.doXhr(base_url, AjaxObject);});
1865
+ };
1866
+
1867
+ InfoReceiver.prototype = new EventEmitter(['finish']);
1868
+
1869
+ InfoReceiver.prototype.doXhr = function(base_url, AjaxObject) {
1870
+ var that = this;
1871
+ var t0 = (new Date()).getTime();
1872
+ var xo = new AjaxObject('GET', base_url + '/info');
1873
+
1874
+ var tref = utils.delay(8000,
1875
+ function(){xo.ontimeout();});
1876
+
1877
+ xo.onfinish = function(status, text) {
1878
+ clearTimeout(tref);
1879
+ tref = null;
1880
+ if (status === 200) {
1881
+ var rtt = (new Date()).getTime() - t0;
1882
+ var info = JSON.parse(text);
1883
+ if (typeof info !== 'object') info = {};
1884
+ that.emit('finish', info, rtt);
1885
+ } else {
1886
+ that.emit('finish');
1887
+ }
1888
+ };
1889
+ xo.ontimeout = function() {
1890
+ xo.close();
1891
+ that.emit('finish');
1892
+ };
1893
+ };
1894
+
1895
+ var InfoReceiverIframe = function(base_url) {
1896
+ var that = this;
1897
+ var go = function() {
1898
+ var ifr = new IframeTransport();
1899
+ ifr.protocol = 'w-iframe-info-receiver';
1900
+ var fun = function(r) {
1901
+ if (typeof r === 'string' && r.substr(0,1) === 'm') {
1902
+ var d = JSON.parse(r.substr(1));
1903
+ var info = d[0], rtt = d[1];
1904
+ that.emit('finish', info, rtt);
1905
+ } else {
1906
+ that.emit('finish');
1907
+ }
1908
+ ifr.doCleanup();
1909
+ ifr = null;
1910
+ };
1911
+ var mock_ri = {
1912
+ _options: {},
1913
+ _didClose: fun,
1914
+ _didMessage: fun
1915
+ };
1916
+ ifr.i_constructor(mock_ri, base_url, base_url);
1917
+ }
1918
+ if(!_document.body) {
1919
+ utils.attachEvent('load', go);
1920
+ } else {
1921
+ go();
1922
+ }
1923
+ };
1924
+ InfoReceiverIframe.prototype = new EventEmitter(['finish']);
1925
+
1926
+
1927
+ var InfoReceiverFake = function() {
1928
+ // It may not be possible to do cross domain AJAX to get the info
1929
+ // data, for example for IE7. But we want to run JSONP, so let's
1930
+ // fake the response, with rtt=2s (rto=6s).
1931
+ var that = this;
1932
+ utils.delay(function() {
1933
+ that.emit('finish', {}, 2000);
1934
+ });
1935
+ };
1936
+ InfoReceiverFake.prototype = new EventEmitter(['finish']);
1937
+
1938
+ var createInfoReceiver = function(base_url) {
1939
+ if (utils.isSameOriginUrl(base_url)) {
1940
+ // If, for some reason, we have SockJS locally - there's no
1941
+ // need to start up the complex machinery. Just use ajax.
1942
+ return new InfoReceiver(base_url, utils.XHRLocalObject);
1943
+ }
1944
+ switch (utils.isXHRCorsCapable()) {
1945
+ case 1:
1946
+ // XHRLocalObject -> no_credentials=true
1947
+ return new InfoReceiver(base_url, utils.XHRLocalObject);
1948
+ case 2:
1949
+ return new InfoReceiver(base_url, utils.XDRObject);
1950
+ case 3:
1951
+ // Opera
1952
+ return new InfoReceiverIframe(base_url);
1953
+ default:
1954
+ // IE 7
1955
+ return new InfoReceiverFake();
1956
+ };
1957
+ };
1958
+
1959
+
1960
+ var WInfoReceiverIframe = FacadeJS['w-iframe-info-receiver'] = function(ri, _trans_url, base_url) {
1961
+ var ir = new InfoReceiver(base_url, utils.XHRLocalObject);
1962
+ ir.onfinish = function(info, rtt) {
1963
+ ri._didMessage('m'+JSON.stringify([info, rtt]));
1964
+ ri._didClose();
1965
+ }
1966
+ };
1967
+ WInfoReceiverIframe.prototype.doCleanup = function() {};
1968
+ // [*] End of lib/info.js
1969
+
1970
+
1971
+ // [*] Including lib/trans-iframe-eventsource.js
1972
+ /*
1973
+ * ***** BEGIN LICENSE BLOCK *****
1974
+ * Copyright (c) 2011-2012 VMware, Inc.
1975
+ *
1976
+ * For the license see COPYING.
1977
+ * ***** END LICENSE BLOCK *****
1978
+ */
1979
+
1980
+ var EventSourceIframeTransport = SockJS['iframe-eventsource'] = function () {
1981
+ var that = this;
1982
+ that.protocol = 'w-iframe-eventsource';
1983
+ that.i_constructor.apply(that, arguments);
1984
+ };
1985
+
1986
+ EventSourceIframeTransport.prototype = new IframeTransport();
1987
+
1988
+ EventSourceIframeTransport.enabled = function () {
1989
+ return ('EventSource' in _window) && IframeTransport.enabled();
1990
+ };
1991
+
1992
+ EventSourceIframeTransport.need_body = true;
1993
+ EventSourceIframeTransport.roundTrips = 3; // html, javascript, eventsource
1994
+
1995
+
1996
+ // w-iframe-eventsource
1997
+ var EventSourceTransport = FacadeJS['w-iframe-eventsource'] = function(ri, trans_url) {
1998
+ this.run(ri, trans_url, '/eventsource', EventSourceReceiver, utils.XHRLocalObject);
1999
+ }
2000
+ EventSourceTransport.prototype = new AjaxBasedTransport();
2001
+ // [*] End of lib/trans-iframe-eventsource.js
2002
+
2003
+
2004
+ // [*] Including lib/trans-iframe-xhr-polling.js
2005
+ /*
2006
+ * ***** BEGIN LICENSE BLOCK *****
2007
+ * Copyright (c) 2011-2012 VMware, Inc.
2008
+ *
2009
+ * For the license see COPYING.
2010
+ * ***** END LICENSE BLOCK *****
2011
+ */
2012
+
2013
+ var XhrPollingIframeTransport = SockJS['iframe-xhr-polling'] = function () {
2014
+ var that = this;
2015
+ that.protocol = 'w-iframe-xhr-polling';
2016
+ that.i_constructor.apply(that, arguments);
2017
+ };
2018
+
2019
+ XhrPollingIframeTransport.prototype = new IframeTransport();
2020
+
2021
+ XhrPollingIframeTransport.enabled = function () {
2022
+ return _window.XMLHttpRequest && IframeTransport.enabled();
2023
+ };
2024
+
2025
+ XhrPollingIframeTransport.need_body = true;
2026
+ XhrPollingIframeTransport.roundTrips = 3; // html, javascript, xhr
2027
+
2028
+
2029
+ // w-iframe-xhr-polling
2030
+ var XhrPollingITransport = FacadeJS['w-iframe-xhr-polling'] = function(ri, trans_url) {
2031
+ this.run(ri, trans_url, '/xhr', XhrReceiver, utils.XHRLocalObject);
2032
+ };
2033
+
2034
+ XhrPollingITransport.prototype = new AjaxBasedTransport();
2035
+ // [*] End of lib/trans-iframe-xhr-polling.js
2036
+
2037
+
2038
+ // [*] Including lib/trans-iframe-htmlfile.js
2039
+ /*
2040
+ * ***** BEGIN LICENSE BLOCK *****
2041
+ * Copyright (c) 2011-2012 VMware, Inc.
2042
+ *
2043
+ * For the license see COPYING.
2044
+ * ***** END LICENSE BLOCK *****
2045
+ */
2046
+
2047
+ // This transport generally works in any browser, but will cause a
2048
+ // spinning cursor to appear in any browser other than IE.
2049
+ // We may test this transport in all browsers - why not, but in
2050
+ // production it should be only run in IE.
2051
+
2052
+ var HtmlFileIframeTransport = SockJS['iframe-htmlfile'] = function () {
2053
+ var that = this;
2054
+ that.protocol = 'w-iframe-htmlfile';
2055
+ that.i_constructor.apply(that, arguments);
2056
+ };
2057
+
2058
+ // Inheritance.
2059
+ HtmlFileIframeTransport.prototype = new IframeTransport();
2060
+
2061
+ HtmlFileIframeTransport.enabled = function() {
2062
+ return IframeTransport.enabled();
2063
+ };
2064
+
2065
+ HtmlFileIframeTransport.need_body = true;
2066
+ HtmlFileIframeTransport.roundTrips = 3; // html, javascript, htmlfile
2067
+
2068
+
2069
+ // w-iframe-htmlfile
2070
+ var HtmlFileTransport = FacadeJS['w-iframe-htmlfile'] = function(ri, trans_url) {
2071
+ this.run(ri, trans_url, '/htmlfile', HtmlfileReceiver, utils.XHRLocalObject);
2072
+ };
2073
+ HtmlFileTransport.prototype = new AjaxBasedTransport();
2074
+ // [*] End of lib/trans-iframe-htmlfile.js
2075
+
2076
+
2077
+ // [*] Including lib/trans-polling.js
2078
+ /*
2079
+ * ***** BEGIN LICENSE BLOCK *****
2080
+ * Copyright (c) 2011-2012 VMware, Inc.
2081
+ *
2082
+ * For the license see COPYING.
2083
+ * ***** END LICENSE BLOCK *****
2084
+ */
2085
+
2086
+ var Polling = function(ri, Receiver, recv_url, AjaxObject) {
2087
+ var that = this;
2088
+ that.ri = ri;
2089
+ that.Receiver = Receiver;
2090
+ that.recv_url = recv_url;
2091
+ that.AjaxObject = AjaxObject;
2092
+ that._scheduleRecv();
2093
+ };
2094
+
2095
+ Polling.prototype._scheduleRecv = function() {
2096
+ var that = this;
2097
+ var poll = that.poll = new that.Receiver(that.recv_url, that.AjaxObject);
2098
+ var msg_counter = 0;
2099
+ poll.onmessage = function(e) {
2100
+ msg_counter += 1;
2101
+ that.ri._didMessage(e.data);
2102
+ };
2103
+ poll.onclose = function(e) {
2104
+ that.poll = poll = poll.onmessage = poll.onclose = null;
2105
+ if (!that.poll_is_closing) {
2106
+ if (e.reason === 'permanent') {
2107
+ that.ri._didClose(1006, 'Polling error (' + e.reason + ')');
2108
+ } else {
2109
+ that._scheduleRecv();
2110
+ }
2111
+ }
2112
+ };
2113
+ };
2114
+
2115
+ Polling.prototype.abort = function() {
2116
+ var that = this;
2117
+ that.poll_is_closing = true;
2118
+ if (that.poll) {
2119
+ that.poll.abort();
2120
+ }
2121
+ };
2122
+ // [*] End of lib/trans-polling.js
2123
+
2124
+
2125
+ // [*] Including lib/trans-receiver-eventsource.js
2126
+ /*
2127
+ * ***** BEGIN LICENSE BLOCK *****
2128
+ * Copyright (c) 2011-2012 VMware, Inc.
2129
+ *
2130
+ * For the license see COPYING.
2131
+ * ***** END LICENSE BLOCK *****
2132
+ */
2133
+
2134
+ var EventSourceReceiver = function(url) {
2135
+ var that = this;
2136
+ var es = new EventSource(url);
2137
+ es.onmessage = function(e) {
2138
+ that.dispatchEvent(new SimpleEvent('message',
2139
+ {'data': unescape(e.data)}));
2140
+ };
2141
+ that.es_close = es.onerror = function(e, abort_reason) {
2142
+ // ES on reconnection has readyState = 0 or 1.
2143
+ // on network error it's CLOSED = 2
2144
+ var reason = abort_reason ? 'user' :
2145
+ (es.readyState !== 2 ? 'network' : 'permanent');
2146
+ that.es_close = es.onmessage = es.onerror = null;
2147
+ // EventSource reconnects automatically.
2148
+ es.close();
2149
+ es = null;
2150
+ // Safari and chrome < 15 crash if we close window before
2151
+ // waiting for ES cleanup. See:
2152
+ // https://code.google.com/p/chromium/issues/detail?id=89155
2153
+ utils.delay(200, function() {
2154
+ that.dispatchEvent(new SimpleEvent('close', {reason: reason}));
2155
+ });
2156
+ };
2157
+ };
2158
+
2159
+ EventSourceReceiver.prototype = new REventTarget();
2160
+
2161
+ EventSourceReceiver.prototype.abort = function() {
2162
+ var that = this;
2163
+ if (that.es_close) {
2164
+ that.es_close({}, true);
2165
+ }
2166
+ };
2167
+ // [*] End of lib/trans-receiver-eventsource.js
2168
+
2169
+
2170
+ // [*] Including lib/trans-receiver-htmlfile.js
2171
+ /*
2172
+ * ***** BEGIN LICENSE BLOCK *****
2173
+ * Copyright (c) 2011-2012 VMware, Inc.
2174
+ *
2175
+ * For the license see COPYING.
2176
+ * ***** END LICENSE BLOCK *****
2177
+ */
2178
+
2179
+ var _is_ie_htmlfile_capable;
2180
+ var isIeHtmlfileCapable = function() {
2181
+ if (_is_ie_htmlfile_capable === undefined) {
2182
+ if ('ActiveXObject' in _window) {
2183
+ try {
2184
+ _is_ie_htmlfile_capable = !!new ActiveXObject('htmlfile');
2185
+ } catch (x) {}
2186
+ } else {
2187
+ _is_ie_htmlfile_capable = false;
2188
+ }
2189
+ }
2190
+ return _is_ie_htmlfile_capable;
2191
+ };
2192
+
2193
+
2194
+ var HtmlfileReceiver = function(url) {
2195
+ var that = this;
2196
+ utils.polluteGlobalNamespace();
2197
+
2198
+ that.id = 'a' + utils.random_string(6, 26);
2199
+ url += ((url.indexOf('?') === -1) ? '?' : '&') +
2200
+ 'c=' + escape(WPrefix + '.' + that.id);
2201
+
2202
+ var constructor = isIeHtmlfileCapable() ?
2203
+ utils.createHtmlfile : utils.createIframe;
2204
+
2205
+ var iframeObj;
2206
+ _window[WPrefix][that.id] = {
2207
+ start: function () {
2208
+ iframeObj.loaded();
2209
+ },
2210
+ message: function (data) {
2211
+ that.dispatchEvent(new SimpleEvent('message', {'data': data}));
2212
+ },
2213
+ stop: function () {
2214
+ that.iframe_close({}, 'network');
2215
+ }
2216
+ };
2217
+ that.iframe_close = function(e, abort_reason) {
2218
+ iframeObj.cleanup();
2219
+ that.iframe_close = iframeObj = null;
2220
+ delete _window[WPrefix][that.id];
2221
+ that.dispatchEvent(new SimpleEvent('close', {reason: abort_reason}));
2222
+ };
2223
+ iframeObj = constructor(url, function(e) {
2224
+ that.iframe_close({}, 'permanent');
2225
+ });
2226
+ };
2227
+
2228
+ HtmlfileReceiver.prototype = new REventTarget();
2229
+
2230
+ HtmlfileReceiver.prototype.abort = function() {
2231
+ var that = this;
2232
+ if (that.iframe_close) {
2233
+ that.iframe_close({}, 'user');
2234
+ }
2235
+ };
2236
+ // [*] End of lib/trans-receiver-htmlfile.js
2237
+
2238
+
2239
+ // [*] Including lib/trans-receiver-xhr.js
2240
+ /*
2241
+ * ***** BEGIN LICENSE BLOCK *****
2242
+ * Copyright (c) 2011-2012 VMware, Inc.
2243
+ *
2244
+ * For the license see COPYING.
2245
+ * ***** END LICENSE BLOCK *****
2246
+ */
2247
+
2248
+ var XhrReceiver = function(url, AjaxObject) {
2249
+ var that = this;
2250
+ var buf_pos = 0;
2251
+
2252
+ that.xo = new AjaxObject('POST', url, null);
2253
+ that.xo.onchunk = function(status, text) {
2254
+ if (status !== 200) return;
2255
+ while (1) {
2256
+ var buf = text.slice(buf_pos);
2257
+ var p = buf.indexOf('\n');
2258
+ if (p === -1) break;
2259
+ buf_pos += p+1;
2260
+ var msg = buf.slice(0, p);
2261
+ that.dispatchEvent(new SimpleEvent('message', {data: msg}));
2262
+ }
2263
+ };
2264
+ that.xo.onfinish = function(status, text) {
2265
+ that.xo.onchunk(status, text);
2266
+ that.xo = null;
2267
+ var reason = status === 200 ? 'network' : 'permanent';
2268
+ that.dispatchEvent(new SimpleEvent('close', {reason: reason}));
2269
+ }
2270
+ };
2271
+
2272
+ XhrReceiver.prototype = new REventTarget();
2273
+
2274
+ XhrReceiver.prototype.abort = function() {
2275
+ var that = this;
2276
+ if (that.xo) {
2277
+ that.xo.close();
2278
+ that.dispatchEvent(new SimpleEvent('close', {reason: 'user'}));
2279
+ that.xo = null;
2280
+ }
2281
+ };
2282
+ // [*] End of lib/trans-receiver-xhr.js
2283
+
2284
+
2285
+ // [*] Including lib/test-hooks.js
2286
+ /*
2287
+ * ***** BEGIN LICENSE BLOCK *****
2288
+ * Copyright (c) 2011-2012 VMware, Inc.
2289
+ *
2290
+ * For the license see COPYING.
2291
+ * ***** END LICENSE BLOCK *****
2292
+ */
2293
+
2294
+ // For testing
2295
+ SockJS.getUtils = function(){
2296
+ return utils;
2297
+ };
2298
+
2299
+ SockJS.getIframeTransport = function(){
2300
+ return IframeTransport;
2301
+ };
2302
+ // [*] End of lib/test-hooks.js
2303
+
2304
+ return SockJS;
2305
+ })();
2306
+ if ('_sockjs_onload' in window) setTimeout(_sockjs_onload, 1);
2307
+
2308
+ // AMD compliance
2309
+ if (typeof define === 'function' && define.amd) {
2310
+ define('sockjs', [], function(){return SockJS;});
2311
+ }
2312
+ // [*] End of lib/index.js
2313
+
2314
+ // [*] End of lib/all.js