rhet-butler 0.11.1 → 0.12.1

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