arnaucube
arnaucube/socketioMEANseedPublic Self-hosted repository
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};