/** * Module requirements. */ var Polling = require('./polling') , util = require('../util'); /** * Module exports. */ module.exports = JSONPPolling; /** * Global reference. */ var global = 'undefined' != typeof window ? window : global; /** * Cached regular expressions. */ var rNewline = /\n/g; /** * Global JSONP callbacks. */ var callbacks; /** * Callbacks count. */ var index = 0; /** * Noop. */ function empty () { } /** * JSONP Polling constructor. * * @param {Object} opts. * @api public */ function JSONPPolling (opts) { Polling.call(this, opts); // define global callbacks array if not present // we do this here (lazily) to avoid unneeded global pollution if (!callbacks) { // we need to consider multiple engines in the same page if (!global.___eio) global.___eio = []; callbacks = global.___eio; } // callback identifier this.index = callbacks.length; // add callback to jsonp global var self = this; callbacks.push(function (msg) { self.onData(msg); }); // append to query string this.query.j = this.index; }; /** * Inherits from Polling. */ util.inherits(JSONPPolling, Polling); /** * Opens the socket. * * @api private */ JSONPPolling.prototype.doOpen = function () { var self = this; util.defer(function () { Polling.prototype.doOpen.call(self); }); }; /** * Closes the socket * * @api private */ JSONPPolling.prototype.doClose = function () { if (this.script) { this.script.parentNode.removeChild(this.script); this.script = null; } if (this.form) { this.form.parentNode.removeChild(this.form); this.form = null; } Polling.prototype.doClose.call(this); }; /** * Starts a poll cycle. * * @api private */ JSONPPolling.prototype.doPoll = function () { var script = document.createElement('script'); if (this.script) { this.script.parentNode.removeChild(this.script); this.script = null; } script.async = true; script.src = this.uri(); var insertAt = document.getElementsByTagName('script')[0]; insertAt.parentNode.insertBefore(script, insertAt); this.script = script; if (util.ua.gecko) { setTimeout(function () { var iframe = document.createElement('iframe'); document.body.appendChild(iframe); document.body.removeChild(iframe); }, 100); } }; /** * Writes with a hidden iframe. * * @param {String} data to send * @param {Function} called upon flush. * @api private */ JSONPPolling.prototype.doWrite = function (data, fn) { var self = this; if (!this.form) { var form = document.createElement('form') , area = document.createElement('textarea') , id = this.iframeId = 'eio_iframe_' + this.index , iframe; form.className = 'socketio'; form.style.position = 'absolute'; form.style.top = '-1000px'; form.style.left = '-1000px'; form.target = id; form.method = 'POST'; form.setAttribute('accept-charset', 'utf-8'); area.name = 'd'; form.appendChild(area); document.body.appendChild(form); this.form = form; this.area = area; } this.form.action = this.uri(); function complete () { initIframe(); fn(); }; function initIframe () { if (self.iframe) { self.form.removeChild(self.iframe); } try { // ie6 dynamic iframes with target="" support (thanks Chris Lambacher) iframe = document.createElement('