4 * Copyright(c) 2011 LearnBoost <dev@learnboost.com>
8 (function (exports, io, global) {
10 * There is a way to hide the loading indicator in Firefox. If you create and
11 * remove a iframe it will stop showing the current loading indicator.
12 * Unfortunately we can't feature detect that and UA sniffing is evil.
17 var indicator = global.document && "MozAppearance" in
18 global.document.documentElement.style;
24 exports['jsonp-polling'] = JSONPPolling;
27 * The JSONP transport creates an persistent connection by dynamically
28 * inserting a script tag in the page. This script tag will receive the
29 * information of the Socket.IO server. When new information is received
30 * it creates a new script tag for the new data stream.
33 * @extends {io.Transport.xhr-polling}
37 function JSONPPolling (socket) {
38 io.Transport['xhr-polling'].apply(this, arguments);
40 this.index = io.j.length;
44 io.j.push(function (msg) {
50 * Inherits from XHR polling transport.
53 io.util.inherit(JSONPPolling, io.Transport['xhr-polling']);
61 JSONPPolling.prototype.name = 'jsonp-polling';
64 * Posts a encoded message to the Socket.IO server using an iframe.
65 * The iframe is used because script tags can create POST based requests.
66 * The iframe is positioned outside of the view so the user does not
67 * notice it's existence.
69 * @param {String} data A encoded message.
73 JSONPPolling.prototype.post = function (data) {
75 , query = io.util.query(
76 this.socket.options.query
77 , 't='+ (+new Date) + '&i=' + this.index
81 var form = document.createElement('form')
82 , area = document.createElement('textarea')
83 , id = this.iframeId = 'socketio_iframe_' + this.index
86 form.className = 'socketio';
87 form.style.position = 'absolute';
88 form.style.top = '0px';
89 form.style.left = '0px';
90 form.style.display = 'none';
93 form.setAttribute('accept-charset', 'utf-8');
95 form.appendChild(area);
96 document.body.appendChild(form);
102 this.form.action = this.prepareUrl() + query;
104 function complete () {
106 self.socket.setBuffer(false);
109 function initIframe () {
111 self.form.removeChild(self.iframe);
115 // ie6 dynamic iframes with target="" support (thanks Chris Lambacher)
116 iframe = document.createElement('<iframe name="'+ self.iframeId +'">');
118 iframe = document.createElement('iframe');
119 iframe.name = self.iframeId;
122 iframe.id = self.iframeId;
124 self.form.appendChild(iframe);
125 self.iframe = iframe;
130 // we temporarily stringify until we figure out how to prevent
131 // browsers from turning `\n` into `\r\n` in form inputs
132 this.area.value = io.JSON.stringify(data);
138 if (this.iframe.attachEvent) {
139 iframe.onreadystatechange = function () {
140 if (self.iframe.readyState == 'complete') {
145 this.iframe.onload = complete;
148 this.socket.setBuffer(true);
152 * Creates a new JSONP poll that can be used to listen
153 * for messages from the Socket.IO server.
158 JSONPPolling.prototype.get = function () {
160 , script = document.createElement('script')
161 , query = io.util.query(
162 this.socket.options.query
163 , 't='+ (+new Date) + '&i=' + this.index
167 this.script.parentNode.removeChild(this.script);
172 script.src = this.prepareUrl() + query;
173 script.onerror = function () {
177 var insertAt = document.getElementsByTagName('script')[0];
178 insertAt.parentNode.insertBefore(script, insertAt);
179 this.script = script;
182 setTimeout(function () {
183 var iframe = document.createElement('iframe');
184 document.body.appendChild(iframe);
185 document.body.removeChild(iframe);
191 * Callback function for the incoming message stream from the Socket.IO server.
193 * @param {String} data The message
197 JSONPPolling.prototype._ = function (msg) {
206 * The indicator hack only works after onload
208 * @param {Socket} socket The socket instance that needs a transport
209 * @param {Function} fn The callback
213 JSONPPolling.prototype.ready = function (socket, fn) {
215 if (!indicator) return fn.call(this);
217 io.util.load(function () {
223 * Checks if browser supports this transport.
229 JSONPPolling.check = function () {
230 return 'document' in global;
234 * Check if cross domain requests are supported
240 JSONPPolling.xdomainCheck = function () {
245 * Add the transport to your public io.transports array.
250 io.transports.push('jsonp-polling');
253 'undefined' != typeof io ? io.Transport : module.exports
254 , 'undefined' != typeof io ? io : module.parent.exports