mirror of
https://github.com/viq/NewsBlur.git
synced 2025-08-05 16:49:45 +00:00
255 lines
5.8 KiB
JavaScript
255 lines
5.8 KiB
JavaScript
|
|
/**
|
|
* socket.io
|
|
* Copyright(c) 2011 LearnBoost <dev@learnboost.com>
|
|
* MIT Licensed
|
|
*/
|
|
|
|
(function (exports, io, global) {
|
|
/**
|
|
* There is a way to hide the loading indicator in Firefox. If you create and
|
|
* remove a iframe it will stop showing the current loading indicator.
|
|
* Unfortunately we can't feature detect that and UA sniffing is evil.
|
|
*
|
|
* @api private
|
|
*/
|
|
|
|
var indicator = global.document && "MozAppearance" in
|
|
global.document.documentElement.style;
|
|
|
|
/**
|
|
* Expose constructor.
|
|
*/
|
|
|
|
exports['jsonp-polling'] = JSONPPolling;
|
|
|
|
/**
|
|
* The JSONP transport creates an persistent connection by dynamically
|
|
* inserting a script tag in the page. This script tag will receive the
|
|
* information of the Socket.IO server. When new information is received
|
|
* it creates a new script tag for the new data stream.
|
|
*
|
|
* @constructor
|
|
* @extends {io.Transport.xhr-polling}
|
|
* @api public
|
|
*/
|
|
|
|
function JSONPPolling (socket) {
|
|
io.Transport['xhr-polling'].apply(this, arguments);
|
|
|
|
this.index = io.j.length;
|
|
|
|
var self = this;
|
|
|
|
io.j.push(function (msg) {
|
|
self._(msg);
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Inherits from XHR polling transport.
|
|
*/
|
|
|
|
io.util.inherit(JSONPPolling, io.Transport['xhr-polling']);
|
|
|
|
/**
|
|
* Transport name
|
|
*
|
|
* @api public
|
|
*/
|
|
|
|
JSONPPolling.prototype.name = 'jsonp-polling';
|
|
|
|
/**
|
|
* Posts a encoded message to the Socket.IO server using an iframe.
|
|
* The iframe is used because script tags can create POST based requests.
|
|
* The iframe is positioned outside of the view so the user does not
|
|
* notice it's existence.
|
|
*
|
|
* @param {String} data A encoded message.
|
|
* @api private
|
|
*/
|
|
|
|
JSONPPolling.prototype.post = function (data) {
|
|
var self = this
|
|
, query = io.util.query(
|
|
this.socket.options.query
|
|
, 't='+ (+new Date) + '&i=' + this.index
|
|
);
|
|
|
|
if (!this.form) {
|
|
var form = document.createElement('form')
|
|
, area = document.createElement('textarea')
|
|
, id = this.iframeId = 'socketio_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.prepareUrl() + query;
|
|
|
|
function complete () {
|
|
initIframe();
|
|
self.socket.setBuffer(false);
|
|
};
|
|
|
|
function initIframe () {
|
|
if (self.iframe) {
|
|
self.form.removeChild(self.iframe);
|
|
}
|
|
|
|
try {
|
|
// ie6 dynamic iframes with target="" support (thanks Chris Lambacher)
|
|
iframe = document.createElement('<iframe name="'+ self.iframeId +'">');
|
|
} catch (e) {
|
|
iframe = document.createElement('iframe');
|
|
iframe.name = self.iframeId;
|
|
}
|
|
|
|
iframe.id = self.iframeId;
|
|
|
|
self.form.appendChild(iframe);
|
|
self.iframe = iframe;
|
|
};
|
|
|
|
initIframe();
|
|
|
|
// we temporarily stringify until we figure out how to prevent
|
|
// browsers from turning `\n` into `\r\n` in form inputs
|
|
this.area.value = io.JSON.stringify(data);
|
|
|
|
try {
|
|
this.form.submit();
|
|
} catch(e) {}
|
|
|
|
if (this.iframe.attachEvent) {
|
|
iframe.onreadystatechange = function () {
|
|
if (self.iframe.readyState == 'complete') {
|
|
complete();
|
|
}
|
|
};
|
|
} else {
|
|
this.iframe.onload = complete;
|
|
}
|
|
|
|
this.socket.setBuffer(true);
|
|
};
|
|
|
|
/**
|
|
* Creates a new JSONP poll that can be used to listen
|
|
* for messages from the Socket.IO server.
|
|
*
|
|
* @api private
|
|
*/
|
|
|
|
JSONPPolling.prototype.get = function () {
|
|
var self = this
|
|
, script = document.createElement('script')
|
|
, query = io.util.query(
|
|
this.socket.options.query
|
|
, 't='+ (+new Date) + '&i=' + this.index
|
|
);
|
|
|
|
if (this.script) {
|
|
this.script.parentNode.removeChild(this.script);
|
|
this.script = null;
|
|
}
|
|
|
|
script.async = true;
|
|
script.src = this.prepareUrl() + query;
|
|
script.onerror = function () {
|
|
self.onClose();
|
|
};
|
|
|
|
var insertAt = document.getElementsByTagName('script')[0]
|
|
insertAt.parentNode.insertBefore(script, insertAt);
|
|
this.script = script;
|
|
|
|
if (indicator) {
|
|
setTimeout(function () {
|
|
var iframe = document.createElement('iframe');
|
|
document.body.appendChild(iframe);
|
|
document.body.removeChild(iframe);
|
|
}, 100);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Callback function for the incoming message stream from the Socket.IO server.
|
|
*
|
|
* @param {String} data The message
|
|
* @api private
|
|
*/
|
|
|
|
JSONPPolling.prototype._ = function (msg) {
|
|
this.onData(msg);
|
|
if (this.open) {
|
|
this.get();
|
|
}
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* The indicator hack only works after onload
|
|
*
|
|
* @param {Socket} socket The socket instance that needs a transport
|
|
* @param {Function} fn The callback
|
|
* @api private
|
|
*/
|
|
|
|
JSONPPolling.prototype.ready = function (socket, fn) {
|
|
var self = this;
|
|
if (!indicator) return fn.call(this);
|
|
|
|
io.util.load(function () {
|
|
fn.call(self);
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Checks if browser supports this transport.
|
|
*
|
|
* @return {Boolean}
|
|
* @api public
|
|
*/
|
|
|
|
JSONPPolling.check = function () {
|
|
return 'document' in global;
|
|
};
|
|
|
|
/**
|
|
* Check if cross domain requests are supported
|
|
*
|
|
* @returns {Boolean}
|
|
* @api public
|
|
*/
|
|
|
|
JSONPPolling.xdomainCheck = function () {
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* Add the transport to your public io.transports array.
|
|
*
|
|
* @api private
|
|
*/
|
|
|
|
io.transports.push('jsonp-polling');
|
|
|
|
})(
|
|
'undefined' != typeof io ? io.Transport : module.exports
|
|
, 'undefined' != typeof io ? io : module.parent.exports
|
|
, this
|
|
);
|