You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by pa...@apache.org on 2013/10/28 09:16:54 UTC
[38/47] Upgrade Atmosphere to 2.0.0
http://git-wip-us.apache.org/repos/asf/wicket/blob/a13dec06/wicket-experimental/wicket-atmosphere/src/main/java/org/apache/wicket/atmosphere/jquery.atmosphere.js
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-atmosphere/src/main/java/org/apache/wicket/atmosphere/jquery.atmosphere.js b/wicket-experimental/wicket-atmosphere/src/main/java/org/apache/wicket/atmosphere/jquery.atmosphere.js
index 2b17666..b909609 100644
--- a/wicket-experimental/wicket-atmosphere/src/main/java/org/apache/wicket/atmosphere/jquery.atmosphere.js
+++ b/wicket-experimental/wicket-atmosphere/src/main/java/org/apache/wicket/atmosphere/jquery.atmosphere.js
@@ -28,19 +28,24 @@
/**
* Official documentation of this library: https://github.com/Atmosphere/atmosphere/wiki/jQuery.atmosphere.js-API
*/
-jQuery.atmosphere = function() {
- jQuery(window).bind("unload.atmosphere", function() {
+jQuery.atmosphere = function () {
+
+ jQuery(window).bind("unload.atmosphere", function () {
+ jQuery.atmosphere.unsubscribe();
+ });
+
+ jQuery(window).bind("offline", function () {
jQuery.atmosphere.unsubscribe();
});
// Prevent ESC to kill the connection from Firefox.
- jQuery(window).keypress(function(e){
- if(e.keyCode == 27){
+ jQuery(window).keypress(function (e) {
+ if (e.keyCode === 27) {
e.preventDefault();
}
});
- var parseHeaders = function(headerString) {
+ var parseHeaders = function (headerString) {
var match, rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, headers = {};
while (match = rheaders.exec(headerString)) {
headers[match[1]] = match[2];
@@ -49,106 +54,119 @@ jQuery.atmosphere = function() {
};
return {
- version : "1.0.13",
- requests : [],
- callbacks : [],
+ version: "2.0.3-jquery",
+ requests: [],
+ callbacks: [],
- onError : function(response) {
+ onError: function (response) {
+ },
+ onClose: function (response) {
},
- onClose : function(response) {
+ onOpen: function (response) {
},
- onOpen : function(response) {
+ onMessage: function (response) {
},
- onMessage : function(response) {
+ onReconnect: function (request, response) {
},
- onReconnect : function(request, response) {
+ onMessagePublished: function (response) {
},
- onMessagePublished : function(response) {
+ onTransportFailure: function (errorMessage, _request) {
},
- onTransportFailure : function (reason, request) {
+ onLocalMessage: function (response) {
},
- onLocalMessage : function (response) {
+ onClientTimeout: function(request){
+ },
+ onFailureToReconnect: function (request, response) {
},
- AtmosphereRequest : function(options) {
+ AtmosphereRequest: function (options) {
/**
* {Object} Request parameters.
+ *
* @private
*/
var _request = {
timeout: 300000,
method: 'GET',
headers: {},
- contentType : '',
+ contentType: '',
callback: null,
- url : '',
- data : '',
- suspend : true,
- maxRequest : -1,
- reconnect : true,
- maxStreamingLength : 10000000,
- lastIndex : 0,
- logLevel : 'info',
- requestCount : 0,
+ url: '',
+ data: '',
+ suspend: true,
+ maxRequest: -1,
+ reconnect: true,
+ maxStreamingLength: 10000000,
+ lastIndex: 0,
+ logLevel: 'info',
+ requestCount: 0,
fallbackMethod: 'GET',
- fallbackTransport : 'streaming',
- transport : 'long-polling',
+ fallbackTransport: 'streaming',
+ transport: 'long-polling',
webSocketImpl: null,
- webSocketUrl: null,
+ webSocketBinaryType: null,
+ dispatchUrl: null,
webSocketPathDelimiter: "@@",
- enableXDR : false,
- rewriteURL : false,
- attachHeadersAsQueryString : true,
- executeCallbackBeforeReconnect : false,
- readyState : 0,
- lastTimestamp : 0,
- withCredentials : false,
- trackMessageLength : false ,
- messageDelimiter : '|',
- connectTimeout : -1,
- reconnectInterval : 0,
- dropAtmosphereHeaders : true,
- uuid : 0,
- shared : false,
- readResponsesHeaders : true,
+ enableXDR: false,
+ rewriteURL: false,
+ attachHeadersAsQueryString: true,
+ executeCallbackBeforeReconnect: false,
+ readyState: 0,
+ lastTimestamp: 0,
+ withCredentials: false,
+ trackMessageLength: false,
+ messageDelimiter: '|',
+ connectTimeout: -1,
+ reconnectInterval: 0,
+ dropAtmosphereHeaders: true,
+ uuid: 0,
+ shared: false,
+ readResponsesHeaders: false,
maxReconnectOnClose: 5,
- enableProtocol: false,
- onError : function(response) {
+ enableProtocol: true,
+ onError: function (response) {
+ },
+ onClose: function (response) {
+ },
+ onOpen: function (response) {
},
- onClose : function(response) {
+ onMessage: function (response) {
},
- onOpen : function(response) {
+ onReopen: function (request, response) {
},
- onMessage : function(response) {
+ onReconnect: function (request, response) {
},
- onReconnect : function(request, response) {
+ onMessagePublished: function (response) {
},
- onMessagePublished : function(response) {
+ onTransportFailure: function (reason, request) {
},
- onTransportFailure : function (reason, request) {
+ onLocalMessage: function (request) {
},
- onLocalMessage : function (request) {
+ onFailureToReconnect: function (request, response) {
+ },
+ onClientTimeout: function(request){
}
};
/**
* {Object} Request's last response.
+ *
* @private
*/
var _response = {
status: 200,
- reasonPhrase : "OK",
- responseBody : '',
- messages : [],
- headers : [],
- state : "messageReceived",
- transport : "polling",
+ reasonPhrase: "OK",
+ responseBody: '',
+ messages: [],
+ headers: [],
+ state: "messageReceived",
+ transport: "polling",
error: null,
- request : null,
- partialMessage : "",
+ request: null,
+ partialMessage: "",
errorHandled: false,
- id : 0
+ id: 0
};
/**
@@ -166,8 +184,7 @@ jQuery.atmosphere = function() {
var _sse = null;
/**
- * {XMLHttpRequest, ActiveXObject} Opened ajax request (in case of
- * http-streaming or long-polling)
+ * {XMLHttpRequest, ActiveXObject} Opened ajax request (in case of http-streaming or long-polling)
*
* @private
*/
@@ -210,24 +227,28 @@ jQuery.atmosphere = function() {
/**
* A local "channel' of communication.
+ *
* @private
*/
var _localSocketF = null;
/**
* The storage used.
+ *
* @private
*/
var _storageService;
/**
* Local communication
+ *
* @private
*/
var _localStorageService = null;
/**
* A Unique ID
+ *
* @private
*/
var guid = jQuery.now();
@@ -256,6 +277,7 @@ jQuery.atmosphere = function() {
/**
* Re-initialize atmosphere object.
+ *
* @private
*/
function _reinit() {
@@ -267,8 +289,7 @@ jQuery.atmosphere = function() {
* Subscribe request using request transport. <br>
* If request is currently opened, this one will be closed.
*
- * @param {Object}
- * Request parameters.
+ * @param {Object} Request parameters.
* @private
*/
function _subscribe(options) {
@@ -283,11 +304,9 @@ jQuery.atmosphere = function() {
}
/**
- * Check if web socket is supported (check for custom implementation
- * provided by request object or browser implementation).
+ * Check if web socket is supported (check for custom implementation provided by request object or browser implementation).
*
- * @returns {boolean} True if web socket is supported, false
- * otherwise.
+ * @returns {boolean} True if web socket is supported, false otherwise.
* @private
*/
function _supportWebsocket() {
@@ -295,11 +314,9 @@ jQuery.atmosphere = function() {
}
/**
- * Check if server side events (SSE) is supported (check for custom implementation
- * provided by request object or browser implementation).
+ * Check if server side events (SSE) is supported (check for custom implementation provided by request object or browser implementation).
*
- * @returns {boolean} True if web socket is supported, false
- * otherwise.
+ * @returns {boolean} True if web socket is supported, false otherwise.
* @private
*/
function _supportSSE() {
@@ -308,9 +325,7 @@ jQuery.atmosphere = function() {
/**
* Open request using request transport. <br>
- * If request transport is 'websocket' but websocket can't be
- * opened, request will automatically reconnect using fallback
- * transport.
+ * If request transport is 'websocket' but websocket can't be opened, request will automatically reconnect using fallback transport.
*
* @private
*/
@@ -319,7 +334,7 @@ jQuery.atmosphere = function() {
if (_request.shared) {
_localStorageService = _local(_request);
if (_localStorageService != null) {
- if (_request.logLevel == 'debug') {
+ if (_request.logLevel === 'debug') {
jQuery.atmosphere.debug("Storage service available. All communication will be local");
}
@@ -329,7 +344,7 @@ jQuery.atmosphere = function() {
}
}
- if (_request.logLevel == 'debug') {
+ if (_request.logLevel === 'debug') {
jQuery.atmosphere.debug("No Storage service available.");
}
// Wasn't local or an error occurred
@@ -337,25 +352,24 @@ jQuery.atmosphere = function() {
}
// Protocol
- _request.firstMessage= true;
+ _request.firstMessage = true;
+ _request.isOpen = false;
_request.ctime = jQuery.now();
- if (_request.transport != 'websocket' && _request.transport != 'sse') {
- // Gives a chance to the connection to be established before calling the callback
- setTimeout(function() {
- _open('opening', _request.transport, _request);
- }, 500);
- _executeRequest();
+ if (_request.transport !== 'websocket' && _request.transport !== 'sse') {
+ _executeRequest(_request);
- } else if (_request.transport == 'websocket') {
+ } else if (_request.transport === 'websocket') {
if (!_supportWebsocket()) {
- _reconnectWithFallbackTransport("Websocket is not supported, using request.fallbackTransport (" + _request.fallbackTransport + ")");
+ _reconnectWithFallbackTransport("Websocket is not supported, using request.fallbackTransport (" + _request.fallbackTransport
+ + ")");
} else {
_executeWebSocket(false);
}
- } else if (_request.transport == 'sse') {
+ } else if (_request.transport === 'sse') {
if (!_supportSSE()) {
- _reconnectWithFallbackTransport("Server Side Events(SSE) is not supported, using request.fallbackTransport (" + _request.fallbackTransport + ")");
+ _reconnectWithFallbackTransport("Server Side Events(SSE) is not supported, using request.fallbackTransport ("
+ + _request.fallbackTransport + ")");
} else {
_executeSSE(false);
}
@@ -364,23 +378,21 @@ jQuery.atmosphere = function() {
function _local(request) {
var trace, connector, orphan, name = "atmosphere-" + request.url, connectors = {
- storage: function() {
+ storage: function () {
if (!jQuery.atmosphere.supportStorage()) {
return;
}
- var storage = window.localStorage,
- get = function(key) {
- return jQuery.parseJSON(storage.getItem(name + "-" + key));
- },
- set = function(key, value) {
- storage.setItem(name + "-" + key, jQuery.stringifyJSON(value));
- };
+ var storage = window.localStorage, get = function (key) {
+ return jQuery.parseJSON(storage.getItem(name + "-" + key));
+ }, set = function (key, value) {
+ storage.setItem(name + "-" + key, jQuery.stringifyJSON(value));
+ };
return {
- init: function() {
+ init: function () {
set("children", get("children").concat([guid]));
- jQuery(window).on("storage.socket", function(event) {
+ jQuery(window).on("storage.socket", function (event) {
event = event.originalEvent;
if (event.key === name && event.newValue) {
listener(event.newValue);
@@ -388,10 +400,14 @@ jQuery.atmosphere = function() {
});
return get("opened");
},
- signal: function(type, data) {
- storage.setItem(name, jQuery.stringifyJSON({target: "p", type: type, data: data}));
+ signal: function (type, data) {
+ storage.setItem(name, jQuery.stringifyJSON({
+ target: "p",
+ type: type,
+ data: data
+ }));
},
- close: function() {
+ close: function () {
var index, children = get("children");
jQuery(window).off("storage.socket");
@@ -405,7 +421,7 @@ jQuery.atmosphere = function() {
}
};
},
- windowref: function() {
+ windowref: function () {
var win = window.open("", name.replace(/\W/g, ""));
if (!win || win.closed || !win.callbacks) {
@@ -413,17 +429,21 @@ jQuery.atmosphere = function() {
}
return {
- init: function() {
+ init: function () {
win.callbacks.push(listener);
win.children.push(guid);
return win.opened;
},
- signal: function(type, data) {
+ signal: function (type, data) {
if (!win.closed && win.fire) {
- win.fire(jQuery.stringifyJSON({target: "p", type: type, data: data}));
+ win.fire(jQuery.stringifyJSON({
+ target: "p",
+ type: type,
+ data: data
+ }));
}
},
- close : function() {
+ close: function () {
function remove(array, e) {
var index = jQuery.inArray(e, array);
if (index > -1) {
@@ -449,7 +469,7 @@ jQuery.atmosphere = function() {
if (command.target === "c") {
switch (command.type) {
case "open":
- _open("opening", 'local', _request)
+ _open("opening", 'local', _request);
break;
case "close":
if (!orphan) {
@@ -461,7 +481,7 @@ jQuery.atmosphere = function() {
if (data.heir === guid) {
_execute();
} else {
- setTimeout(function() {
+ setTimeout(function () {
_execute();
}, 100);
}
@@ -498,35 +518,45 @@ jQuery.atmosphere = function() {
}
return {
- open: function() {
+ open: function () {
var parentOpened;
// Checks the shared one is alive
- _traceTimer = setInterval(function() {
+ _traceTimer = setInterval(function () {
var oldTrace = trace;
trace = findTrace();
if (!trace || oldTrace.ts === trace.ts) {
// Simulates a close signal
- listener(jQuery.stringifyJSON({target: "c", type: "close", data: {reason: "error", heir: oldTrace.heir}}));
+ listener(jQuery.stringifyJSON({
+ target: "c",
+ type: "close",
+ data: {
+ reason: "error",
+ heir: oldTrace.heir
+ }
+ }));
}
}, 1000);
parentOpened = connector.init();
if (parentOpened) {
// Firing the open event without delay robs the user of the opportunity to bind connecting event handlers
- setTimeout(function() {
- _open("opening", 'local', request)
+ setTimeout(function () {
+ _open("opening", 'local', request);
}, 50);
}
return parentOpened;
},
- send: function(event) {
+ send: function (event) {
connector.signal("send", event);
},
- localSend: function(event) {
- connector.signal("localSend", jQuery.stringifyJSON({id: guid , event: event}));
+ localSend: function (event) {
+ connector.signal("localSend", jQuery.stringifyJSON({
+ id: guid,
+ event: event
+ }));
},
- close: function() {
+ close: function () {
// Do not signal the parent if this method is executed by the unload event handler
if (!_abordingConnection) {
clearInterval(_traceTimer);
@@ -535,13 +565,13 @@ jQuery.atmosphere = function() {
}
}
};
- };
+ }
function share() {
var storageService, name = "atmosphere-" + _request.url, servers = {
// Powered by the storage event and the localStorage
// http://www.w3.org/TR/webstorage/#event-storage
- storage: function() {
+ storage: function () {
if (!jQuery.atmosphere.supportStorage()) {
return;
}
@@ -549,9 +579,9 @@ jQuery.atmosphere = function() {
var storage = window.localStorage;
return {
- init: function() {
+ init: function () {
// Handles the storage event
- jQuery(window).on("storage.socket", function(event) {
+ jQuery(window).on("storage.socket", function (event) {
event = event.originalEvent;
// When a deletion, newValue initialized to null
if (event.key === name && event.newValue) {
@@ -559,16 +589,20 @@ jQuery.atmosphere = function() {
}
});
},
- signal: function(type, data) {
- storage.setItem(name, jQuery.stringifyJSON({target: "c", type: type, data: data}));
+ signal: function (type, data) {
+ storage.setItem(name, jQuery.stringifyJSON({
+ target: "c",
+ type: type,
+ data: data
+ }));
},
- get: function(key) {
+ get: function (key) {
return jQuery.parseJSON(storage.getItem(name + "-" + key));
},
- set: function(key, value) {
+ set: function (key, value) {
storage.setItem(name + "-" + key, jQuery.stringifyJSON(value));
},
- close : function() {
+ close: function () {
jQuery(window).off("storage.socket");
storage.removeItem(name);
storage.removeItem(name + "-opened");
@@ -579,18 +613,18 @@ jQuery.atmosphere = function() {
},
// Powered by the window.open method
// https://developer.mozilla.org/en/DOM/window.open
- windowref: function() {
+ windowref: function () {
// Internet Explorer raises an invalid argument error
// when calling the window.open method with the name containing non-word characters
- var neim = name.replace(/\W/g, ""), win = (jQuery('iframe[name="' + neim + '"]')[0]
- || jQuery('<iframe name="' + neim + '" />').hide().appendTo("body")[0]).contentWindow;
+ var neim = name.replace(/\W/g, ""), win = (jQuery('iframe[name="' + neim + '"]')[0] || jQuery(
+ '<iframe name="' + neim + '" />').hide().appendTo("body")[0]).contentWindow;
return {
- init: function() {
+ init: function () {
// Callbacks from different windows
win.callbacks = [listener];
// In IE 8 and less, only string argument can be safely passed to the function in other window
- win.fire = function(string) {
+ win.fire = function (string) {
var i;
for (i = 0; i < win.callbacks.length; i++) {
@@ -598,25 +632,29 @@ jQuery.atmosphere = function() {
}
};
},
- signal: function(type, data) {
+ signal: function (type, data) {
if (!win.closed && win.fire) {
- win.fire(jQuery.stringifyJSON({target: "c", type: type, data: data}));
+ win.fire(jQuery.stringifyJSON({
+ target: "c",
+ type: type,
+ data: data
+ }));
}
},
- get: function(key) {
+ get: function (key) {
return !win.closed ? win[key] : null;
},
- set: function(key, value) {
+ set: function (key, value) {
if (!win.closed) {
win[key] = value;
}
},
- close : function() {}
+ close: function () {
+ }
};
}
};
-
// Receives send and close command from the children
function listener(string) {
var command = jQuery.parseJSON(string), data = command.data;
@@ -638,20 +676,23 @@ jQuery.atmosphere = function() {
_localSocketF = function propagateMessageEvent(context) {
storageService.signal("message", context);
- }
+ };
function leaveTrace() {
document.cookie = encodeURIComponent(name) + "=" +
// Opera's JSON implementation ignores a number whose a last digit of 0 strangely
// but has no problem with a number whose a last digit of 9 + 1
- encodeURIComponent(jQuery.stringifyJSON({ts: jQuery.now() + 1, heir: (storageService.get("children") || [])[0]}));
+ encodeURIComponent(jQuery.stringifyJSON({
+ ts: jQuery.now() + 1,
+ heir: (storageService.get("children") || [])[0]
+ }));
}
// Chooses a storageService
storageService = servers.storage() || servers.windowref();
storageService.init();
- if (_request.logLevel == 'debug') {
+ if (_request.logLevel === 'debug') {
jQuery.atmosphere.debug("Installed StorageService " + storageService);
}
@@ -673,7 +714,7 @@ jQuery.atmosphere = function() {
* @private
*/
function _open(state, transport, request) {
- if (_request.shared && transport != 'local') {
+ if (_request.shared && transport !== 'local') {
share();
}
@@ -681,15 +722,17 @@ jQuery.atmosphere = function() {
_storageService.set("opened", true);
}
- request.close = function() {
+ request.close = function () {
_close();
};
- if (_response.error == null) {
+ if (_requestCount > 0 && state === 're-connecting') {
+ request.isReopen = true;
+ _tryingToReconnect(_response);
+ } else if (_response.error == null) {
_response.request = request;
var prevState = _response.state;
_response.state = state;
- _response.status = 200;
var prevTransport = _response.transport;
_response.transport = transport;
@@ -705,54 +748,56 @@ jQuery.atmosphere = function() {
/**
* Execute request using jsonp transport.
*
- * @param request
- * {Object} request Request parameters, if
- * undefined _request object will be used.
+ * @param request {Object} request Request parameters, if undefined _request object will be used.
* @private
*/
function _jsonp(request) {
// When CORS is enabled, make sure we force the proper transport.
- request.transport="jsonp";
+ request.transport = "jsonp";
var rq = _request;
- if ((request != null) && (typeof(request) != 'undefined')) {
+ if ((request != null) && (typeof (request) !== 'undefined')) {
rq = request;
}
var url = rq.url;
+ if (rq.dispatchUrl != null) {
+ url += rq.dispatchUrl;
+ }
+
var data = rq.data;
if (rq.attachHeadersAsQueryString) {
url = _attachHeaders(rq);
- if (data != '') {
+ if (data !== '') {
url += "&X-Atmosphere-Post-Body=" + encodeURIComponent(data);
}
data = '';
}
_jqxhr = jQuery.ajax({
- url : url,
- type : rq.method,
+ url: url,
+ type: rq.method,
dataType: "jsonp",
- error : function(jqXHR, textStatus, errorThrown) {
+ error: function (jqXHR, textStatus, errorThrown) {
_response.error = true;
- if (jqXHR.status < 300 && rq.reconnect && _requestCount++ < rq.maxReconnectOnClose) {
- _reconnect(_jqxhr, rq);
+ if (jqXHR.status < 300) {
+ _reconnect(_jqxhr, rq, 0);
} else {
_onError(jqXHR.status, errorThrown);
}
},
- jsonp : "jsonpTransport",
- success: function(json) {
+ jsonp: "jsonpTransport",
+ success: function (json) {
if (rq.reconnect) {
- if (rq.maxRequest == -1 || rq.requestCount++ < rq.maxRequest) {
+ if (rq.maxRequest === -1 || rq.requestCount++ < rq.maxRequest) {
_readHeaders(_jqxhr, rq);
if (!rq.executeCallbackBeforeReconnect) {
- _reconnect(_jqxhr, rq);
+ _reconnect(_jqxhr, rq, 0);
}
var msg = json.message;
- if (msg != null && typeof msg != 'string') {
+ if (msg != null && typeof msg !== 'string') {
try {
msg = jQuery.stringifyJSON(msg);
} catch (err) {
@@ -760,12 +805,13 @@ jQuery.atmosphere = function() {
}
}
- if (_handleProtocol(rq, msg)) {
- _prepareCallback(msg, "messageReceived", 200, rq.transport);
+ var skipCallbackInvocation = _trackMessageSize(msg, rq, _response);
+ if (!skipCallbackInvocation) {
+ _prepareCallback(_response.responseBody, "messageReceived", 200, rq.transport);
}
if (rq.executeCallbackBeforeReconnect) {
- _reconnect(_jqxhr, rq);
+ _reconnect(_jqxhr, rq, 0);
}
} else {
jQuery.atmosphere.log(_request.logLevel, ["JSONP reconnect maximum try reached " + _request.requestCount]);
@@ -773,8 +819,8 @@ jQuery.atmosphere = function() {
}
}
},
- data : rq.data,
- beforeSend : function(jqXHR) {
+ data: rq.data,
+ beforeSend: function (jqXHR) {
_doRequest(jqXHR, rq, false);
}
});
@@ -783,32 +829,34 @@ jQuery.atmosphere = function() {
/**
* Execute request using ajax transport.
*
- * @param request
- * {Object} request Request parameters, if
- * undefined _request object will be used.
+ * @param request {Object} request Request parameters, if undefined _request object will be used.
* @private
*/
function _ajax(request) {
var rq = _request;
- if ((request != null) && (typeof(request) != 'undefined')) {
+ if ((request != null) && (typeof (request) !== 'undefined')) {
rq = request;
}
var url = rq.url;
+ if (rq.dispatchUrl != null) {
+ url += rq.dispatchUrl;
+ }
+
var data = rq.data;
if (rq.attachHeadersAsQueryString) {
url = _attachHeaders(rq);
- if (data != '') {
+ if (data !== '') {
url += "&X-Atmosphere-Post-Body=" + encodeURIComponent(data);
}
data = '';
}
- var async = typeof(rq.async) != 'undefined' ? rq.async : true;
+ var async = typeof (rq.async) !== 'undefined' ? rq.async : true;
_jqxhr = jQuery.ajax({
- url : url,
- type : rq.method,
- error : function(jqXHR, textStatus, errorThrown) {
+ url: url,
+ type: rq.method,
+ error: function (jqXHR, textStatus, errorThrown) {
_response.error = true;
if (jqXHR.status < 300) {
_reconnect(_jqxhr, rq);
@@ -816,20 +864,20 @@ jQuery.atmosphere = function() {
_onError(jqXHR.status, errorThrown);
}
},
- success: function(data, textStatus, jqXHR) {
+ success: function (data, textStatus, jqXHR) {
if (rq.reconnect) {
- if (rq.maxRequest == -1 || rq.requestCount++ < rq.maxRequest) {
+ if (rq.maxRequest === -1 || rq.requestCount++ < rq.maxRequest) {
if (!rq.executeCallbackBeforeReconnect) {
- _reconnect(_jqxhr, rq);
+ _reconnect(_jqxhr, rq, 0);
}
-
- if (_handleProtocol(rq, data)) {
- _prepareCallback(data, "messageReceived", 200, rq.transport);
+ var skipCallbackInvocation = _trackMessageSize(data, rq, _response);
+ if (!skipCallbackInvocation) {
+ _prepareCallback(_response.responseBody, "messageReceived", 200, rq.transport);
}
if (rq.executeCallbackBeforeReconnect) {
- _reconnect(_jqxhr, rq);
+ _reconnect(_jqxhr, rq, 0);
}
} else {
jQuery.atmosphere.log(_request.logLevel, ["AJAX reconnect maximum try reached " + _request.requestCount]);
@@ -837,10 +885,10 @@ jQuery.atmosphere = function() {
}
}
},
- beforeSend : function(jqXHR) {
+ beforeSend: function (jqXHR) {
_doRequest(jqXHR, rq, false);
},
- crossDomain : rq.enableXDR,
+ crossDomain: rq.enableXDR,
async: async
});
}
@@ -848,8 +896,7 @@ jQuery.atmosphere = function() {
/**
* Build websocket object.
*
- * @param location
- * {string} Web socket url.
+ * @param location {string} Web socket url.
* @returns {websocket} Web socket object.
* @private
*/
@@ -868,8 +915,7 @@ jQuery.atmosphere = function() {
/**
* Build web socket url from request url.
*
- * @return {string} Web socket url (start with "ws" or "wss" for
- * secure web socket).
+ * @return {string} Web socket url (start with "ws" or "wss" for secure web socket).
* @private
*/
function _buildWebSocketUrl() {
@@ -891,8 +937,7 @@ jQuery.atmosphere = function() {
/**
* Open SSE. <br>
- * Automatically use fallback transport if SSE can't be
- * opened.
+ * Automatically use fallback transport if SSE can't be opened.
*
* @private
*/
@@ -902,15 +947,11 @@ jQuery.atmosphere = function() {
var location = _buildSSEUrl(_request.url);
- if (_request.logLevel == 'debug') {
+ if (_request.logLevel === 'debug') {
jQuery.atmosphere.debug("Invoking executeSSE");
jQuery.atmosphere.debug("Using URL: " + location);
}
- if (sseOpened) {
- _open('re-opening', "sse", _request);
- }
-
if (_request.enableProtocol && sseOpened) {
var time = jQuery.now() - _request.ctime;
_request.lastTimestamp = Number(_request.stime) + Number(time);
@@ -924,7 +965,9 @@ jQuery.atmosphere = function() {
}
try {
- _sse = new EventSource(location, {withCredentials: _request.withCredentials});
+ _sse = new EventSource(location, {
+ withCredentials: _request.withCredentials
+ });
} catch (e) {
_onError(0, e);
_reconnectWithFallbackTransport("SSE failed. Downgrading to fallback transport and resending");
@@ -932,43 +975,46 @@ jQuery.atmosphere = function() {
}
if (_request.connectTimeout > 0) {
- _request.id = setTimeout(function() {
+ _request.id = setTimeout(function () {
if (!sseOpened) {
_clearState();
}
}, _request.connectTimeout);
}
- _sse.onopen = function(event) {
- if (_request.logLevel == 'debug') {
+ _sse.onopen = function (event) {
+ _timeout(_request);
+ if (_request.logLevel === 'debug') {
jQuery.atmosphere.debug("SSE successfully opened");
}
- if (!sseOpened) {
- _open('opening', "sse", _request);
+ if (!_request.enableProtocol) {
+ if (!sseOpened) {
+ _open('opening', "sse", _request);
+ } else {
+ _open('re-opening', "sse", _request);
+ }
}
sseOpened = true;
- if (_request.method == 'POST') {
+ if (_request.method === 'POST') {
_response.state = "messageReceived";
_sse.send(_request.data);
}
};
- _sse.onmessage = function(message) {
- if (message.origin != window.location.protocol + "//" + window.location.host) {
+ _sse.onmessage = function (message) {
+ _timeout(_request);
+ if (!_request.enableXDR && message.origin !== window.location.protocol + "//" + window.location.host) {
jQuery.atmosphere.log(_request.logLevel, ["Origin was not " + window.location.protocol + "//" + window.location.host]);
return;
}
- var data = message.data;
-
- if (!_handleProtocol(_request, data)) return;
-
_response.state = 'messageReceived';
_response.status = 200;
- var skipCallbackInvocation = _trackMessageSize(data, _request, _response);
+ message = message.data;
+ var skipCallbackInvocation = _trackMessageSize(message, _request, _response);
if (!skipCallbackInvocation) {
_invokeCallback();
_response.responseBody = '';
@@ -976,9 +1022,11 @@ jQuery.atmosphere = function() {
}
};
- _sse.onerror = function(message) {
-
+ _sse.onerror = function (message) {
clearTimeout(_request.id);
+
+ if (_response.state === 'closedByClient') return;
+
_invokeClose(sseOpened);
_clearState();
@@ -986,11 +1034,16 @@ jQuery.atmosphere = function() {
jQuery.atmosphere.log(_request.logLevel, ["SSE closed normally"]);
} else if (!sseOpened) {
_reconnectWithFallbackTransport("SSE failed. Downgrading to fallback transport and resending");
- } else if (_request.reconnect && (_response.transport == 'sse')) {
+ } else if (_request.reconnect && (_response.transport === 'sse')) {
if (_requestCount++ < _request.maxReconnectOnClose) {
- _request.id = setTimeout(function() {
+ _open('re-connecting', _request.transport, _request);
+ if (_request.reconnectInterval > 0) {
+ _request.id = setTimeout(function () {
+ _executeSSE(true);
+ }, _request.reconnectInterval);
+ } else {
_executeSSE(true);
- }, _request.reconnectInterval);
+ }
_response.responseBody = "";
_response.messages = [];
} else {
@@ -1003,8 +1056,7 @@ jQuery.atmosphere = function() {
/**
* Open web socket. <br>
- * Automatically use fallback transport if web socket can't be
- * opened.
+ * Automatically use fallback transport if web socket can't be opened.
*
* @private
*/
@@ -1018,17 +1070,11 @@ jQuery.atmosphere = function() {
}
var location = _buildWebSocketUrl(_request.url);
- var closed = false;
-
- if (_request.logLevel == 'debug') {
+ if (_request.logLevel === 'debug') {
jQuery.atmosphere.debug("Invoking executeWebSocket");
jQuery.atmosphere.debug("Using URL: " + location);
}
- if (webSocketOpened) {
- _open('re-opening', "websocket", _request);
- }
-
if (webSocketOpened && !_request.reconnect) {
if (_websocket != null) {
_clearState();
@@ -1037,13 +1083,17 @@ jQuery.atmosphere = function() {
}
_websocket = _getWebSocket(location);
+ if (_request.webSocketBinaryType != null) {
+ _websocket.binaryType = _request.webSocketBinaryType;
+ }
+
if (_request.connectTimeout > 0) {
- _request.id = setTimeout(function() {
+ _request.id = setTimeout(function () {
if (!webSocketOpened) {
var _message = {
- code : 1002,
- reason : "",
- wasClean : false
+ code: 1002,
+ reason: "",
+ wasClean: false
};
_websocket.onclose(_message);
// Close it anyway
@@ -1057,83 +1107,84 @@ jQuery.atmosphere = function() {
}, _request.connectTimeout);
}
- _request.id = setTimeout(function() {
- setTimeout(function () {
- _clearState();
- }, _request.reconnectInterval)
- }, _request.timeout);
-
- _websocket.onopen = function(message) {
- if (_request.logLevel == 'debug') {
+ _websocket.onopen = function (message) {
+ _timeout(_request);
+ if (_request.logLevel === 'debug') {
jQuery.atmosphere.debug("Websocket successfully opened");
}
- if (!webSocketOpened) {
- _open('opening', "websocket", _request);
+ if (!_request.enableProtocol) {
+ if (!webSocketOpened) {
+ _open('opening', "websocket", _request);
+ } else {
+ _open('re-opening', "websocket", _request);
+ }
}
webSocketOpened = true;
- _websocket.webSocketOpened = webSocketOpened;
+ if (_websocket != null) {
+ _websocket.webSocketOpened = webSocketOpened;
- if (_request.method == 'POST') {
- _response.state = "messageReceived";
- _websocket.send(_request.data);
+ if (_request.method === 'POST') {
+ _response.state = "messageReceived";
+ _websocket.send(_request.data);
+ }
}
};
- _websocket.onmessage = function(message) {
-
- clearTimeout(_request.id);
- _request.id = setTimeout(function() {
- setTimeout(function () {
- _clearState();
- }, _request.reconnectInterval)
- }, _request.timeout);
-
- var data = message.data;
-
- if (!_handleProtocol(_request, data)) return;
+ _websocket.onmessage = function (message) {
+ _timeout(_request);
_response.state = 'messageReceived';
_response.status = 200;
- var skipCallbackInvocation = _trackMessageSize(data, _request, _response);
- if (!skipCallbackInvocation) {
+ message = message.data;
+ var isString = typeof (message) === 'string';
+ if (isString) {
+ var skipCallbackInvocation = _trackMessageSize(message, _request, _response);
+ if (!skipCallbackInvocation) {
+ _invokeCallback();
+ _response.responseBody = '';
+ _response.messages = [];
+ }
+ } else {
+ if (!_handleProtocol(_request, message))
+ return;
+
+ _response.responseBody = message;
_invokeCallback();
- _response.responseBody = '';
- _response.messages = [];
+ _response.responseBody = null;
}
};
- _websocket.onerror = function(message) {
- clearTimeout(_request.id)
+ _websocket.onerror = function (message) {
+ clearTimeout(_request.id);
};
- _websocket.onclose = function(message) {
- if (closed) return
+ _websocket.onclose = function (message) {
+ if (_response.state === 'closed')
+ return;
clearTimeout(_request.id);
var reason = message.reason;
if (reason === "") {
switch (message.code) {
case 1000:
- reason = "Normal closure; the connection successfully completed whatever purpose for which " +
- "it was created.";
+ reason = "Normal closure; the connection successfully completed whatever purpose for which " + "it was created.";
break;
case 1001:
- reason = "The endpoint is going away, either because of a server failure or because the " +
- "browser is navigating away from the page that opened the connection.";
+ reason = "The endpoint is going away, either because of a server failure or because the "
+ + "browser is navigating away from the page that opened the connection.";
break;
case 1002:
reason = "The endpoint is terminating the connection due to a protocol error.";
break;
case 1003:
- reason = "The connection is being terminated because the endpoint received data of a type it " +
- "cannot accept (for example, a text-only endpoint received binary data).";
+ reason = "The connection is being terminated because the endpoint received data of a type it "
+ + "cannot accept (for example, a text-only endpoint received binary data).";
break;
case 1004:
- reason = "The endpoint is terminating the connection because a data frame was received that " +
- "is too large.";
+ reason = "The endpoint is terminating the connection because a data frame was received that " + "is too large.";
break;
case 1005:
reason = "Unknown: no status code was provided even though one was expected.";
@@ -1144,94 +1195,151 @@ jQuery.atmosphere = function() {
}
}
- jQuery.atmosphere.warn("Websocket closed, reason: " + reason);
- jQuery.atmosphere.warn("Websocket closed, wasClean: " + message.wasClean);
+ if (_request.logLevel === 'warn') {
+ jQuery.atmosphere.warn("Websocket closed, reason: " + reason);
+ jQuery.atmosphere.warn("Websocket closed, wasClean: " + message.wasClean);
+ }
+
+ if (_response.state === 'closedByClient') {
+ return;
+ }
_invokeClose(webSocketOpened);
- closed = true;
+
+ _response.state = 'closed';
if (_abordingConnection) {
jQuery.atmosphere.log(_request.logLevel, ["Websocket closed normally"]);
} else if (!webSocketOpened) {
_reconnectWithFallbackTransport("Websocket failed. Downgrading to Comet and resending");
- } else if (_request.reconnect && _response.transport == 'websocket') {
+ } else if (_request.reconnect && _response.transport === 'websocket') {
_clearState();
- if (_request.reconnect && _requestCount++ < _request.maxReconnectOnClose) {
- _request.id = setTimeout(function() {
+ if (_requestCount++ < _request.maxReconnectOnClose) {
+ _open('re-connecting', _request.transport, _request);
+ if (_request.reconnectInterval > 0) {
+ _request.id = setTimeout(function () {
+ _response.responseBody = "";
+ _response.messages = [];
+ _executeWebSocket(true);
+ }, _request.reconnectInterval);
+ } else {
_response.responseBody = "";
_response.messages = [];
_executeWebSocket(true);
- }, _request.reconnectInterval);
+ }
} else {
- jQuery.atmosphere.log(_request.logLevel, ["Websocket reconnect maximum try reached " + _requestCount]);
- jQuery.atmosphere.warn("Websocket error, reason: " + message.reason);
+ jQuery.atmosphere.log(_request.logLevel, ["Websocket reconnect maximum try reached " + _request.requestCount]);
+ if (_request.logLevel === 'warn') {
+ jQuery.atmosphere.warn("Websocket error, reason: " + message.reason);
+ }
_onError(0, "maxReconnectOnClose reached");
}
}
};
+
+ if (_websocket.url === undefined) {
+ // Android 4.1 does not really support websockets and fails silently
+ _websocket.onclose({
+ reason: "Android 4.1 does not support websockets.",
+ wasClean: false
+ });
+ }
}
function _handleProtocol(request, message) {
// The first messages is always the uuid.
- if (jQuery.trim(message) != 0 && request.enableProtocol && request.firstMessage) {
- request.firstMessage = false;
- var messages = message.split(request.messageDelimiter);
- var pos = messages.length == 2 ? 0 : 1;
+ var b = true;
+ if (jQuery.trim(message).length !== 0 && request.enableProtocol && request.firstMessage) {
+ request.firstMessage = false;
+ var messages = message.split(request.messageDelimiter);
+ var pos = messages.length === 2 ? 0 : 1;
request.uuid = jQuery.trim(messages[pos]);
request.stime = jQuery.trim(messages[pos + 1]);
- return false;
+ b = false;
+ if (request.transport !== 'long-polling') {
+ _triggerOpen(request);
+ }
+ } else if (request.enableProtocol && request.firstMessage) {
+ // In case we are getting some junk from IE
+ b = false;
+ } else {
+ _triggerOpen(request);
}
- return true;
+ return b;
+ }
+
+ function _timeout(_request) {
+ clearTimeout(_request.id);
+ if (_request.timeout > 0 && _request.transport !== 'polling') {
+ _request.id = setTimeout(function () {
+ _onClientTimeout(_request);
+ _disconnect();
+ _clearState();
+ }, _request.timeout);
+ }
+ }
+
+ function _onClientTimeout(_request) {
+ _response.state = 'closedByClient';
+ _response.responseBody = "";
+ _response.status = 408;
+ _response.messages = [];
+ _invokeCallback();
}
function _onError(code, reason) {
_clearState();
-
+ clearTimeout(_request.id);
_response.state = 'error';
_response.reasonPhrase = reason;
_response.responseBody = "";
- _response.messages = [];
_response.status = code;
+ _response.messages = [];
_invokeCallback();
}
/**
- * Track received message and make sure callbacks/functions are only invoked when the complete message
- * has been received.
+ * Track received message and make sure callbacks/functions are only invoked when the complete message has been received.
*
* @param message
* @param request
* @param response
*/
function _trackMessageSize(message, request, response) {
- if (request.trackMessageLength) {
+ if (!_handleProtocol(_request, message))
+ return true;
+ if (message.length === 0)
+ return true;
- // If we have found partial message, prepend them.
- if (response.partialMessage.length != 0) {
- message = response.partialMessage + message;
- }
+ if (request.trackMessageLength) {
+ // prepend partialMessage if any
+ message = response.partialMessage + message;
var messages = [];
- var messageLength = 0;
var messageStart = message.indexOf(request.messageDelimiter);
- while (messageStart != -1) {
- messageLength = jQuery.trim(message.substring(messageLength, messageStart));
- message = message.substring(messageStart + request.messageDelimiter.length, message.length);
-
- if (message.length == 0 || message.length < messageLength) break;
-
- messageStart = message.indexOf(request.messageDelimiter);
- messages.push(message.substring(0, messageLength));
+ while (messageStart !== -1) {
+ var str = jQuery.trim(message.substring(0, messageStart));
+ var messageLength = parseInt(str, 10);
+ if (isNaN(messageLength))
+ throw 'message length "' + str + '" is not a number';
+ messageStart += request.messageDelimiter.length;
+ if (messageStart + messageLength > message.length) {
+ // message not complete, so there is no trailing messageDelimiter
+ messageStart = -1;
+ } else {
+ // message complete, so add it
+ messages.push(message.substring(messageStart, messageStart + messageLength));
+ // remove consumed characters
+ message = message.substring(messageStart + messageLength, message.length);
+ messageStart = message.indexOf(request.messageDelimiter);
+ }
}
- if (messages.length == 0 || (messageStart != -1 && message.length != 0 && messageLength != message.length)){
- response.partialMessage = messageLength + request.messageDelimiter + message ;
- } else {
- response.partialMessage = "";
- }
+ /* keep any remaining data */
+ response.partialMessage = message;
- if (messages.length != 0) {
+ if (messages.length !== 0) {
response.responseBody = messages.join(request.messageDelimiter);
response.messages = messages;
return false;
@@ -1255,21 +1363,25 @@ jQuery.atmosphere = function() {
function _reconnectWithFallbackTransport(errorMessage) {
jQuery.atmosphere.log(_request.logLevel, [errorMessage]);
- if (typeof(_request.onTransportFailure) != 'undefined') {
+ if (typeof (_request.onTransportFailure) !== 'undefined') {
_request.onTransportFailure(errorMessage, _request);
- } else if (typeof(jQuery.atmosphere.onTransportFailure) != 'undefined') {
+ } else if (typeof (jQuery.atmosphere.onTransportFailure) !== 'undefined') {
jQuery.atmosphere.onTransportFailure(errorMessage, _request);
}
_request.transport = _request.fallbackTransport;
- var reconnectInterval = _request.connectTimeout == -1 ? 0 : _request.connectTimeout;
- if (_request.reconnect && _request.transport != 'none' || _request.transport == null) {
+ var reconnectInterval = _request.connectTimeout === -1 ? 0 : _request.connectTimeout;
+ if (_request.reconnect && _request.transport !== 'none' || _request.transport == null) {
_request.method = _request.fallbackMethod;
_response.transport = _request.fallbackTransport;
_request.fallbackTransport = 'none';
- _request.id = setTimeout(function() {
+ if (reconnectInterval > 0) {
+ _request.id = setTimeout(function () {
+ _execute();
+ }, reconnectInterval);
+ } else {
_execute();
- }, reconnectInterval);
+ }
} else {
_onError(500, "Unable to reconnect with fallback transport");
}
@@ -1278,31 +1390,31 @@ jQuery.atmosphere = function() {
/**
* Get url from request and attach headers to it.
*
- * @param request
- * {Object} request Request parameters, if
- * undefined _request object will be used.
+ * @param request {Object} request Request parameters, if undefined _request object will be used.
*
- * @returns {Object} Request object, if undefined,
- * _request object will be used.
+ * @returns {Object} Request object, if undefined, _request object will be used.
* @private
*/
- function _attachHeaders(request) {
+ function _attachHeaders(request, url) {
var rq = _request;
- if ((request != null) && (typeof(request) != 'undefined')) {
+ if ((request != null) && (typeof (request) !== 'undefined')) {
rq = request;
}
- var url = rq.url;
+ if (url == null) {
+ url = rq.url;
+ }
// If not enabled
- if (!rq.attachHeadersAsQueryString) return url;
+ if (!rq.attachHeadersAsQueryString)
+ return url;
// If already added
- if (url.indexOf("X-Atmosphere-Framework") != -1) {
+ if (url.indexOf("X-Atmosphere-Framework") !== -1) {
return url;
}
- url += (url.indexOf('?') != -1) ? '&' : '?';
+ url += (url.indexOf('?') !== -1) ? '&' : '?';
url += "X-Atmosphere-tracking-id=" + rq.uuid;
url += "&X-Atmosphere-Framework=" + jQuery.atmosphere.version;
url += "&X-Atmosphere-Transport=" + rq.transport;
@@ -1311,21 +1423,21 @@ jQuery.atmosphere = function() {
url += "&X-Atmosphere-TrackMessageSize=" + "true";
}
- if (rq.lastTimestamp != undefined) {
+ if (rq.lastTimestamp != null) {
url += "&X-Cache-Date=" + rq.lastTimestamp;
} else {
url += "&X-Cache-Date=" + 0;
}
- if (rq.contentType != '') {
+ if (rq.contentType !== '') {
url += "&Content-Type=" + rq.contentType;
}
if (rq.enableProtocol) {
- url += "&X-atmo-protocol=true";
+ url += "&X-atmo-protocol=true";
}
- jQuery.each(rq.headers, function(name, value) {
+ jQuery.each(rq.headers, function (name, value) {
var h = jQuery.isFunction(value) ? value.call(this, rq, request, _response) : value;
if (h != null) {
url += "&" + encodeURIComponent(name) + "=" + encodeURIComponent(h);
@@ -1335,42 +1447,25 @@ jQuery.atmosphere = function() {
return url;
}
- /**
- * Build ajax request. <br>
- * Ajax Request is an XMLHttpRequest object, except for IE6 where
- * ajax request is an ActiveXObject.
- *
- * @return {XMLHttpRequest, ActiveXObject} Ajax request.
- * @private
- */
- function _buildAjaxRequest() {
- if (jQuery.browser.msie) {
- if (typeof XMLHttpRequest == "undefined")
- XMLHttpRequest = function () {
- try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); }
- catch (e) {}
- try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
- catch (e) {}
- try { return new ActiveXObject("Microsoft.XMLHTTP"); }
- catch (e) {}
- //Microsoft.XMLHTTP points to Msxml2.XMLHTTP and is redundant
- throw new Error("This browser does not support XMLHttpRequest.");
- };
- }
- return new XMLHttpRequest();
+ function _triggerOpen(rq) {
+ if (!rq.isOpen) {
+ rq.isOpen = true;
+ _open('opening', rq.transport, rq);
+ } else if (rq.isReopen) {
+ rq.isReopen = false;
+ _open('re-opening', rq.transport, rq);
+ }
}
/**
* Execute ajax request. <br>
*
- * @param request
- * {Object} request Request parameters, if
- * undefined _request object will be used.
+ * @param request {Object} request Request parameters, if undefined _request object will be used.
* @private
*/
function _executeRequest(request) {
var rq = _request;
- if ((request != null) || (typeof(request) != 'undefined')) {
+ if ((request != null) || (typeof (request) !== 'undefined')) {
rq = request;
}
@@ -1378,19 +1473,23 @@ jQuery.atmosphere = function() {
rq.readyState = 0;
// CORS fake using JSONP
- if ((rq.transport == 'jsonp') || ((rq.enableXDR) && (jQuery.atmosphere.checkCORSSupport()))) {
+ if ((rq.transport === 'jsonp') || ((rq.enableXDR) && (jQuery.atmosphere.checkCORSSupport()))) {
_jsonp(rq);
return;
}
- if (rq.transport == 'ajax') {
+ if (rq.transport === 'ajax') {
_ajax(request);
return;
}
if (jQuery.browser.msie && jQuery.browser.version < 10) {
- if ((rq.transport == 'streaming')) {
- rq.enableXDR && window.XDomainRequest ? _ieXDR(rq) : _ieStreaming(rq);
+ if ((rq.transport === 'streaming')) {
+ if (rq.enableXDR && window.XDomainRequest) {
+ _ieXDR(rq);
+ } else {
+ _ieStreaming(rq);
+ }
return;
}
@@ -1400,99 +1499,102 @@ jQuery.atmosphere = function() {
}
}
- var reconnectF = function() {
+ var reconnectF = function () {
+ rq.lastIndex = 0;
if (rq.reconnect && _requestCount++ < rq.maxReconnectOnClose) {
- _reconnect(ajaxRequest, rq, true);
+ _open('re-connecting', request.transport, request);
+ _reconnect(ajaxRequest, rq, request.reconnectInterval);
} else {
_onError(0, "maxReconnectOnClose reached");
}
};
- if (rq.reconnect && ( rq.maxRequest == -1 || rq.requestCount++ < rq.maxRequest)) {
- var ajaxRequest = _buildAjaxRequest();
+ if (rq.reconnect && (rq.maxRequest === -1 || rq.requestCount++ < rq.maxRequest)) {
+ var ajaxRequest = jQuery.ajaxSettings.xhr();
+ ajaxRequest.hasData = false;
+
_doRequest(ajaxRequest, rq, true);
if (rq.suspend) {
_activeRequest = ajaxRequest;
}
- if (rq.transport != 'polling') {
+ if (rq.transport !== 'polling') {
_response.transport = rq.transport;
- }
- ajaxRequest.onabort = function () {
- _invokeClose(true);
- };
+ ajaxRequest.onabort = function () {
+ _invokeClose(true);
+ };
- ajaxRequest.onerror = function() {
- _response.error = true;
- try {
- _response.status = XMLHttpRequest.status;
- } catch(e) {
- _response.status = 500;
- }
+ ajaxRequest.onerror = function () {
+ _response.error = true;
+ try {
+ _response.status = XMLHttpRequest.status;
+ } catch (e) {
+ _response.status = 500;
+ }
- if (!_response.status) {
- _response.status = 500;
- }
- _clearState();
- if (!_response.errorHandled) {
- reconnectF();
- }
- };
+ if (!_response.status) {
+ _response.status = 500;
+ }
+ _clearState();
+ if (!_response.errorHandled) {
+ reconnectF();
+ }
+ };
+ }
- ajaxRequest.onreadystatechange = function() {
+ ajaxRequest.onreadystatechange = function () {
if (_abordingConnection) {
return;
}
+
_response.error = null;
var skipCallbackInvocation = false;
var update = false;
-
- // Opera doesn't call onerror if the server disconnect.
- if (jQuery.browser.opera
- && rq.transport == 'streaming'
- && rq.readyState > 2
- && ajaxRequest.readyState == 4) {
-
- rq.readyState = 0;
- rq.lastIndex = 0;
-
+ if (rq.transport === 'streaming' && rq.readyState > 2 && ajaxRequest.readyState === 4) {
+ _clearState();
reconnectF();
return;
}
rq.readyState = ajaxRequest.readyState;
- if (rq.transport == 'streaming' && ajaxRequest.readyState >= 3) {
+ if (rq.transport === 'streaming' && ajaxRequest.readyState >= 3) {
update = true;
- } else if (rq.transport == 'long-polling' && ajaxRequest.readyState === 4) {
+ } else if (rq.transport === 'long-polling' && ajaxRequest.readyState === 4) {
update = true;
}
- clearTimeout(rq.id);
+ _timeout(_request);
- if (update) {
+ if (rq.transport !== 'polling') {
+ if ((!rq.enableProtocol || !request.firstMessage) && ajaxRequest.readyState === 2) {
+ _triggerOpen(rq);
+ }
// MSIE 9 and lower status can be higher than 1000, Chrome can be 0
- var status = 0;
- if (ajaxRequest.readyState != 0) {
+ var status = 200;
+ if (ajaxRequest.readyState > 1) {
status = ajaxRequest.status > 1000 ? 0 : ajaxRequest.status;
}
- if (status >= 300 || status == 0) {
+ if (status >= 300 || status === 0) {
// Prevent onerror callback to be called
_response.errorHandled = true;
_clearState();
reconnectF();
return;
}
+ }
+
+ if (update) {
var responseText = ajaxRequest.responseText;
- if (jQuery.trim(responseText.length) == 0 && rq.transport == 'long-polling') {
+ if (jQuery.trim(responseText.length).length === 0 && rq.transport === 'long-polling') {
// For browser that aren't support onabort
if (!ajaxRequest.hasData) {
reconnectF();
- } else {
+ } else {
ajaxRequest.hasData = false;
}
return;
@@ -1501,49 +1603,48 @@ jQuery.atmosphere = function() {
_readHeaders(ajaxRequest, _request);
- if (rq.transport == 'streaming') {
+ if (rq.transport === 'streaming') {
if (!jQuery.browser.opera) {
var message = responseText.substring(rq.lastIndex, responseText.length);
+ skipCallbackInvocation = _trackMessageSize(message, rq, _response);
+
rq.lastIndex = responseText.length;
- if (!_handleProtocol(_request, message)) {
+ if (skipCallbackInvocation) {
return;
}
- skipCallbackInvocation = _trackMessageSize(message, rq, _response);
} else {
jQuery.atmosphere.iterate(function () {
- if (_response.status != 500 && ajaxRequest.responseText.length > rq.lastIndex) {
+ if (_response.status !== 500 && ajaxRequest.responseText.length > rq.lastIndex) {
try {
_response.status = ajaxRequest.status;
- }
- catch (e) {
+ _response.headers = parseHeaders(ajaxRequest.getAllResponseHeaders());
+
+ _readHeaders(ajaxRequest, _request);
+
+ } catch (e) {
_response.status = 404;
}
- _response.state = "messageReceived";
+ _timeout(_request);
+ _response.state = "messageReceived";
var message = ajaxRequest.responseText.substring(rq.lastIndex);
rq.lastIndex = ajaxRequest.responseText.length;
- if (_handleProtocol(_request, message)) {
- skipCallbackInvocation = _trackMessageSize(message, rq, _response);
- if (!skipCallbackInvocation) {
- _invokeCallback();
- }
- _verifyStreamingLength(ajaxRequest, rq);
+ skipCallbackInvocation = _trackMessageSize(message, rq, _response);
+ if (!skipCallbackInvocation) {
+ _invokeCallback();
}
- } else if (_response.status > 400){
+
+ _verifyStreamingLength(ajaxRequest, rq);
+ } else if (_response.status > 400) {
+ // Prevent replaying the last message.
rq.lastIndex = ajaxRequest.responseText.length;
return false;
}
}, 0);
}
} else {
- if (!_handleProtocol( _request, responseText)) {
- _reconnect(ajaxRequest, rq, false);
- return;
- }
-
skipCallbackInvocation = _trackMessageSize(responseText, rq, _response);
- rq.lastIndex = responseText.length;
}
try {
@@ -1551,52 +1652,36 @@ jQuery.atmosphere = function() {
_response.headers = parseHeaders(ajaxRequest.getAllResponseHeaders());
_readHeaders(ajaxRequest, rq);
- } catch(e) {
+ } catch (e) {
_response.status = 404;
}
if (rq.suspend) {
- _response.state = _response.status == 0 ? "closed" : "messageReceived";
+ _response.state = _response.status === 0 ? "closed" : "messageReceived";
} else {
_response.state = "messagePublished";
}
- if (!rq.executeCallbackBeforeReconnect) {
- _reconnect(ajaxRequest, rq, false);
- }
-
- // For backward compatibility with Atmosphere < 0.8
- if (_response.responseBody.indexOf("parent.callback") != -1) {
- jQuery.atmosphere.log(rq.logLevel, ["parent.callback no longer supported with 0.8 version and up. Please upgrade"]);
+ var isAllowedToReconnect = request.transport !== 'streaming';
+ if (isAllowedToReconnect && !rq.executeCallbackBeforeReconnect) {
+ _reconnect(ajaxRequest, rq, 0);
}
- if (!skipCallbackInvocation) {
+ if (_response.responseBody.length !== 0 && !skipCallbackInvocation)
_invokeCallback();
- }
- if (rq.executeCallbackBeforeReconnect) {
- _reconnect(ajaxRequest, rq, false);
+ if (isAllowedToReconnect && rq.executeCallbackBeforeReconnect) {
+ _reconnect(ajaxRequest, rq, 0);
}
_verifyStreamingLength(ajaxRequest, rq);
}
};
- ajaxRequest.send(rq.data);
- if (rq.suspend) {
- rq.id = setTimeout(function() {
- if (_subscribed) {
- setTimeout(function () {
- _clearState();
- _executeRequest(rq);
- }, rq.reconnectInterval)
- }
- }, rq.timeout);
- }
+ ajaxRequest.send(rq.data);
_subscribed = true;
-
} else {
- if (rq.logLevel == 'debug') {
+ if (rq.logLevel === 'debug') {
jQuery.atmosphere.log(rq.logLevel, ["Max re-connection reached."]);
}
_onError(0, "maxRequest reached");
@@ -1605,20 +1690,25 @@ jQuery.atmosphere = function() {
/**
* Do ajax request.
+ *
* @param ajaxRequest Ajax request.
* @param request Request parameters.
* @param create If ajax request has to be open.
*/
function _doRequest(ajaxRequest, request, create) {
// Prevent Android to cache request
- var url = _attachHeaders(request);
+ var url = request.url;
+ if (request.dispatchUrl != null && request.method === 'POST') {
+ url += request.dispatchUrl;
+ }
+ url = _attachHeaders(request, url);
url = jQuery.atmosphere.prepareURL(url);
if (create) {
ajaxRequest.open(request.method, url, true);
- if (request.connectTimeout > -1) {
- request.id = setTimeout(function() {
- if (request.requestCount == 0) {
+ if (request.connectTimeout > 0) {
+ request.id = setTimeout(function () {
+ if (request.requestCount === 0) {
_clearState();
_prepareC
<TRUNCATED>