socketioMEANseed/server/node_modules/engine.io-client/lib/transports/polling-jsonp.js
server/node_modules/engine.io-client/lib/transports/polling-jsonp.jsRaw
1
2/**
3 * Module requirements.
4 */
5
6var Polling = require('./polling');
7var inherit = require('component-inherit');
8
9/**
10 * Module exports.
11 */
12
13module.exports = JSONPPolling;
14
15/**
16 * Cached regular expressions.
17 */
18
19var rNewline = /\n/g;
20var rEscapedNewline = /\\n/g;
21
22/**
23 * Global JSONP callbacks.
24 */
25
26var callbacks;
27
28/**
29 * Noop.
30 */
31
32function empty () { }
33
34/**
35 * JSONP Polling constructor.
36 *
37 * @param {Object} opts.
38 * @api public
39 */
40
41function JSONPPolling (opts) {
42 Polling.call(this, opts);
43
44 this.query = this.query || {};
45
46 // define global callbacks array if not present
47 // we do this here (lazily) to avoid unneeded global pollution
48 if (!callbacks) {
49 // we need to consider multiple engines in the same page
50 if (!global.___eio) global.___eio = [];
51 callbacks = global.___eio;
52 }
53
54 // callback identifier
55 this.index = callbacks.length;
56
57 // add callback to jsonp global
58 var self = this;
59 callbacks.push(function (msg) {
60 self.onData(msg);
61 });
62
63 // append to query string
64 this.query.j = this.index;
65
66 // prevent spurious errors from being emitted when the window is unloaded
67 if (global.document && global.addEventListener) {
68 global.addEventListener('beforeunload', function () {
69 if (self.script) self.script.onerror = empty;
70 }, false);
71 }
72}
73
74/**
75 * Inherits from Polling.
76 */
77
78inherit(JSONPPolling, Polling);
79
80/*
81 * JSONP only supports binary as base64 encoded strings
82 */
83
84JSONPPolling.prototype.supportsBinary = false;
85
86/**
87 * Closes the socket.
88 *
89 * @api private
90 */
91
92JSONPPolling.prototype.doClose = function () {
93 if (this.script) {
94 this.script.parentNode.removeChild(this.script);
95 this.script = null;
96 }
97
98 if (this.form) {
99 this.form.parentNode.removeChild(this.form);
100 this.form = null;
101 this.iframe = null;
102 }
103
104 Polling.prototype.doClose.call(this);
105};
106
107/**
108 * Starts a poll cycle.
109 *
110 * @api private
111 */
112
113JSONPPolling.prototype.doPoll = function () {
114 var self = this;
115 var script = document.createElement('script');
116
117 if (this.script) {
118 this.script.parentNode.removeChild(this.script);
119 this.script = null;
120 }
121
122 script.async = true;
123 script.src = this.uri();
124 script.onerror = function (e) {
125 self.onError('jsonp poll error', e);
126 };
127
128 var insertAt = document.getElementsByTagName('script')[0];
129 if (insertAt) {
130 insertAt.parentNode.insertBefore(script, insertAt);
131 } else {
132 (document.head || document.body).appendChild(script);
133 }
134 this.script = script;
135
136 var isUAgecko = 'undefined' !== typeof navigator && /gecko/i.test(navigator.userAgent);
137
138 if (isUAgecko) {
139 setTimeout(function () {
140 var iframe = document.createElement('iframe');
141 document.body.appendChild(iframe);
142 document.body.removeChild(iframe);
143 }, 100);
144 }
145};
146
147/**
148 * Writes with a hidden iframe.
149 *
150 * @param {String} data to send
151 * @param {Function} called upon flush.
152 * @api private
153 */
154
155JSONPPolling.prototype.doWrite = function (data, fn) {
156 var self = this;
157
158 if (!this.form) {
159 var form = document.createElement('form');
160 var area = document.createElement('textarea');
161 var id = this.iframeId = 'eio_iframe_' + this.index;
162 var iframe;
163
164 form.className = 'socketio';
165 form.style.position = 'absolute';
166 form.style.top = '-1000px';
167 form.style.left = '-1000px';
168 form.target = id;
169 form.method = 'POST';
170 form.setAttribute('accept-charset', 'utf-8');
171 area.name = 'd';
172 form.appendChild(area);
173 document.body.appendChild(form);
174
175 this.form = form;
176 this.area = area;
177 }
178
179 this.form.action = this.uri();
180
181 function complete () {
182 initIframe();
183 fn();
184 }
185
186 function initIframe () {
187 if (self.iframe) {
188 try {
189 self.form.removeChild(self.iframe);
190 } catch (e) {
191 self.onError('jsonp polling iframe removal error', e);
192 }
193 }
194
195 try {
196 // ie6 dynamic iframes with target="" support (thanks Chris Lambacher)
197 var html = '<iframe src="javascript:0" name="' + self.iframeId + '">';
198 iframe = document.createElement(html);
199 } catch (e) {
200 iframe = document.createElement('iframe');
201 iframe.name = self.iframeId;
202 iframe.src = 'javascript:0';
203 }
204
205 iframe.id = self.iframeId;
206
207 self.form.appendChild(iframe);
208 self.iframe = iframe;
209 }
210
211 initIframe();
212
213 // escape \n to prevent it from being converted into \r\n by some UAs
214 // double escaping is required for escaped new lines because unescaping of new lines can be done safely on server-side
215 data = data.replace(rEscapedNewline, '\\\n');
216 this.area.value = data.replace(rNewline, '\\n');
217
218 try {
219 this.form.submit();
220 } catch (e) {}
221
222 if (this.iframe.attachEvent) {
223 this.iframe.onreadystatechange = function () {
224 if (self.iframe.readyState === 'complete') {
225 complete();
226 }
227 };
228 } else {
229 this.iframe.onload = complete;
230 }
231};