Best JavaScript code snippet using cypress
jquery.signalR-2.2.2.js
Source:jquery.signalR-2.2.2.js
...838 // Check if the keep alive has completely timed out839 if (timeElapsed >= keepAliveData.timeout) {840 connection.log("Keep alive timed out. Notifying transport that connection has been lost.");841 // Notify transport that the connection has been lost842 connection.transport.lostConnection(connection);843 } else if (timeElapsed >= keepAliveData.timeoutWarning) {844 // This is to assure that the user only gets a single warning845 if (!keepAliveData.userNotified) {846 connection.log("Keep alive has been missed, connection may be dead/slow.");847 $(connection).triggerHandler(events.onConnectionSlow);848 keepAliveData.userNotified = true;849 }850 } else {851 keepAliveData.userNotified = false;852 }853 }854 }855 function getAjaxUrl(connection, path) {856 var url = connection.url + path;857 if (connection.transport) {858 url += "?transport=" + connection.transport.name;859 }860 return transportLogic.prepareQueryString(connection, url);861 }862 function InitHandler(connection) {863 this.connection = connection;864 this.startRequested = false;865 this.startCompleted = false;866 this.connectionStopped = false;867 }868 InitHandler.prototype = {869 start: function (transport, onSuccess, onFallback) {870 var that = this,871 connection = that.connection,872 failCalled = false;873 if (that.startRequested || that.connectionStopped) {874 connection.log("WARNING! " + transport.name + " transport cannot be started. Initialization ongoing or completed.");875 return;876 }877 connection.log(transport.name + " transport starting.");878 transport.start(connection, function () {879 if (!failCalled) {880 that.initReceived(transport, onSuccess);881 }882 }, function (error) {883 // Don't allow the same transport to cause onFallback to be called twice884 if (!failCalled) {885 failCalled = true;886 that.transportFailed(transport, error, onFallback);887 }888 // Returns true if the transport should stop;889 // false if it should attempt to reconnect890 return !that.startCompleted || that.connectionStopped;891 });892 that.transportTimeoutHandle = window.setTimeout(function () {893 if (!failCalled) {894 failCalled = true;895 connection.log(transport.name + " transport timed out when trying to connect.");896 that.transportFailed(transport, undefined, onFallback);897 }898 }, connection._.totalTransportConnectTimeout);899 },900 stop: function () {901 this.connectionStopped = true;902 window.clearTimeout(this.transportTimeoutHandle);903 signalR.transports._logic.tryAbortStartRequest(this.connection);904 },905 initReceived: function (transport, onSuccess) {906 var that = this,907 connection = that.connection;908 if (that.startRequested) {909 connection.log("WARNING! The client received multiple init messages.");910 return;911 }912 if (that.connectionStopped) {913 return;914 }915 that.startRequested = true;916 window.clearTimeout(that.transportTimeoutHandle);917 connection.log(transport.name + " transport connected. Initiating start request.");918 signalR.transports._logic.ajaxStart(connection, function () {919 that.startCompleted = true;920 onSuccess();921 });922 },923 transportFailed: function (transport, error, onFallback) {924 var connection = this.connection,925 deferred = connection._deferral,926 wrappedError;927 if (this.connectionStopped) {928 return;929 }930 window.clearTimeout(this.transportTimeoutHandle);931 if (!this.startRequested) {932 transport.stop(connection);933 connection.log(transport.name + " transport failed to connect. Attempting to fall back.");934 onFallback();935 } else if (!this.startCompleted) {936 // Do not attempt to fall back if a start request is ongoing during a transport failure.937 // Instead, trigger an error and stop the connection.938 wrappedError = signalR._.error(signalR.resources.errorDuringStartRequest, error);939 connection.log(transport.name + " transport failed during the start request. Stopping the connection.");940 $(connection).triggerHandler(events.onError, [wrappedError]);941 if (deferred) {942 deferred.reject(wrappedError);943 }944 connection.stop();945 } else {946 // The start request has completed, but the connection has not stopped.947 // No need to do anything here. The transport should attempt its normal reconnect logic.948 }949 }950 };951 transportLogic = signalR.transports._logic = {952 ajax: function (connection, options) {953 return $.ajax(954 $.extend(/*deep copy*/ true, {}, $.signalR.ajaxDefaults, {955 type: "GET",956 data: {},957 xhrFields: { withCredentials: connection.withCredentials },958 contentType: connection.contentType,959 dataType: connection.ajaxDataType960 }, options));961 },962 pingServer: function (connection) {963 /// <summary>Pings the server</summary>964 /// <param name="connection" type="signalr">Connection associated with the server ping</param>965 /// <returns type="signalR" />966 var url,967 xhr,968 deferral = $.Deferred();969 if (connection.transport) {970 url = connection.url + "/ping";971 url = transportLogic.addQs(url, connection.qs);972 xhr = transportLogic.ajax(connection, {973 url: url,974 success: function (result) {975 var data;976 try {977 data = connection._parseResponse(result);978 }979 catch (error) {980 deferral.reject(981 signalR._.transportError(982 signalR.resources.pingServerFailedParse,983 connection.transport,984 error,985 xhr986 )987 );988 connection.stop();989 return;990 }991 if (data.Response === "pong") {992 deferral.resolve();993 }994 else {995 deferral.reject(996 signalR._.transportError(997 signalR._.format(signalR.resources.pingServerFailedInvalidResponse, result),998 connection.transport,999 null /* error */,1000 xhr1001 )1002 );1003 }1004 },1005 error: function (error) {1006 if (error.status === 401 || error.status === 403) {1007 deferral.reject(1008 signalR._.transportError(1009 signalR._.format(signalR.resources.pingServerFailedStatusCode, error.status),1010 connection.transport,1011 error,1012 xhr1013 )1014 );1015 connection.stop();1016 }1017 else {1018 deferral.reject(1019 signalR._.transportError(1020 signalR.resources.pingServerFailed,1021 connection.transport,1022 error,1023 xhr1024 )1025 );1026 }1027 }1028 });1029 }1030 else {1031 deferral.reject(1032 signalR._.transportError(1033 signalR.resources.noConnectionTransport,1034 connection.transport1035 )1036 );1037 }1038 return deferral.promise();1039 },1040 prepareQueryString: function (connection, url) {1041 var preparedUrl;1042 // Use addQs to start since it handles the ?/& prefix for us1043 preparedUrl = transportLogic.addQs(url, "clientProtocol=" + connection.clientProtocol);1044 // Add the user-specified query string params if any1045 preparedUrl = transportLogic.addQs(preparedUrl, connection.qs);1046 if (connection.token) {1047 preparedUrl += "&connectionToken=" + window.encodeURIComponent(connection.token);1048 }1049 if (connection.data) {1050 preparedUrl += "&connectionData=" + window.encodeURIComponent(connection.data);1051 }1052 return preparedUrl;1053 },1054 addQs: function (url, qs) {1055 var appender = url.indexOf("?") !== -1 ? "&" : "?",1056 firstChar;1057 if (!qs) {1058 return url;1059 }1060 if (typeof (qs) === "object") {1061 return url + appender + $.param(qs);1062 }1063 if (typeof (qs) === "string") {1064 firstChar = qs.charAt(0);1065 if (firstChar === "?" || firstChar === "&") {1066 appender = "";1067 }1068 return url + appender + qs;1069 }1070 throw new Error("Query string property must be either a string or object.");1071 },1072 // BUG #2953: The url needs to be same otherwise it will cause a memory leak1073 getUrl: function (connection, transport, reconnecting, poll, ajaxPost) {1074 /// <summary>Gets the url for making a GET based connect request</summary>1075 var baseUrl = transport === "webSockets" ? "" : connection.baseUrl,1076 url = baseUrl + connection.appRelativeUrl,1077 qs = "transport=" + transport;1078 if (!ajaxPost && connection.groupsToken) {1079 qs += "&groupsToken=" + window.encodeURIComponent(connection.groupsToken);1080 }1081 if (!reconnecting) {1082 url += "/connect";1083 } else {1084 if (poll) {1085 // longPolling transport specific1086 url += "/poll";1087 } else {1088 url += "/reconnect";1089 }1090 if (!ajaxPost && connection.messageId) {1091 qs += "&messageId=" + window.encodeURIComponent(connection.messageId);1092 }1093 }1094 url += "?" + qs;1095 url = transportLogic.prepareQueryString(connection, url);1096 if (!ajaxPost) {1097 url += "&tid=" + Math.floor(Math.random() * 11);1098 }1099 return url;1100 },1101 maximizePersistentResponse: function (minPersistentResponse) {1102 return {1103 MessageId: minPersistentResponse.C,1104 Messages: minPersistentResponse.M,1105 Initialized: typeof (minPersistentResponse.S) !== "undefined" ? true : false,1106 ShouldReconnect: typeof (minPersistentResponse.T) !== "undefined" ? true : false,1107 LongPollDelay: minPersistentResponse.L,1108 GroupsToken: minPersistentResponse.G1109 };1110 },1111 updateGroups: function (connection, groupsToken) {1112 if (groupsToken) {1113 connection.groupsToken = groupsToken;1114 }1115 },1116 stringifySend: function (connection, message) {1117 if (typeof (message) === "string" || typeof (message) === "undefined" || message === null) {1118 return message;1119 }1120 return connection.json.stringify(message);1121 },1122 ajaxSend: function (connection, data) {1123 var payload = transportLogic.stringifySend(connection, data),1124 url = getAjaxUrl(connection, "/send"),1125 xhr,1126 onFail = function (error, connection) {1127 $(connection).triggerHandler(events.onError, [signalR._.transportError(signalR.resources.sendFailed, connection.transport, error, xhr), data]);1128 };1129 xhr = transportLogic.ajax(connection, {1130 url: url,1131 type: connection.ajaxDataType === "jsonp" ? "GET" : "POST",1132 contentType: signalR._.defaultContentType,1133 data: {1134 data: payload1135 },1136 success: function (result) {1137 var res;1138 if (result) {1139 try {1140 res = connection._parseResponse(result);1141 }1142 catch (error) {1143 onFail(error, connection);1144 connection.stop();1145 return;1146 }1147 transportLogic.triggerReceived(connection, res);1148 }1149 },1150 error: function (error, textStatus) {1151 if (textStatus === "abort" || textStatus === "parsererror") {1152 // The parsererror happens for sends that don't return any data, and hence1153 // don't write the jsonp callback to the response. This is harder to fix on the server1154 // so just hack around it on the client for now.1155 return;1156 }1157 onFail(error, connection);1158 }1159 });1160 return xhr;1161 },1162 ajaxAbort: function (connection, async) {1163 if (typeof (connection.transport) === "undefined") {1164 return;1165 }1166 // Async by default unless explicitly overidden1167 async = typeof async === "undefined" ? true : async;1168 var url = getAjaxUrl(connection, "/abort");1169 transportLogic.ajax(connection, {1170 url: url,1171 async: async,1172 timeout: 1000,1173 type: "POST"1174 });1175 connection.log("Fired ajax abort async = " + async + ".");1176 },1177 ajaxStart: function (connection, onSuccess) {1178 var rejectDeferred = function (error) {1179 var deferred = connection._deferral;1180 if (deferred) {1181 deferred.reject(error);1182 }1183 },1184 triggerStartError = function (error) {1185 connection.log("The start request failed. Stopping the connection.");1186 $(connection).triggerHandler(events.onError, [error]);1187 rejectDeferred(error);1188 connection.stop();1189 };1190 connection._.startRequest = transportLogic.ajax(connection, {1191 url: getAjaxUrl(connection, "/start"),1192 success: function (result, statusText, xhr) {1193 var data;1194 try {1195 data = connection._parseResponse(result);1196 } catch (error) {1197 triggerStartError(signalR._.error(1198 signalR._.format(signalR.resources.errorParsingStartResponse, result),1199 error, xhr));1200 return;1201 }1202 if (data.Response === "started") {1203 onSuccess();1204 } else {1205 triggerStartError(signalR._.error(1206 signalR._.format(signalR.resources.invalidStartResponse, result),1207 null /* error */, xhr));1208 }1209 },1210 error: function (xhr, statusText, error) {1211 if (statusText !== startAbortText) {1212 triggerStartError(signalR._.error(1213 signalR.resources.errorDuringStartRequest,1214 error, xhr));1215 } else {1216 // Stop has been called, no need to trigger the error handler1217 // or stop the connection again with onStartError1218 connection.log("The start request aborted because connection.stop() was called.");1219 rejectDeferred(signalR._.error(1220 signalR.resources.stoppedDuringStartRequest,1221 null /* error */, xhr));1222 }1223 }1224 });1225 },1226 tryAbortStartRequest: function (connection) {1227 if (connection._.startRequest) {1228 // If the start request has already completed this will noop.1229 connection._.startRequest.abort(startAbortText);1230 delete connection._.startRequest;1231 }1232 },1233 tryInitialize: function (connection, persistentResponse, onInitialized) {1234 if (persistentResponse.Initialized && onInitialized) {1235 onInitialized();1236 } else if (persistentResponse.Initialized) {1237 connection.log("WARNING! The client received an init message after reconnecting.");1238 }1239 },1240 triggerReceived: function (connection, data) {1241 if (!connection._.connectingMessageBuffer.tryBuffer(data)) {1242 $(connection).triggerHandler(events.onReceived, [data]);1243 }1244 },1245 processMessages: function (connection, minData, onInitialized) {1246 var data;1247 // Update the last message time stamp1248 transportLogic.markLastMessage(connection);1249 if (minData) {1250 data = transportLogic.maximizePersistentResponse(minData);1251 transportLogic.updateGroups(connection, data.GroupsToken);1252 if (data.MessageId) {1253 connection.messageId = data.MessageId;1254 }1255 if (data.Messages) {1256 $.each(data.Messages, function (index, message) {1257 transportLogic.triggerReceived(connection, message);1258 });1259 transportLogic.tryInitialize(connection, data, onInitialized);1260 }1261 }1262 },1263 monitorKeepAlive: function (connection) {1264 var keepAliveData = connection._.keepAliveData;1265 // If we haven't initiated the keep alive timeouts then we need to1266 if (!keepAliveData.monitoring) {1267 keepAliveData.monitoring = true;1268 transportLogic.markLastMessage(connection);1269 // Save the function so we can unbind it on stop1270 connection._.keepAliveData.reconnectKeepAliveUpdate = function () {1271 // Mark a new message so that keep alive doesn't time out connections1272 transportLogic.markLastMessage(connection);1273 };1274 // Update Keep alive on reconnect1275 $(connection).bind(events.onReconnect, connection._.keepAliveData.reconnectKeepAliveUpdate);1276 connection.log("Now monitoring keep alive with a warning timeout of " + keepAliveData.timeoutWarning + ", keep alive timeout of " + keepAliveData.timeout + " and disconnecting timeout of " + connection.disconnectTimeout);1277 } else {1278 connection.log("Tried to monitor keep alive but it's already being monitored.");1279 }1280 },1281 stopMonitoringKeepAlive: function (connection) {1282 var keepAliveData = connection._.keepAliveData;1283 // Only attempt to stop the keep alive monitoring if its being monitored1284 if (keepAliveData.monitoring) {1285 // Stop monitoring1286 keepAliveData.monitoring = false;1287 // Remove the updateKeepAlive function from the reconnect event1288 $(connection).unbind(events.onReconnect, connection._.keepAliveData.reconnectKeepAliveUpdate);1289 // Clear all the keep alive data1290 connection._.keepAliveData = {};1291 connection.log("Stopping the monitoring of the keep alive.");1292 }1293 },1294 startHeartbeat: function (connection) {1295 connection._.lastActiveAt = new Date().getTime();1296 beat(connection);1297 },1298 markLastMessage: function (connection) {1299 connection._.lastMessageAt = new Date().getTime();1300 },1301 markActive: function (connection) {1302 if (transportLogic.verifyLastActive(connection)) {1303 connection._.lastActiveAt = new Date().getTime();1304 return true;1305 }1306 return false;1307 },1308 isConnectedOrReconnecting: function (connection) {1309 return connection.state === signalR.connectionState.connected ||1310 connection.state === signalR.connectionState.reconnecting;1311 },1312 ensureReconnectingState: function (connection) {1313 if (changeState(connection,1314 signalR.connectionState.connected,1315 signalR.connectionState.reconnecting) === true) {1316 $(connection).triggerHandler(events.onReconnecting);1317 }1318 return connection.state === signalR.connectionState.reconnecting;1319 },1320 clearReconnectTimeout: function (connection) {1321 if (connection && connection._.reconnectTimeout) {1322 window.clearTimeout(connection._.reconnectTimeout);1323 delete connection._.reconnectTimeout;1324 }1325 },1326 verifyLastActive: function (connection) {1327 if (new Date().getTime() - connection._.lastActiveAt >= connection.reconnectWindow) {1328 var message = signalR._.format(signalR.resources.reconnectWindowTimeout, new Date(connection._.lastActiveAt), connection.reconnectWindow);1329 connection.log(message);1330 $(connection).triggerHandler(events.onError, [signalR._.error(message, /* source */ "TimeoutException")]);1331 connection.stop(/* async */ false, /* notifyServer */ false);1332 return false;1333 }1334 return true;1335 },1336 reconnect: function (connection, transportName) {1337 var transport = signalR.transports[transportName];1338 // We should only set a reconnectTimeout if we are currently connected1339 // and a reconnectTimeout isn't already set.1340 if (transportLogic.isConnectedOrReconnecting(connection) && !connection._.reconnectTimeout) {1341 // Need to verify before the setTimeout occurs because an application sleep could occur during the setTimeout duration.1342 if (!transportLogic.verifyLastActive(connection)) {1343 return;1344 }1345 connection._.reconnectTimeout = window.setTimeout(function () {1346 if (!transportLogic.verifyLastActive(connection)) {1347 return;1348 }1349 transport.stop(connection);1350 if (transportLogic.ensureReconnectingState(connection)) {1351 connection.log(transportName + " reconnecting.");1352 transport.start(connection);1353 }1354 }, connection.reconnectDelay);1355 }1356 },1357 handleParseFailure: function (connection, result, error, onFailed, context) {1358 var wrappedError = signalR._.transportError(1359 signalR._.format(signalR.resources.parseFailed, result),1360 connection.transport,1361 error,1362 context);1363 // If we're in the initialization phase trigger onFailed, otherwise stop the connection.1364 if (onFailed && onFailed(wrappedError)) {1365 connection.log("Failed to parse server response while attempting to connect.");1366 } else {1367 $(connection).triggerHandler(events.onError, [wrappedError]);1368 connection.stop();1369 }1370 },1371 initHandler: function (connection) {1372 return new InitHandler(connection);1373 },1374 foreverFrame: {1375 count: 0,1376 connections: {}1377 }1378 };1379}(window.jQuery, window));1380/* jquery.signalR.transports.webSockets.js */1381// Copyright (c) .NET Foundation. All rights reserved.1382// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.1383/*global window:false */1384/// <reference path="jquery.signalR.transports.common.js" />1385(function ($, window, undefined) {1386 var signalR = $.signalR,1387 events = $.signalR.events,1388 changeState = $.signalR.changeState,1389 transportLogic = signalR.transports._logic;1390 signalR.transports.webSockets = {1391 name: "webSockets",1392 supportsKeepAlive: function () {1393 return true;1394 },1395 send: function (connection, data) {1396 var payload = transportLogic.stringifySend(connection, data);1397 try {1398 connection.socket.send(payload);1399 } catch (ex) {1400 $(connection).triggerHandler(events.onError,1401 [signalR._.transportError(1402 signalR.resources.webSocketsInvalidState,1403 connection.transport,1404 ex,1405 connection.socket1406 ),1407 data]);1408 }1409 },1410 start: function (connection, onSuccess, onFailed) {1411 var url,1412 opened = false,1413 that = this,1414 reconnecting = !onSuccess,1415 $connection = $(connection);1416 if (!window.WebSocket) {1417 onFailed();1418 return;1419 }1420 if (!connection.socket) {1421 if (connection.webSocketServerUrl) {1422 url = connection.webSocketServerUrl;1423 } else {1424 url = connection.wsProtocol + connection.host;1425 }1426 url += transportLogic.getUrl(connection, this.name, reconnecting);1427 connection.log("Connecting to websocket endpoint '" + url + "'.");1428 connection.socket = new window.WebSocket(url);1429 connection.socket.onopen = function () {1430 opened = true;1431 connection.log("Websocket opened.");1432 transportLogic.clearReconnectTimeout(connection);1433 if (changeState(connection,1434 signalR.connectionState.reconnecting,1435 signalR.connectionState.connected) === true) {1436 $connection.triggerHandler(events.onReconnect);1437 }1438 };1439 connection.socket.onclose = function (event) {1440 var error;1441 // Only handle a socket close if the close is from the current socket.1442 // Sometimes on disconnect the server will push down an onclose event1443 // to an expired socket.1444 if (this === connection.socket) {1445 if (opened && typeof event.wasClean !== "undefined" && event.wasClean === false) {1446 // Ideally this would use the websocket.onerror handler (rather than checking wasClean in onclose) but1447 // I found in some circumstances Chrome won't call onerror. This implementation seems to work on all browsers.1448 error = signalR._.transportError(1449 signalR.resources.webSocketClosed,1450 connection.transport,1451 event);1452 connection.log("Unclean disconnect from websocket: " + (event.reason || "[no reason given]."));1453 } else {1454 connection.log("Websocket closed.");1455 }1456 if (!onFailed || !onFailed(error)) {1457 if (error) {1458 $(connection).triggerHandler(events.onError, [error]);1459 }1460 that.reconnect(connection);1461 }1462 }1463 };1464 connection.socket.onmessage = function (event) {1465 var data;1466 try {1467 data = connection._parseResponse(event.data);1468 }1469 catch (error) {1470 transportLogic.handleParseFailure(connection, event.data, error, onFailed, event);1471 return;1472 }1473 if (data) {1474 // data.M is PersistentResponse.Messages1475 if ($.isEmptyObject(data) || data.M) {1476 transportLogic.processMessages(connection, data, onSuccess);1477 } else {1478 // For websockets we need to trigger onReceived1479 // for callbacks to outgoing hub calls.1480 transportLogic.triggerReceived(connection, data);1481 }1482 }1483 };1484 }1485 },1486 reconnect: function (connection) {1487 transportLogic.reconnect(connection, this.name);1488 },1489 lostConnection: function (connection) {1490 this.reconnect(connection);1491 },1492 stop: function (connection) {1493 // Don't trigger a reconnect after stopping1494 transportLogic.clearReconnectTimeout(connection);1495 if (connection.socket) {1496 connection.log("Closing the Websocket.");1497 connection.socket.close();1498 connection.socket = null;1499 }1500 },1501 abort: function (connection, async) {1502 transportLogic.ajaxAbort(connection, async);1503 }1504 };1505}(window.jQuery, window));1506/* jquery.signalR.transports.serverSentEvents.js */1507// Copyright (c) .NET Foundation. All rights reserved.1508// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.1509/*global window:false */1510/// <reference path="jquery.signalR.transports.common.js" />1511(function ($, window, undefined) {1512 var signalR = $.signalR,1513 events = $.signalR.events,1514 changeState = $.signalR.changeState,1515 transportLogic = signalR.transports._logic,1516 clearReconnectAttemptTimeout = function (connection) {1517 window.clearTimeout(connection._.reconnectAttemptTimeoutHandle);1518 delete connection._.reconnectAttemptTimeoutHandle;1519 };1520 signalR.transports.serverSentEvents = {1521 name: "serverSentEvents",1522 supportsKeepAlive: function () {1523 return true;1524 },1525 timeOut: 3000,1526 start: function (connection, onSuccess, onFailed) {1527 var that = this,1528 opened = false,1529 $connection = $(connection),1530 reconnecting = !onSuccess,1531 url;1532 if (connection.eventSource) {1533 connection.log("The connection already has an event source. Stopping it.");1534 connection.stop();1535 }1536 if (!window.EventSource) {1537 if (onFailed) {1538 connection.log("This browser doesn't support SSE.");1539 onFailed();1540 }1541 return;1542 }1543 url = transportLogic.getUrl(connection, this.name, reconnecting);1544 try {1545 connection.log("Attempting to connect to SSE endpoint '" + url + "'.");1546 connection.eventSource = new window.EventSource(url, { withCredentials: connection.withCredentials });1547 }1548 catch (e) {1549 connection.log("EventSource failed trying to connect with error " + e.Message + ".");1550 if (onFailed) {1551 // The connection failed, call the failed callback1552 onFailed();1553 } else {1554 $connection.triggerHandler(events.onError, [signalR._.transportError(signalR.resources.eventSourceFailedToConnect, connection.transport, e)]);1555 if (reconnecting) {1556 // If we were reconnecting, rather than doing initial connect, then try reconnect again1557 that.reconnect(connection);1558 }1559 }1560 return;1561 }1562 if (reconnecting) {1563 connection._.reconnectAttemptTimeoutHandle = window.setTimeout(function () {1564 if (opened === false) {1565 // If we're reconnecting and the event source is attempting to connect,1566 // don't keep retrying. This causes duplicate connections to spawn.1567 if (connection.eventSource.readyState !== window.EventSource.OPEN) {1568 // If we were reconnecting, rather than doing initial connect, then try reconnect again1569 that.reconnect(connection);1570 }1571 }1572 },1573 that.timeOut);1574 }1575 connection.eventSource.addEventListener("open", function (e) {1576 connection.log("EventSource connected.");1577 clearReconnectAttemptTimeout(connection);1578 transportLogic.clearReconnectTimeout(connection);1579 if (opened === false) {1580 opened = true;1581 if (changeState(connection,1582 signalR.connectionState.reconnecting,1583 signalR.connectionState.connected) === true) {1584 $connection.triggerHandler(events.onReconnect);1585 }1586 }1587 }, false);1588 connection.eventSource.addEventListener("message", function (e) {1589 var res;1590 // process messages1591 if (e.data === "initialized") {1592 return;1593 }1594 try {1595 res = connection._parseResponse(e.data);1596 }1597 catch (error) {1598 transportLogic.handleParseFailure(connection, e.data, error, onFailed, e);1599 return;1600 }1601 transportLogic.processMessages(connection, res, onSuccess);1602 }, false);1603 connection.eventSource.addEventListener("error", function (e) {1604 var error = signalR._.transportError(1605 signalR.resources.eventSourceError,1606 connection.transport,1607 e);1608 // Only handle an error if the error is from the current Event Source.1609 // Sometimes on disconnect the server will push down an error event1610 // to an expired Event Source.1611 if (this !== connection.eventSource) {1612 return;1613 }1614 if (onFailed && onFailed(error)) {1615 return;1616 }1617 connection.log("EventSource readyState: " + connection.eventSource.readyState + ".");1618 if (e.eventPhase === window.EventSource.CLOSED) {1619 // We don't use the EventSource's native reconnect function as it1620 // doesn't allow us to change the URL when reconnecting. We need1621 // to change the URL to not include the /connect suffix, and pass1622 // the last message id we received.1623 connection.log("EventSource reconnecting due to the server connection ending.");1624 that.reconnect(connection);1625 } else {1626 // connection error1627 connection.log("EventSource error.");1628 $connection.triggerHandler(events.onError, [error]);1629 }1630 }, false);1631 },1632 reconnect: function (connection) {1633 transportLogic.reconnect(connection, this.name);1634 },1635 lostConnection: function (connection) {1636 this.reconnect(connection);1637 },1638 send: function (connection, data) {1639 transportLogic.ajaxSend(connection, data);1640 },1641 stop: function (connection) {1642 // Don't trigger a reconnect after stopping1643 clearReconnectAttemptTimeout(connection);1644 transportLogic.clearReconnectTimeout(connection);1645 if (connection && connection.eventSource) {1646 connection.log("EventSource calling close().");1647 connection.eventSource.close();1648 connection.eventSource = null;1649 delete connection.eventSource;1650 }1651 },1652 abort: function (connection, async) {1653 transportLogic.ajaxAbort(connection, async);1654 }1655 };1656}(window.jQuery, window));1657/* jquery.signalR.transports.foreverFrame.js */1658// Copyright (c) .NET Foundation. All rights reserved.1659// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.1660/*global window:false */1661/// <reference path="jquery.signalR.transports.common.js" />1662(function ($, window, undefined) {1663 var signalR = $.signalR,1664 events = $.signalR.events,1665 changeState = $.signalR.changeState,1666 transportLogic = signalR.transports._logic,1667 createFrame = function () {1668 var frame = window.document.createElement("iframe");1669 frame.setAttribute("style", "position:absolute;top:0;left:0;width:0;height:0;visibility:hidden;");1670 return frame;1671 },1672 // Used to prevent infinite loading icon spins in older versions of ie1673 // We build this object inside a closure so we don't pollute the rest of1674 // the foreverFrame transport with unnecessary functions/utilities.1675 loadPreventer = (function () {1676 var loadingFixIntervalId = null,1677 loadingFixInterval = 1000,1678 attachedTo = 0;1679 return {1680 prevent: function () {1681 // Prevent additional iframe removal procedures from newer browsers1682 if (signalR._.ieVersion <= 8) {1683 // We only ever want to set the interval one time, so on the first attachedTo1684 if (attachedTo === 0) {1685 // Create and destroy iframe every 3 seconds to prevent loading icon, super hacky1686 loadingFixIntervalId = window.setInterval(function () {1687 var tempFrame = createFrame();1688 window.document.body.appendChild(tempFrame);1689 window.document.body.removeChild(tempFrame);1690 tempFrame = null;1691 }, loadingFixInterval);1692 }1693 attachedTo++;1694 }1695 },1696 cancel: function () {1697 // Only clear the interval if there's only one more object that the loadPreventer is attachedTo1698 if (attachedTo === 1) {1699 window.clearInterval(loadingFixIntervalId);1700 }1701 if (attachedTo > 0) {1702 attachedTo--;1703 }1704 }1705 };1706 })();1707 signalR.transports.foreverFrame = {1708 name: "foreverFrame",1709 supportsKeepAlive: function () {1710 return true;1711 },1712 // Added as a value here so we can create tests to verify functionality1713 iframeClearThreshold: 50,1714 start: function (connection, onSuccess, onFailed) {1715 var that = this,1716 frameId = (transportLogic.foreverFrame.count += 1),1717 url,1718 frame = createFrame(),1719 frameLoadHandler = function () {1720 connection.log("Forever frame iframe finished loading and is no longer receiving messages.");1721 if (!onFailed || !onFailed()) {1722 that.reconnect(connection);1723 }1724 };1725 if (window.EventSource) {1726 // If the browser supports SSE, don't use Forever Frame1727 if (onFailed) {1728 connection.log("Forever Frame is not supported by SignalR on browsers with SSE support.");1729 onFailed();1730 }1731 return;1732 }1733 frame.setAttribute("data-signalr-connection-id", connection.id);1734 // Start preventing loading icon1735 // This will only perform work if the loadPreventer is not attached to another connection.1736 loadPreventer.prevent();1737 // Build the url1738 url = transportLogic.getUrl(connection, this.name);1739 url += "&frameId=" + frameId;1740 // add frame to the document prior to setting URL to avoid caching issues.1741 window.document.documentElement.appendChild(frame);1742 connection.log("Binding to iframe's load event.");1743 if (frame.addEventListener) {1744 frame.addEventListener("load", frameLoadHandler, false);1745 } else if (frame.attachEvent) {1746 frame.attachEvent("onload", frameLoadHandler);1747 }1748 frame.src = url;1749 transportLogic.foreverFrame.connections[frameId] = connection;1750 connection.frame = frame;1751 connection.frameId = frameId;1752 if (onSuccess) {1753 connection.onSuccess = function () {1754 connection.log("Iframe transport started.");1755 onSuccess();1756 };1757 }1758 },1759 reconnect: function (connection) {1760 var that = this;1761 // Need to verify connection state and verify before the setTimeout occurs because an application sleep could occur during the setTimeout duration.1762 if (transportLogic.isConnectedOrReconnecting(connection) && transportLogic.verifyLastActive(connection)) {1763 window.setTimeout(function () {1764 // Verify that we're ok to reconnect.1765 if (!transportLogic.verifyLastActive(connection)) {1766 return;1767 }1768 if (connection.frame && transportLogic.ensureReconnectingState(connection)) {1769 var frame = connection.frame,1770 src = transportLogic.getUrl(connection, that.name, true) + "&frameId=" + connection.frameId;1771 connection.log("Updating iframe src to '" + src + "'.");1772 frame.src = src;1773 }1774 }, connection.reconnectDelay);1775 }1776 },1777 lostConnection: function (connection) {1778 this.reconnect(connection);1779 },1780 send: function (connection, data) {1781 transportLogic.ajaxSend(connection, data);1782 },1783 receive: function (connection, data) {1784 var cw,1785 body,1786 response;1787 if (connection.json !== connection._originalJson) {1788 // If there's a custom JSON parser configured then serialize the object1789 // using the original (browser) JSON parser and then deserialize it using1790 // the custom parser (connection._parseResponse does that). This is so we1791 // can easily send the response from the server as "raw" JSON but still1792 // support custom JSON deserialization in the browser.1793 data = connection._originalJson.stringify(data);1794 }1795 response = connection._parseResponse(data);1796 transportLogic.processMessages(connection, response, connection.onSuccess);1797 // Protect against connection stopping from a callback trigger within the processMessages above.1798 if (connection.state === $.signalR.connectionState.connected) {1799 // Delete the script & div elements1800 connection.frameMessageCount = (connection.frameMessageCount || 0) + 1;1801 if (connection.frameMessageCount > signalR.transports.foreverFrame.iframeClearThreshold) {1802 connection.frameMessageCount = 0;1803 cw = connection.frame.contentWindow || connection.frame.contentDocument;1804 if (cw && cw.document && cw.document.body) {1805 body = cw.document.body;1806 // Remove all the child elements from the iframe's body to conserver memory1807 while (body.firstChild) {1808 body.removeChild(body.firstChild);1809 }1810 }1811 }1812 }1813 },1814 stop: function (connection) {1815 var cw = null;1816 // Stop attempting to prevent loading icon1817 loadPreventer.cancel();1818 if (connection.frame) {1819 if (connection.frame.stop) {1820 connection.frame.stop();1821 } else {1822 try {1823 cw = connection.frame.contentWindow || connection.frame.contentDocument;1824 if (cw.document && cw.document.execCommand) {1825 cw.document.execCommand("Stop");1826 }1827 }1828 catch (e) {1829 connection.log("Error occurred when stopping foreverFrame transport. Message = " + e.message + ".");1830 }1831 }1832 // Ensure the iframe is where we left it1833 if (connection.frame.parentNode === window.document.documentElement) {1834 window.document.documentElement.removeChild(connection.frame);1835 }1836 delete transportLogic.foreverFrame.connections[connection.frameId];1837 connection.frame = null;1838 connection.frameId = null;1839 delete connection.frame;1840 delete connection.frameId;1841 delete connection.onSuccess;1842 delete connection.frameMessageCount;1843 connection.log("Stopping forever frame.");1844 }1845 },1846 abort: function (connection, async) {1847 transportLogic.ajaxAbort(connection, async);1848 },1849 getConnection: function (id) {1850 return transportLogic.foreverFrame.connections[id];1851 },1852 started: function (connection) {1853 if (changeState(connection,1854 signalR.connectionState.reconnecting,1855 signalR.connectionState.connected) === true) {1856 $(connection).triggerHandler(events.onReconnect);1857 }1858 }1859 };1860}(window.jQuery, window));1861/* jquery.signalR.transports.longPolling.js */1862// Copyright (c) .NET Foundation. All rights reserved.1863// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.1864/*global window:false */1865/// <reference path="jquery.signalR.transports.common.js" />1866(function ($, window, undefined) {1867 var signalR = $.signalR,1868 events = $.signalR.events,1869 changeState = $.signalR.changeState,1870 isDisconnecting = $.signalR.isDisconnecting,1871 transportLogic = signalR.transports._logic;1872 signalR.transports.longPolling = {1873 name: "longPolling",1874 supportsKeepAlive: function () {1875 return false;1876 },1877 reconnectDelay: 3000,1878 start: function (connection, onSuccess, onFailed) {1879 /// <summary>Starts the long polling connection</summary>1880 /// <param name="connection" type="signalR">The SignalR connection to start</param>1881 var that = this,1882 fireConnect = function () {1883 fireConnect = $.noop;1884 connection.log("LongPolling connected.");1885 if (onSuccess) {1886 onSuccess();1887 } else {1888 connection.log("WARNING! The client received an init message after reconnecting.");1889 }1890 },1891 tryFailConnect = function (error) {1892 if (onFailed(error)) {1893 connection.log("LongPolling failed to connect.");1894 return true;1895 }1896 return false;1897 },1898 privateData = connection._,1899 reconnectErrors = 0,1900 fireReconnected = function (instance) {1901 window.clearTimeout(privateData.reconnectTimeoutId);1902 privateData.reconnectTimeoutId = null;1903 if (changeState(instance,1904 signalR.connectionState.reconnecting,1905 signalR.connectionState.connected) === true) {1906 // Successfully reconnected!1907 instance.log("Raising the reconnect event");1908 $(instance).triggerHandler(events.onReconnect);1909 }1910 },1911 // 1 hour1912 maxFireReconnectedTimeout = 3600000;1913 if (connection.pollXhr) {1914 connection.log("Polling xhr requests already exists, aborting.");1915 connection.stop();1916 }1917 connection.messageId = null;1918 privateData.reconnectTimeoutId = null;1919 privateData.pollTimeoutId = window.setTimeout(function () {1920 (function poll(instance, raiseReconnect) {1921 var messageId = instance.messageId,1922 connect = (messageId === null),1923 reconnecting = !connect,1924 polling = !raiseReconnect,1925 url = transportLogic.getUrl(instance, that.name, reconnecting, polling, true /* use Post for longPolling */),1926 postData = {};1927 if (instance.messageId) {1928 postData.messageId = instance.messageId;1929 }1930 if (instance.groupsToken) {1931 postData.groupsToken = instance.groupsToken;1932 }1933 // If we've disconnected during the time we've tried to re-instantiate the poll then stop.1934 if (isDisconnecting(instance) === true) {1935 return;1936 }1937 connection.log("Opening long polling request to '" + url + "'.");1938 instance.pollXhr = transportLogic.ajax(connection, {1939 xhrFields: {1940 onprogress: function () {1941 transportLogic.markLastMessage(connection);1942 }1943 },1944 url: url,1945 type: "POST",1946 contentType: signalR._.defaultContentType,1947 data: postData,1948 timeout: connection._.pollTimeout,1949 success: function (result) {1950 var minData,1951 delay = 0,1952 data,1953 shouldReconnect;1954 connection.log("Long poll complete.");1955 // Reset our reconnect errors so if we transition into a reconnecting state again we trigger1956 // reconnected quickly1957 reconnectErrors = 0;1958 try {1959 // Remove any keep-alives from the beginning of the result1960 minData = connection._parseResponse(result);1961 }1962 catch (error) {1963 transportLogic.handleParseFailure(instance, result, error, tryFailConnect, instance.pollXhr);1964 return;1965 }1966 // If there's currently a timeout to trigger reconnect, fire it now before processing messages1967 if (privateData.reconnectTimeoutId !== null) {1968 fireReconnected(instance);1969 }1970 if (minData) {1971 data = transportLogic.maximizePersistentResponse(minData);1972 }1973 transportLogic.processMessages(instance, minData, fireConnect);1974 if (data &&1975 $.type(data.LongPollDelay) === "number") {1976 delay = data.LongPollDelay;1977 }1978 if (isDisconnecting(instance) === true) {1979 return;1980 }1981 shouldReconnect = data && data.ShouldReconnect;1982 if (shouldReconnect) {1983 // Transition into the reconnecting state1984 // If this fails then that means that the user transitioned the connection into a invalid state in processMessages.1985 if (!transportLogic.ensureReconnectingState(instance)) {1986 return;1987 }1988 }1989 // We never want to pass a raiseReconnect flag after a successful poll. This is handled via the error function1990 if (delay > 0) {1991 privateData.pollTimeoutId = window.setTimeout(function () {1992 poll(instance, shouldReconnect);1993 }, delay);1994 } else {1995 poll(instance, shouldReconnect);1996 }1997 },1998 error: function (data, textStatus) {1999 var error = signalR._.transportError(signalR.resources.longPollFailed, connection.transport, data, instance.pollXhr);2000 // Stop trying to trigger reconnect, connection is in an error state2001 // If we're not in the reconnect state this will noop2002 window.clearTimeout(privateData.reconnectTimeoutId);2003 privateData.reconnectTimeoutId = null;2004 if (textStatus === "abort") {2005 connection.log("Aborted xhr request.");2006 return;2007 }2008 if (!tryFailConnect(error)) {2009 // Increment our reconnect errors, we assume all errors to be reconnect errors2010 // In the case that it's our first error this will cause Reconnect to be fired2011 // after 1 second due to reconnectErrors being = 1.2012 reconnectErrors++;2013 if (connection.state !== signalR.connectionState.reconnecting) {2014 connection.log("An error occurred using longPolling. Status = " + textStatus + ". Response = " + data.responseText + ".");2015 $(instance).triggerHandler(events.onError, [error]);2016 }2017 // We check the state here to verify that we're not in an invalid state prior to verifying Reconnect.2018 // If we're not in connected or reconnecting then the next ensureReconnectingState check will fail and will return.2019 // Therefore we don't want to change that failure code path.2020 if ((connection.state === signalR.connectionState.connected ||2021 connection.state === signalR.connectionState.reconnecting) &&2022 !transportLogic.verifyLastActive(connection)) {2023 return;2024 }2025 // Transition into the reconnecting state2026 // If this fails then that means that the user transitioned the connection into the disconnected or connecting state within the above error handler trigger.2027 if (!transportLogic.ensureReconnectingState(instance)) {2028 return;2029 }2030 // Call poll with the raiseReconnect flag as true after the reconnect delay2031 privateData.pollTimeoutId = window.setTimeout(function () {2032 poll(instance, true);2033 }, that.reconnectDelay);2034 }2035 }2036 });2037 // This will only ever pass after an error has occurred via the poll ajax procedure.2038 if (reconnecting && raiseReconnect === true) {2039 // We wait to reconnect depending on how many times we've failed to reconnect.2040 // This is essentially a heuristic that will exponentially increase in wait time before2041 // triggering reconnected. This depends on the "error" handler of Poll to cancel this2042 // timeout if it triggers before the Reconnected event fires.2043 // The Math.min at the end is to ensure that the reconnect timeout does not overflow.2044 privateData.reconnectTimeoutId = window.setTimeout(function () { fireReconnected(instance); }, Math.min(1000 * (Math.pow(2, reconnectErrors) - 1), maxFireReconnectedTimeout));2045 }2046 }(connection));2047 }, 250); // Have to delay initial poll so Chrome doesn't show loader spinner in tab2048 },2049 lostConnection: function (connection) {2050 if (connection.pollXhr) {2051 connection.pollXhr.abort("lostConnection");2052 }2053 },2054 send: function (connection, data) {2055 transportLogic.ajaxSend(connection, data);2056 },2057 stop: function (connection) {2058 /// <summary>Stops the long polling connection</summary>2059 /// <param name="connection" type="signalR">The SignalR connection to stop</param>2060 window.clearTimeout(connection._.pollTimeoutId);2061 window.clearTimeout(connection._.reconnectTimeoutId);2062 delete connection._.pollTimeoutId;2063 delete connection._.reconnectTimeoutId;2064 if (connection.pollXhr) {2065 connection.pollXhr.abort();2066 connection.pollXhr = null;2067 delete connection.pollXhr;2068 }2069 },2070 abort: function (connection, async) {2071 transportLogic.ajaxAbort(connection, async);2072 }2073 };2074}(window.jQuery, window));2075/* jquery.signalR.hubs.js */2076// Copyright (c) .NET Foundation. All rights reserved.2077// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.2078/*global window:false */2079/// <reference path="jquery.signalR.core.js" />2080(function ($, window, undefined) {2081 var eventNamespace = ".hubProxy",2082 signalR = $.signalR;2083 function makeEventName(event) {2084 return event + eventNamespace;2085 }2086 // Equivalent to Array.prototype.map2087 function map(arr, fun, thisp) {2088 var i,2089 length = arr.length,2090 result = [];2091 for (i = 0; i < length; i += 1) {2092 if (arr.hasOwnProperty(i)) {2093 result[i] = fun.call(thisp, arr[i], i, arr);2094 }2095 }2096 return result;2097 }2098 function getArgValue(a) {2099 return $.isFunction(a) ? null : ($.type(a) === "undefined" ? null : a);2100 }2101 function hasMembers(obj) {2102 for (var key in obj) {2103 // If we have any properties in our callback map then we have callbacks and can exit the loop via return2104 if (obj.hasOwnProperty(key)) {2105 return true;2106 }2107 }2108 return false;2109 }2110 function clearInvocationCallbacks(connection, error) {2111 /// <param name="connection" type="hubConnection" />2112 var callbacks = connection._.invocationCallbacks,2113 callback;2114 if (hasMembers(callbacks)) {2115 connection.log("Clearing hub invocation callbacks with error: " + error + ".");2116 }2117 // Reset the callback cache now as we have a local var referencing it2118 connection._.invocationCallbackId = 0;2119 delete connection._.invocationCallbacks;2120 connection._.invocationCallbacks = {};2121 // Loop over the callbacks and invoke them.2122 // We do this using a local var reference and *after* we've cleared the cache2123 // so that if a fail callback itself tries to invoke another method we don't2124 // end up with its callback in the list we're looping over.2125 for (var callbackId in callbacks) {2126 callback = callbacks[callbackId];2127 callback.method.call(callback.scope, { E: error });2128 }2129 }2130 // hubProxy2131 function hubProxy(hubConnection, hubName) {2132 /// <summary>2133 /// Creates a new proxy object for the given hub connection that can be used to invoke2134 /// methods on server hubs and handle client method invocation requests from the server.2135 /// </summary>2136 return new hubProxy.fn.init(hubConnection, hubName);2137 }2138 hubProxy.fn = hubProxy.prototype = {2139 init: function (connection, hubName) {2140 this.state = {};2141 this.connection = connection;2142 this.hubName = hubName;2143 this._ = {2144 callbackMap: {}2145 };2146 },2147 constructor: hubProxy,2148 hasSubscriptions: function () {2149 return hasMembers(this._.callbackMap);2150 },2151 on: function (eventName, callback) {2152 /// <summary>Wires up a callback to be invoked when a invocation request is received from the server hub.</summary>2153 /// <param name="eventName" type="String">The name of the hub event to register the callback for.</param>2154 /// <param name="callback" type="Function">The callback to be invoked.</param>2155 var that = this,2156 callbackMap = that._.callbackMap;2157 // Normalize the event name to lowercase2158 eventName = eventName.toLowerCase();2159 // If there is not an event registered for this callback yet we want to create its event space in the callback map.2160 if (!callbackMap[eventName]) {2161 callbackMap[eventName] = {};2162 }2163 // Map the callback to our encompassed function2164 callbackMap[eventName][callback] = function (e, data) {2165 callback.apply(that, data);2166 };2167 $(that).bind(makeEventName(eventName), callbackMap[eventName][callback]);2168 return that;2169 },2170 off: function (eventName, callback) {2171 /// <summary>Removes the callback invocation request from the server hub for the given event name.</summary>2172 /// <param name="eventName" type="String">The name of the hub event to unregister the callback for.</param>2173 /// <param name="callback" type="Function">The callback to be invoked.</param>2174 var that = this,2175 callbackMap = that._.callbackMap,2176 callbackSpace;2177 // Normalize the event name to lowercase2178 eventName = eventName.toLowerCase();2179 callbackSpace = callbackMap[eventName];2180 // Verify that there is an event space to unbind2181 if (callbackSpace) {2182 // Only unbind if there's an event bound with eventName and a callback with the specified callback2183 if (callbackSpace[callback]) {2184 $(that).unbind(makeEventName(eventName), callbackSpace[callback]);2185 // Remove the callback from the callback map2186 delete callbackSpace[callback];2187 // Check if there are any members left on the event, if not we need to destroy it.2188 if (!hasMembers(callbackSpace)) {2189 delete callbackMap[eventName];2190 }2191 } else if (!callback) { // Check if we're removing the whole event and we didn't error because of an invalid callback2192 $(that).unbind(makeEventName(eventName));2193 delete callbackMap[eventName];2194 }2195 }2196 return that;2197 },2198 invoke: function (methodName) {2199 /// <summary>Invokes a server hub method with the given arguments.</summary>2200 /// <param name="methodName" type="String">The name of the server hub method.</param>2201 var that = this,2202 connection = that.connection,2203 args = $.makeArray(arguments).slice(1),2204 argValues = map(args, getArgValue),2205 data = { H: that.hubName, M: methodName, A: argValues, I: connection._.invocationCallbackId },2206 d = $.Deferred(),2207 callback = function (minResult) {2208 var result = that._maximizeHubResponse(minResult),2209 source,2210 error;2211 // Update the hub state2212 $.extend(that.state, result.State);2213 if (result.Progress) {2214 if (d.notifyWith) {2215 // Progress is only supported in jQuery 1.7+2216 d.notifyWith(that, [result.Progress.Data]);2217 } else if(!connection._.progressjQueryVersionLogged) {2218 connection.log("A hub method invocation progress update was received but the version of jQuery in use (" + $.prototype.jquery + ") does not support progress updates. Upgrade to jQuery 1.7+ to receive progress notifications.");2219 connection._.progressjQueryVersionLogged = true;2220 }2221 } else if (result.Error) {2222 // Server hub method threw an exception, log it & reject the deferred2223 if (result.StackTrace) {2224 connection.log(result.Error + "\n" + result.StackTrace + ".");2225 }2226 // result.ErrorData is only set if a HubException was thrown2227 source = result.IsHubException ? "HubException" : "Exception";2228 error = signalR._.error(result.Error, source);2229 error.data = result.ErrorData;2230 connection.log(that.hubName + "." + methodName + " failed to execute. Error: " + error.message);2231 d.rejectWith(that, [error]);2232 } else {2233 // Server invocation succeeded, resolve the deferred2234 connection.log("Invoked " + that.hubName + "." + methodName);2235 d.resolveWith(that, [result.Result]);2236 }2237 };2238 connection._.invocationCallbacks[connection._.invocationCallbackId.toString()] = { scope: that, method: callback };2239 connection._.invocationCallbackId += 1;2240 if (!$.isEmptyObject(that.state)) {2241 data.S = that.state;2242 }2243 connection.log("Invoking " + that.hubName + "." + methodName);2244 connection.send(data);2245 return d.promise();2246 },2247 _maximizeHubResponse: function (minHubResponse) {2248 return {2249 State: minHubResponse.S,2250 Result: minHubResponse.R,2251 Progress: minHubResponse.P ? {2252 Id: minHubResponse.P.I,2253 Data: minHubResponse.P.D2254 } : null,2255 Id: minHubResponse.I,2256 IsHubException: minHubResponse.H,2257 Error: minHubResponse.E,2258 StackTrace: minHubResponse.T,2259 ErrorData: minHubResponse.D2260 };2261 }2262 };2263 hubProxy.fn.init.prototype = hubProxy.fn;2264 // hubConnection2265 function hubConnection(url, options) {2266 /// <summary>Creates a new hub connection.</summary>2267 /// <param name="url" type="String">[Optional] The hub route url, defaults to "/signalr".</param>2268 /// <param name="options" type="Object">[Optional] Settings to use when creating the hubConnection.</param>2269 var settings = {2270 qs: null,2271 logging: false,2272 useDefaultPath: true2273 };2274 $.extend(settings, options);2275 if (!url || settings.useDefaultPath) {2276 url = (url || "") + "/signalr";2277 }2278 return new hubConnection.fn.init(url, settings);2279 }...
jquery.signalR-2.2.1.js
Source:jquery.signalR-2.2.1.js
...835 // Check if the keep alive has completely timed out836 if (timeElapsed >= keepAliveData.timeout) {837 connection.log("Keep alive timed out. Notifying transport that connection has been lost.");838 // Notify transport that the connection has been lost839 connection.transport.lostConnection(connection);840 } else if (timeElapsed >= keepAliveData.timeoutWarning) {841 // This is to assure that the user only gets a single warning842 if (!keepAliveData.userNotified) {843 connection.log("Keep alive has been missed, connection may be dead/slow.");844 $(connection).triggerHandler(events.onConnectionSlow);845 keepAliveData.userNotified = true;846 }847 } else {848 keepAliveData.userNotified = false;849 }850 }851 }852 function getAjaxUrl(connection, path) {853 var url = connection.url + path;854 if (connection.transport) {855 url += "?transport=" + connection.transport.name;856 }857 return transportLogic.prepareQueryString(connection, url);858 }859 function InitHandler(connection) {860 this.connection = connection;861 this.startRequested = false;862 this.startCompleted = false;863 this.connectionStopped = false;864 }865 InitHandler.prototype = {866 start: function (transport, onSuccess, onFallback) {867 var that = this,868 connection = that.connection,869 failCalled = false;870 if (that.startRequested || that.connectionStopped) {871 connection.log("WARNING! " + transport.name + " transport cannot be started. Initialization ongoing or completed.");872 return;873 }874 connection.log(transport.name + " transport starting.");875 transport.start(connection, function () {876 if (!failCalled) {877 that.initReceived(transport, onSuccess);878 }879 }, function (error) {880 // Don't allow the same transport to cause onFallback to be called twice881 if (!failCalled) {882 failCalled = true;883 that.transportFailed(transport, error, onFallback);884 }885 // Returns true if the transport should stop;886 // false if it should attempt to reconnect887 return !that.startCompleted || that.connectionStopped;888 });889 that.transportTimeoutHandle = window.setTimeout(function () {890 if (!failCalled) {891 failCalled = true;892 connection.log(transport.name + " transport timed out when trying to connect.");893 that.transportFailed(transport, undefined, onFallback);894 }895 }, connection._.totalTransportConnectTimeout);896 },897 stop: function () {898 this.connectionStopped = true;899 window.clearTimeout(this.transportTimeoutHandle);900 signalR.transports._logic.tryAbortStartRequest(this.connection);901 },902 initReceived: function (transport, onSuccess) {903 var that = this,904 connection = that.connection;905 if (that.startRequested) {906 connection.log("WARNING! The client received multiple init messages.");907 return;908 }909 if (that.connectionStopped) {910 return;911 }912 that.startRequested = true;913 window.clearTimeout(that.transportTimeoutHandle);914 connection.log(transport.name + " transport connected. Initiating start request.");915 signalR.transports._logic.ajaxStart(connection, function () {916 that.startCompleted = true;917 onSuccess();918 });919 },920 transportFailed: function (transport, error, onFallback) {921 var connection = this.connection,922 deferred = connection._deferral,923 wrappedError;924 if (this.connectionStopped) {925 return;926 }927 window.clearTimeout(this.transportTimeoutHandle);928 if (!this.startRequested) {929 transport.stop(connection);930 connection.log(transport.name + " transport failed to connect. Attempting to fall back.");931 onFallback();932 } else if (!this.startCompleted) {933 // Do not attempt to fall back if a start request is ongoing during a transport failure.934 // Instead, trigger an error and stop the connection.935 wrappedError = signalR._.error(signalR.resources.errorDuringStartRequest, error);936 connection.log(transport.name + " transport failed during the start request. Stopping the connection.");937 $(connection).triggerHandler(events.onError, [wrappedError]);938 if (deferred) {939 deferred.reject(wrappedError);940 }941 connection.stop();942 } else {943 // The start request has completed, but the connection has not stopped.944 // No need to do anything here. The transport should attempt its normal reconnect logic.945 }946 }947 };948 transportLogic = signalR.transports._logic = {949 ajax: function (connection, options) {950 return $.ajax(951 $.extend(/*deep copy*/ true, {}, $.signalR.ajaxDefaults, {952 type: "GET",953 data: {},954 xhrFields: { withCredentials: connection.withCredentials },955 contentType: connection.contentType,956 dataType: connection.ajaxDataType957 }, options));958 },959 pingServer: function (connection) {960 /// <summary>Pings the server</summary>961 /// <param name="connection" type="signalr">Connection associated with the server ping</param>962 /// <returns type="signalR" />963 var url,964 xhr,965 deferral = $.Deferred();966 if (connection.transport) {967 url = connection.url + "/ping";968 url = transportLogic.addQs(url, connection.qs);969 xhr = transportLogic.ajax(connection, {970 url: url,971 success: function (result) {972 var data;973 try {974 data = connection._parseResponse(result);975 }976 catch (error) {977 deferral.reject(978 signalR._.transportError(979 signalR.resources.pingServerFailedParse,980 connection.transport,981 error,982 xhr983 )984 );985 connection.stop();986 return;987 }988 if (data.Response === "pong") {989 deferral.resolve();990 }991 else {992 deferral.reject(993 signalR._.transportError(994 signalR._.format(signalR.resources.pingServerFailedInvalidResponse, result),995 connection.transport,996 null /* error */,997 xhr998 )999 );1000 }1001 },1002 error: function (error) {1003 if (error.status === 401 || error.status === 403) {1004 deferral.reject(1005 signalR._.transportError(1006 signalR._.format(signalR.resources.pingServerFailedStatusCode, error.status),1007 connection.transport,1008 error,1009 xhr1010 )1011 );1012 connection.stop();1013 }1014 else {1015 deferral.reject(1016 signalR._.transportError(1017 signalR.resources.pingServerFailed,1018 connection.transport,1019 error,1020 xhr1021 )1022 );1023 }1024 }1025 });1026 }1027 else {1028 deferral.reject(1029 signalR._.transportError(1030 signalR.resources.noConnectionTransport,1031 connection.transport1032 )1033 );1034 }1035 return deferral.promise();1036 },1037 prepareQueryString: function (connection, url) {1038 var preparedUrl;1039 // Use addQs to start since it handles the ?/& prefix for us1040 preparedUrl = transportLogic.addQs(url, "clientProtocol=" + connection.clientProtocol);1041 // Add the user-specified query string params if any1042 preparedUrl = transportLogic.addQs(preparedUrl, connection.qs);1043 if (connection.token) {1044 preparedUrl += "&connectionToken=" + window.encodeURIComponent(connection.token);1045 }1046 if (connection.data) {1047 preparedUrl += "&connectionData=" + window.encodeURIComponent(connection.data);1048 }1049 return preparedUrl;1050 },1051 addQs: function (url, qs) {1052 var appender = url.indexOf("?") !== -1 ? "&" : "?",1053 firstChar;1054 if (!qs) {1055 return url;1056 }1057 if (typeof (qs) === "object") {1058 return url + appender + $.param(qs);1059 }1060 if (typeof (qs) === "string") {1061 firstChar = qs.charAt(0);1062 if (firstChar === "?" || firstChar === "&") {1063 appender = "";1064 }1065 return url + appender + qs;1066 }1067 throw new Error("Query string property must be either a string or object.");1068 },1069 // BUG #2953: The url needs to be same otherwise it will cause a memory leak1070 getUrl: function (connection, transport, reconnecting, poll, ajaxPost) {1071 /// <summary>Gets the url for making a GET based connect request</summary>1072 var baseUrl = transport === "webSockets" ? "" : connection.baseUrl,1073 url = baseUrl + connection.appRelativeUrl,1074 qs = "transport=" + transport;1075 if (!ajaxPost && connection.groupsToken) {1076 qs += "&groupsToken=" + window.encodeURIComponent(connection.groupsToken);1077 }1078 if (!reconnecting) {1079 url += "/connect";1080 } else {1081 if (poll) {1082 // longPolling transport specific1083 url += "/poll";1084 } else {1085 url += "/reconnect";1086 }1087 if (!ajaxPost && connection.messageId) {1088 qs += "&messageId=" + window.encodeURIComponent(connection.messageId);1089 }1090 }1091 url += "?" + qs;1092 url = transportLogic.prepareQueryString(connection, url);1093 if (!ajaxPost) {1094 url += "&tid=" + Math.floor(Math.random() * 11);1095 }1096 return url;1097 },1098 maximizePersistentResponse: function (minPersistentResponse) {1099 return {1100 MessageId: minPersistentResponse.C,1101 Messages: minPersistentResponse.M,1102 Initialized: typeof (minPersistentResponse.S) !== "undefined" ? true : false,1103 ShouldReconnect: typeof (minPersistentResponse.T) !== "undefined" ? true : false,1104 LongPollDelay: minPersistentResponse.L,1105 GroupsToken: minPersistentResponse.G1106 };1107 },1108 updateGroups: function (connection, groupsToken) {1109 if (groupsToken) {1110 connection.groupsToken = groupsToken;1111 }1112 },1113 stringifySend: function (connection, message) {1114 if (typeof (message) === "string" || typeof (message) === "undefined" || message === null) {1115 return message;1116 }1117 return connection.json.stringify(message);1118 },1119 ajaxSend: function (connection, data) {1120 var payload = transportLogic.stringifySend(connection, data),1121 url = getAjaxUrl(connection, "/send"),1122 xhr,1123 onFail = function (error, connection) {1124 $(connection).triggerHandler(events.onError, [signalR._.transportError(signalR.resources.sendFailed, connection.transport, error, xhr), data]);1125 };1126 xhr = transportLogic.ajax(connection, {1127 url: url,1128 type: connection.ajaxDataType === "jsonp" ? "GET" : "POST",1129 contentType: signalR._.defaultContentType,1130 data: {1131 data: payload1132 },1133 success: function (result) {1134 var res;1135 if (result) {1136 try {1137 res = connection._parseResponse(result);1138 }1139 catch (error) {1140 onFail(error, connection);1141 connection.stop();1142 return;1143 }1144 transportLogic.triggerReceived(connection, res);1145 }1146 },1147 error: function (error, textStatus) {1148 if (textStatus === "abort" || textStatus === "parsererror") {1149 // The parsererror happens for sends that don't return any data, and hence1150 // don't write the jsonp callback to the response. This is harder to fix on the server1151 // so just hack around it on the client for now.1152 return;1153 }1154 onFail(error, connection);1155 }1156 });1157 return xhr;1158 },1159 ajaxAbort: function (connection, async) {1160 if (typeof (connection.transport) === "undefined") {1161 return;1162 }1163 // Async by default unless explicitly overidden1164 async = typeof async === "undefined" ? true : async;1165 var url = getAjaxUrl(connection, "/abort");1166 transportLogic.ajax(connection, {1167 url: url,1168 async: async,1169 timeout: 1000,1170 type: "POST"1171 });1172 connection.log("Fired ajax abort async = " + async + ".");1173 },1174 ajaxStart: function (connection, onSuccess) {1175 var rejectDeferred = function (error) {1176 var deferred = connection._deferral;1177 if (deferred) {1178 deferred.reject(error);1179 }1180 },1181 triggerStartError = function (error) {1182 connection.log("The start request failed. Stopping the connection.");1183 $(connection).triggerHandler(events.onError, [error]);1184 rejectDeferred(error);1185 connection.stop();1186 };1187 connection._.startRequest = transportLogic.ajax(connection, {1188 url: getAjaxUrl(connection, "/start"),1189 success: function (result, statusText, xhr) {1190 var data;1191 try {1192 data = connection._parseResponse(result);1193 } catch (error) {1194 triggerStartError(signalR._.error(1195 signalR._.format(signalR.resources.errorParsingStartResponse, result),1196 error, xhr));1197 return;1198 }1199 if (data.Response === "started") {1200 onSuccess();1201 } else {1202 triggerStartError(signalR._.error(1203 signalR._.format(signalR.resources.invalidStartResponse, result),1204 null /* error */, xhr));1205 }1206 },1207 error: function (xhr, statusText, error) {1208 if (statusText !== startAbortText) {1209 triggerStartError(signalR._.error(1210 signalR.resources.errorDuringStartRequest,1211 error, xhr));1212 } else {1213 // Stop has been called, no need to trigger the error handler1214 // or stop the connection again with onStartError1215 connection.log("The start request aborted because connection.stop() was called.");1216 rejectDeferred(signalR._.error(1217 signalR.resources.stoppedDuringStartRequest,1218 null /* error */, xhr));1219 }1220 }1221 });1222 },1223 tryAbortStartRequest: function (connection) {1224 if (connection._.startRequest) {1225 // If the start request has already completed this will noop.1226 connection._.startRequest.abort(startAbortText);1227 delete connection._.startRequest;1228 }1229 },1230 tryInitialize: function (connection, persistentResponse, onInitialized) {1231 if (persistentResponse.Initialized && onInitialized) {1232 onInitialized();1233 } else if (persistentResponse.Initialized) {1234 connection.log("WARNING! The client received an init message after reconnecting.");1235 }1236 },1237 triggerReceived: function (connection, data) {1238 if (!connection._.connectingMessageBuffer.tryBuffer(data)) {1239 $(connection).triggerHandler(events.onReceived, [data]);1240 }1241 },1242 processMessages: function (connection, minData, onInitialized) {1243 var data;1244 // Update the last message time stamp1245 transportLogic.markLastMessage(connection);1246 if (minData) {1247 data = transportLogic.maximizePersistentResponse(minData);1248 transportLogic.updateGroups(connection, data.GroupsToken);1249 if (data.MessageId) {1250 connection.messageId = data.MessageId;1251 }1252 if (data.Messages) {1253 $.each(data.Messages, function (index, message) {1254 transportLogic.triggerReceived(connection, message);1255 });1256 transportLogic.tryInitialize(connection, data, onInitialized);1257 }1258 }1259 },1260 monitorKeepAlive: function (connection) {1261 var keepAliveData = connection._.keepAliveData;1262 // If we haven't initiated the keep alive timeouts then we need to1263 if (!keepAliveData.monitoring) {1264 keepAliveData.monitoring = true;1265 transportLogic.markLastMessage(connection);1266 // Save the function so we can unbind it on stop1267 connection._.keepAliveData.reconnectKeepAliveUpdate = function () {1268 // Mark a new message so that keep alive doesn't time out connections1269 transportLogic.markLastMessage(connection);1270 };1271 // Update Keep alive on reconnect1272 $(connection).bind(events.onReconnect, connection._.keepAliveData.reconnectKeepAliveUpdate);1273 connection.log("Now monitoring keep alive with a warning timeout of " + keepAliveData.timeoutWarning + ", keep alive timeout of " + keepAliveData.timeout + " and disconnecting timeout of " + connection.disconnectTimeout);1274 } else {1275 connection.log("Tried to monitor keep alive but it's already being monitored.");1276 }1277 },1278 stopMonitoringKeepAlive: function (connection) {1279 var keepAliveData = connection._.keepAliveData;1280 // Only attempt to stop the keep alive monitoring if its being monitored1281 if (keepAliveData.monitoring) {1282 // Stop monitoring1283 keepAliveData.monitoring = false;1284 // Remove the updateKeepAlive function from the reconnect event1285 $(connection).unbind(events.onReconnect, connection._.keepAliveData.reconnectKeepAliveUpdate);1286 // Clear all the keep alive data1287 connection._.keepAliveData = {};1288 connection.log("Stopping the monitoring of the keep alive.");1289 }1290 },1291 startHeartbeat: function (connection) {1292 connection._.lastActiveAt = new Date().getTime();1293 beat(connection);1294 },1295 markLastMessage: function (connection) {1296 connection._.lastMessageAt = new Date().getTime();1297 },1298 markActive: function (connection) {1299 if (transportLogic.verifyLastActive(connection)) {1300 connection._.lastActiveAt = new Date().getTime();1301 return true;1302 }1303 return false;1304 },1305 isConnectedOrReconnecting: function (connection) {1306 return connection.state === signalR.connectionState.connected ||1307 connection.state === signalR.connectionState.reconnecting;1308 },1309 ensureReconnectingState: function (connection) {1310 if (changeState(connection,1311 signalR.connectionState.connected,1312 signalR.connectionState.reconnecting) === true) {1313 $(connection).triggerHandler(events.onReconnecting);1314 }1315 return connection.state === signalR.connectionState.reconnecting;1316 },1317 clearReconnectTimeout: function (connection) {1318 if (connection && connection._.reconnectTimeout) {1319 window.clearTimeout(connection._.reconnectTimeout);1320 delete connection._.reconnectTimeout;1321 }1322 },1323 verifyLastActive: function (connection) {1324 if (new Date().getTime() - connection._.lastActiveAt >= connection.reconnectWindow) {1325 var message = signalR._.format(signalR.resources.reconnectWindowTimeout, new Date(connection._.lastActiveAt), connection.reconnectWindow);1326 connection.log(message);1327 $(connection).triggerHandler(events.onError, [signalR._.error(message, /* source */ "TimeoutException")]);1328 connection.stop(/* async */ false, /* notifyServer */ false);1329 return false;1330 }1331 return true;1332 },1333 reconnect: function (connection, transportName) {1334 var transport = signalR.transports[transportName];1335 // We should only set a reconnectTimeout if we are currently connected1336 // and a reconnectTimeout isn't already set.1337 if (transportLogic.isConnectedOrReconnecting(connection) && !connection._.reconnectTimeout) {1338 // Need to verify before the setTimeout occurs because an application sleep could occur during the setTimeout duration.1339 if (!transportLogic.verifyLastActive(connection)) {1340 return;1341 }1342 connection._.reconnectTimeout = window.setTimeout(function () {1343 if (!transportLogic.verifyLastActive(connection)) {1344 return;1345 }1346 transport.stop(connection);1347 if (transportLogic.ensureReconnectingState(connection)) {1348 connection.log(transportName + " reconnecting.");1349 transport.start(connection);1350 }1351 }, connection.reconnectDelay);1352 }1353 },1354 handleParseFailure: function (connection, result, error, onFailed, context) {1355 var wrappedError = signalR._.transportError(1356 signalR._.format(signalR.resources.parseFailed, result),1357 connection.transport,1358 error,1359 context);1360 // If we're in the initialization phase trigger onFailed, otherwise stop the connection.1361 if (onFailed && onFailed(wrappedError)) {1362 connection.log("Failed to parse server response while attempting to connect.");1363 } else {1364 $(connection).triggerHandler(events.onError, [wrappedError]);1365 connection.stop();1366 }1367 },1368 initHandler: function (connection) {1369 return new InitHandler(connection);1370 },1371 foreverFrame: {1372 count: 0,1373 connections: {}1374 }1375 };1376}(window.jQuery, window));1377/* jquery.signalR.transports.webSockets.js */1378// Copyright (c) .NET Foundation. All rights reserved.1379// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.1380/*global window:false */1381/// <reference path="jquery.signalR.transports.common.js" />1382(function ($, window, undefined) {1383 var signalR = $.signalR,1384 events = $.signalR.events,1385 changeState = $.signalR.changeState,1386 transportLogic = signalR.transports._logic;1387 signalR.transports.webSockets = {1388 name: "webSockets",1389 supportsKeepAlive: function () {1390 return true;1391 },1392 send: function (connection, data) {1393 var payload = transportLogic.stringifySend(connection, data);1394 try {1395 connection.socket.send(payload);1396 } catch (ex) {1397 $(connection).triggerHandler(events.onError,1398 [signalR._.transportError(1399 signalR.resources.webSocketsInvalidState,1400 connection.transport,1401 ex,1402 connection.socket1403 ),1404 data]);1405 }1406 },1407 start: function (connection, onSuccess, onFailed) {1408 var url,1409 opened = false,1410 that = this,1411 reconnecting = !onSuccess,1412 $connection = $(connection);1413 if (!window.WebSocket) {1414 onFailed();1415 return;1416 }1417 if (!connection.socket) {1418 if (connection.webSocketServerUrl) {1419 url = connection.webSocketServerUrl;1420 } else {1421 url = connection.wsProtocol + connection.host;1422 }1423 url += transportLogic.getUrl(connection, this.name, reconnecting);1424 connection.log("Connecting to websocket endpoint '" + url + "'.");1425 connection.socket = new window.WebSocket(url);1426 connection.socket.onopen = function () {1427 opened = true;1428 connection.log("Websocket opened.");1429 transportLogic.clearReconnectTimeout(connection);1430 if (changeState(connection,1431 signalR.connectionState.reconnecting,1432 signalR.connectionState.connected) === true) {1433 $connection.triggerHandler(events.onReconnect);1434 }1435 };1436 connection.socket.onclose = function (event) {1437 var error;1438 // Only handle a socket close if the close is from the current socket.1439 // Sometimes on disconnect the server will push down an onclose event1440 // to an expired socket.1441 if (this === connection.socket) {1442 if (opened && typeof event.wasClean !== "undefined" && event.wasClean === false) {1443 // Ideally this would use the websocket.onerror handler (rather than checking wasClean in onclose) but1444 // I found in some circumstances Chrome won't call onerror. This implementation seems to work on all browsers.1445 error = signalR._.transportError(1446 signalR.resources.webSocketClosed,1447 connection.transport,1448 event);1449 connection.log("Unclean disconnect from websocket: " + (event.reason || "[no reason given]."));1450 } else {1451 connection.log("Websocket closed.");1452 }1453 if (!onFailed || !onFailed(error)) {1454 if (error) {1455 $(connection).triggerHandler(events.onError, [error]);1456 }1457 that.reconnect(connection);1458 }1459 }1460 };1461 connection.socket.onmessage = function (event) {1462 var data;1463 try {1464 data = connection._parseResponse(event.data);1465 }1466 catch (error) {1467 transportLogic.handleParseFailure(connection, event.data, error, onFailed, event);1468 return;1469 }1470 if (data) {1471 // data.M is PersistentResponse.Messages1472 if ($.isEmptyObject(data) || data.M) {1473 transportLogic.processMessages(connection, data, onSuccess);1474 } else {1475 // For websockets we need to trigger onReceived1476 // for callbacks to outgoing hub calls.1477 transportLogic.triggerReceived(connection, data);1478 }1479 }1480 };1481 }1482 },1483 reconnect: function (connection) {1484 transportLogic.reconnect(connection, this.name);1485 },1486 lostConnection: function (connection) {1487 this.reconnect(connection);1488 },1489 stop: function (connection) {1490 // Don't trigger a reconnect after stopping1491 transportLogic.clearReconnectTimeout(connection);1492 if (connection.socket) {1493 connection.log("Closing the Websocket.");1494 connection.socket.close();1495 connection.socket = null;1496 }1497 },1498 abort: function (connection, async) {1499 transportLogic.ajaxAbort(connection, async);1500 }1501 };1502}(window.jQuery, window));1503/* jquery.signalR.transports.serverSentEvents.js */1504// Copyright (c) .NET Foundation. All rights reserved.1505// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.1506/*global window:false */1507/// <reference path="jquery.signalR.transports.common.js" />1508(function ($, window, undefined) {1509 var signalR = $.signalR,1510 events = $.signalR.events,1511 changeState = $.signalR.changeState,1512 transportLogic = signalR.transports._logic,1513 clearReconnectAttemptTimeout = function (connection) {1514 window.clearTimeout(connection._.reconnectAttemptTimeoutHandle);1515 delete connection._.reconnectAttemptTimeoutHandle;1516 };1517 signalR.transports.serverSentEvents = {1518 name: "serverSentEvents",1519 supportsKeepAlive: function () {1520 return true;1521 },1522 timeOut: 3000,1523 start: function (connection, onSuccess, onFailed) {1524 var that = this,1525 opened = false,1526 $connection = $(connection),1527 reconnecting = !onSuccess,1528 url;1529 if (connection.eventSource) {1530 connection.log("The connection already has an event source. Stopping it.");1531 connection.stop();1532 }1533 if (!window.EventSource) {1534 if (onFailed) {1535 connection.log("This browser doesn't support SSE.");1536 onFailed();1537 }1538 return;1539 }1540 url = transportLogic.getUrl(connection, this.name, reconnecting);1541 try {1542 connection.log("Attempting to connect to SSE endpoint '" + url + "'.");1543 connection.eventSource = new window.EventSource(url, { withCredentials: connection.withCredentials });1544 }1545 catch (e) {1546 connection.log("EventSource failed trying to connect with error " + e.Message + ".");1547 if (onFailed) {1548 // The connection failed, call the failed callback1549 onFailed();1550 } else {1551 $connection.triggerHandler(events.onError, [signalR._.transportError(signalR.resources.eventSourceFailedToConnect, connection.transport, e)]);1552 if (reconnecting) {1553 // If we were reconnecting, rather than doing initial connect, then try reconnect again1554 that.reconnect(connection);1555 }1556 }1557 return;1558 }1559 if (reconnecting) {1560 connection._.reconnectAttemptTimeoutHandle = window.setTimeout(function () {1561 if (opened === false) {1562 // If we're reconnecting and the event source is attempting to connect,1563 // don't keep retrying. This causes duplicate connections to spawn.1564 if (connection.eventSource.readyState !== window.EventSource.OPEN) {1565 // If we were reconnecting, rather than doing initial connect, then try reconnect again1566 that.reconnect(connection);1567 }1568 }1569 },1570 that.timeOut);1571 }1572 connection.eventSource.addEventListener("open", function (e) {1573 connection.log("EventSource connected.");1574 clearReconnectAttemptTimeout(connection);1575 transportLogic.clearReconnectTimeout(connection);1576 if (opened === false) {1577 opened = true;1578 if (changeState(connection,1579 signalR.connectionState.reconnecting,1580 signalR.connectionState.connected) === true) {1581 $connection.triggerHandler(events.onReconnect);1582 }1583 }1584 }, false);1585 connection.eventSource.addEventListener("message", function (e) {1586 var res;1587 // process messages1588 if (e.data === "initialized") {1589 return;1590 }1591 try {1592 res = connection._parseResponse(e.data);1593 }1594 catch (error) {1595 transportLogic.handleParseFailure(connection, e.data, error, onFailed, e);1596 return;1597 }1598 transportLogic.processMessages(connection, res, onSuccess);1599 }, false);1600 connection.eventSource.addEventListener("error", function (e) {1601 var error = signalR._.transportError(1602 signalR.resources.eventSourceError,1603 connection.transport,1604 e);1605 // Only handle an error if the error is from the current Event Source.1606 // Sometimes on disconnect the server will push down an error event1607 // to an expired Event Source.1608 if (this !== connection.eventSource) {1609 return;1610 }1611 if (onFailed && onFailed(error)) {1612 return;1613 }1614 connection.log("EventSource readyState: " + connection.eventSource.readyState + ".");1615 if (e.eventPhase === window.EventSource.CLOSED) {1616 // We don't use the EventSource's native reconnect function as it1617 // doesn't allow us to change the URL when reconnecting. We need1618 // to change the URL to not include the /connect suffix, and pass1619 // the last message id we received.1620 connection.log("EventSource reconnecting due to the server connection ending.");1621 that.reconnect(connection);1622 } else {1623 // connection error1624 connection.log("EventSource error.");1625 $connection.triggerHandler(events.onError, [error]);1626 }1627 }, false);1628 },1629 reconnect: function (connection) {1630 transportLogic.reconnect(connection, this.name);1631 },1632 lostConnection: function (connection) {1633 this.reconnect(connection);1634 },1635 send: function (connection, data) {1636 transportLogic.ajaxSend(connection, data);1637 },1638 stop: function (connection) {1639 // Don't trigger a reconnect after stopping1640 clearReconnectAttemptTimeout(connection);1641 transportLogic.clearReconnectTimeout(connection);1642 if (connection && connection.eventSource) {1643 connection.log("EventSource calling close().");1644 connection.eventSource.close();1645 connection.eventSource = null;1646 delete connection.eventSource;1647 }1648 },1649 abort: function (connection, async) {1650 transportLogic.ajaxAbort(connection, async);1651 }1652 };1653}(window.jQuery, window));1654/* jquery.signalR.transports.foreverFrame.js */1655// Copyright (c) .NET Foundation. All rights reserved.1656// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.1657/*global window:false */1658/// <reference path="jquery.signalR.transports.common.js" />1659(function ($, window, undefined) {1660 var signalR = $.signalR,1661 events = $.signalR.events,1662 changeState = $.signalR.changeState,1663 transportLogic = signalR.transports._logic,1664 createFrame = function () {1665 var frame = window.document.createElement("iframe");1666 frame.setAttribute("style", "position:absolute;top:0;left:0;width:0;height:0;visibility:hidden;");1667 return frame;1668 },1669 // Used to prevent infinite loading icon spins in older versions of ie1670 // We build this object inside a closure so we don't pollute the rest of1671 // the foreverFrame transport with unnecessary functions/utilities.1672 loadPreventer = (function () {1673 var loadingFixIntervalId = null,1674 loadingFixInterval = 1000,1675 attachedTo = 0;1676 return {1677 prevent: function () {1678 // Prevent additional iframe removal procedures from newer browsers1679 if (signalR._.ieVersion <= 8) {1680 // We only ever want to set the interval one time, so on the first attachedTo1681 if (attachedTo === 0) {1682 // Create and destroy iframe every 3 seconds to prevent loading icon, super hacky1683 loadingFixIntervalId = window.setInterval(function () {1684 var tempFrame = createFrame();1685 window.document.body.appendChild(tempFrame);1686 window.document.body.removeChild(tempFrame);1687 tempFrame = null;1688 }, loadingFixInterval);1689 }1690 attachedTo++;1691 }1692 },1693 cancel: function () {1694 // Only clear the interval if there's only one more object that the loadPreventer is attachedTo1695 if (attachedTo === 1) {1696 window.clearInterval(loadingFixIntervalId);1697 }1698 if (attachedTo > 0) {1699 attachedTo--;1700 }1701 }1702 };1703 })();1704 signalR.transports.foreverFrame = {1705 name: "foreverFrame",1706 supportsKeepAlive: function () {1707 return true;1708 },1709 // Added as a value here so we can create tests to verify functionality1710 iframeClearThreshold: 50,1711 start: function (connection, onSuccess, onFailed) {1712 var that = this,1713 frameId = (transportLogic.foreverFrame.count += 1),1714 url,1715 frame = createFrame(),1716 frameLoadHandler = function () {1717 connection.log("Forever frame iframe finished loading and is no longer receiving messages.");1718 if (!onFailed || !onFailed()) {1719 that.reconnect(connection);1720 }1721 };1722 if (window.EventSource) {1723 // If the browser supports SSE, don't use Forever Frame1724 if (onFailed) {1725 connection.log("Forever Frame is not supported by SignalR on browsers with SSE support.");1726 onFailed();1727 }1728 return;1729 }1730 frame.setAttribute("data-signalr-connection-id", connection.id);1731 // Start preventing loading icon1732 // This will only perform work if the loadPreventer is not attached to another connection.1733 loadPreventer.prevent();1734 // Build the url1735 url = transportLogic.getUrl(connection, this.name);1736 url += "&frameId=" + frameId;1737 // add frame to the document prior to setting URL to avoid caching issues.1738 window.document.documentElement.appendChild(frame);1739 connection.log("Binding to iframe's load event.");1740 if (frame.addEventListener) {1741 frame.addEventListener("load", frameLoadHandler, false);1742 } else if (frame.attachEvent) {1743 frame.attachEvent("onload", frameLoadHandler);1744 }1745 frame.src = url;1746 transportLogic.foreverFrame.connections[frameId] = connection;1747 connection.frame = frame;1748 connection.frameId = frameId;1749 if (onSuccess) {1750 connection.onSuccess = function () {1751 connection.log("Iframe transport started.");1752 onSuccess();1753 };1754 }1755 },1756 reconnect: function (connection) {1757 var that = this;1758 // Need to verify connection state and verify before the setTimeout occurs because an application sleep could occur during the setTimeout duration.1759 if (transportLogic.isConnectedOrReconnecting(connection) && transportLogic.verifyLastActive(connection)) {1760 window.setTimeout(function () {1761 // Verify that we're ok to reconnect.1762 if (!transportLogic.verifyLastActive(connection)) {1763 return;1764 }1765 if (connection.frame && transportLogic.ensureReconnectingState(connection)) {1766 var frame = connection.frame,1767 src = transportLogic.getUrl(connection, that.name, true) + "&frameId=" + connection.frameId;1768 connection.log("Updating iframe src to '" + src + "'.");1769 frame.src = src;1770 }1771 }, connection.reconnectDelay);1772 }1773 },1774 lostConnection: function (connection) {1775 this.reconnect(connection);1776 },1777 send: function (connection, data) {1778 transportLogic.ajaxSend(connection, data);1779 },1780 receive: function (connection, data) {1781 var cw,1782 body,1783 response;1784 if (connection.json !== connection._originalJson) {1785 // If there's a custom JSON parser configured then serialize the object1786 // using the original (browser) JSON parser and then deserialize it using1787 // the custom parser (connection._parseResponse does that). This is so we1788 // can easily send the response from the server as "raw" JSON but still1789 // support custom JSON deserialization in the browser.1790 data = connection._originalJson.stringify(data);1791 }1792 response = connection._parseResponse(data);1793 transportLogic.processMessages(connection, response, connection.onSuccess);1794 // Protect against connection stopping from a callback trigger within the processMessages above.1795 if (connection.state === $.signalR.connectionState.connected) {1796 // Delete the script & div elements1797 connection.frameMessageCount = (connection.frameMessageCount || 0) + 1;1798 if (connection.frameMessageCount > signalR.transports.foreverFrame.iframeClearThreshold) {1799 connection.frameMessageCount = 0;1800 cw = connection.frame.contentWindow || connection.frame.contentDocument;1801 if (cw && cw.document && cw.document.body) {1802 body = cw.document.body;1803 // Remove all the child elements from the iframe's body to conserver memory1804 while (body.firstChild) {1805 body.removeChild(body.firstChild);1806 }1807 }1808 }1809 }1810 },1811 stop: function (connection) {1812 var cw = null;1813 // Stop attempting to prevent loading icon1814 loadPreventer.cancel();1815 if (connection.frame) {1816 if (connection.frame.stop) {1817 connection.frame.stop();1818 } else {1819 try {1820 cw = connection.frame.contentWindow || connection.frame.contentDocument;1821 if (cw.document && cw.document.execCommand) {1822 cw.document.execCommand("Stop");1823 }1824 }1825 catch (e) {1826 connection.log("Error occurred when stopping foreverFrame transport. Message = " + e.message + ".");1827 }1828 }1829 // Ensure the iframe is where we left it1830 if (connection.frame.parentNode === window.document.body) {1831 window.document.body.removeChild(connection.frame);1832 }1833 delete transportLogic.foreverFrame.connections[connection.frameId];1834 connection.frame = null;1835 connection.frameId = null;1836 delete connection.frame;1837 delete connection.frameId;1838 delete connection.onSuccess;1839 delete connection.frameMessageCount;1840 connection.log("Stopping forever frame.");1841 }1842 },1843 abort: function (connection, async) {1844 transportLogic.ajaxAbort(connection, async);1845 },1846 getConnection: function (id) {1847 return transportLogic.foreverFrame.connections[id];1848 },1849 started: function (connection) {1850 if (changeState(connection,1851 signalR.connectionState.reconnecting,1852 signalR.connectionState.connected) === true) {1853 $(connection).triggerHandler(events.onReconnect);1854 }1855 }1856 };1857}(window.jQuery, window));1858/* jquery.signalR.transports.longPolling.js */1859// Copyright (c) .NET Foundation. All rights reserved.1860// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.1861/*global window:false */1862/// <reference path="jquery.signalR.transports.common.js" />1863(function ($, window, undefined) {1864 var signalR = $.signalR,1865 events = $.signalR.events,1866 changeState = $.signalR.changeState,1867 isDisconnecting = $.signalR.isDisconnecting,1868 transportLogic = signalR.transports._logic;1869 signalR.transports.longPolling = {1870 name: "longPolling",1871 supportsKeepAlive: function () {1872 return false;1873 },1874 reconnectDelay: 3000,1875 start: function (connection, onSuccess, onFailed) {1876 /// <summary>Starts the long polling connection</summary>1877 /// <param name="connection" type="signalR">The SignalR connection to start</param>1878 var that = this,1879 fireConnect = function () {1880 fireConnect = $.noop;1881 connection.log("LongPolling connected.");1882 if (onSuccess) {1883 onSuccess();1884 } else {1885 connection.log("WARNING! The client received an init message after reconnecting.");1886 }1887 },1888 tryFailConnect = function (error) {1889 if (onFailed(error)) {1890 connection.log("LongPolling failed to connect.");1891 return true;1892 }1893 return false;1894 },1895 privateData = connection._,1896 reconnectErrors = 0,1897 fireReconnected = function (instance) {1898 window.clearTimeout(privateData.reconnectTimeoutId);1899 privateData.reconnectTimeoutId = null;1900 if (changeState(instance,1901 signalR.connectionState.reconnecting,1902 signalR.connectionState.connected) === true) {1903 // Successfully reconnected!1904 instance.log("Raising the reconnect event");1905 $(instance).triggerHandler(events.onReconnect);1906 }1907 },1908 // 1 hour1909 maxFireReconnectedTimeout = 3600000;1910 if (connection.pollXhr) {1911 connection.log("Polling xhr requests already exists, aborting.");1912 connection.stop();1913 }1914 connection.messageId = null;1915 privateData.reconnectTimeoutId = null;1916 privateData.pollTimeoutId = window.setTimeout(function () {1917 (function poll(instance, raiseReconnect) {1918 var messageId = instance.messageId,1919 connect = (messageId === null),1920 reconnecting = !connect,1921 polling = !raiseReconnect,1922 url = transportLogic.getUrl(instance, that.name, reconnecting, polling, true /* use Post for longPolling */),1923 postData = {};1924 if (instance.messageId) {1925 postData.messageId = instance.messageId;1926 }1927 if (instance.groupsToken) {1928 postData.groupsToken = instance.groupsToken;1929 }1930 // If we've disconnected during the time we've tried to re-instantiate the poll then stop.1931 if (isDisconnecting(instance) === true) {1932 return;1933 }1934 connection.log("Opening long polling request to '" + url + "'.");1935 instance.pollXhr = transportLogic.ajax(connection, {1936 xhrFields: {1937 onprogress: function () {1938 transportLogic.markLastMessage(connection);1939 }1940 },1941 url: url,1942 type: "POST",1943 contentType: signalR._.defaultContentType,1944 data: postData,1945 timeout: connection._.pollTimeout,1946 success: function (result) {1947 var minData,1948 delay = 0,1949 data,1950 shouldReconnect;1951 connection.log("Long poll complete.");1952 // Reset our reconnect errors so if we transition into a reconnecting state again we trigger1953 // reconnected quickly1954 reconnectErrors = 0;1955 try {1956 // Remove any keep-alives from the beginning of the result1957 minData = connection._parseResponse(result);1958 }1959 catch (error) {1960 transportLogic.handleParseFailure(instance, result, error, tryFailConnect, instance.pollXhr);1961 return;1962 }1963 // If there's currently a timeout to trigger reconnect, fire it now before processing messages1964 if (privateData.reconnectTimeoutId !== null) {1965 fireReconnected(instance);1966 }1967 if (minData) {1968 data = transportLogic.maximizePersistentResponse(minData);1969 }1970 transportLogic.processMessages(instance, minData, fireConnect);1971 if (data &&1972 $.type(data.LongPollDelay) === "number") {1973 delay = data.LongPollDelay;1974 }1975 if (isDisconnecting(instance) === true) {1976 return;1977 }1978 shouldReconnect = data && data.ShouldReconnect;1979 if (shouldReconnect) {1980 // Transition into the reconnecting state1981 // If this fails then that means that the user transitioned the connection into a invalid state in processMessages.1982 if (!transportLogic.ensureReconnectingState(instance)) {1983 return;1984 }1985 }1986 // We never want to pass a raiseReconnect flag after a successful poll. This is handled via the error function1987 if (delay > 0) {1988 privateData.pollTimeoutId = window.setTimeout(function () {1989 poll(instance, shouldReconnect);1990 }, delay);1991 } else {1992 poll(instance, shouldReconnect);1993 }1994 },1995 error: function (data, textStatus) {1996 var error = signalR._.transportError(signalR.resources.longPollFailed, connection.transport, data, instance.pollXhr);1997 // Stop trying to trigger reconnect, connection is in an error state1998 // If we're not in the reconnect state this will noop1999 window.clearTimeout(privateData.reconnectTimeoutId);2000 privateData.reconnectTimeoutId = null;2001 if (textStatus === "abort") {2002 connection.log("Aborted xhr request.");2003 return;2004 }2005 if (!tryFailConnect(error)) {2006 // Increment our reconnect errors, we assume all errors to be reconnect errors2007 // In the case that it's our first error this will cause Reconnect to be fired2008 // after 1 second due to reconnectErrors being = 1.2009 reconnectErrors++;2010 if (connection.state !== signalR.connectionState.reconnecting) {2011 connection.log("An error occurred using longPolling. Status = " + textStatus + ". Response = " + data.responseText + ".");2012 $(instance).triggerHandler(events.onError, [error]);2013 }2014 // We check the state here to verify that we're not in an invalid state prior to verifying Reconnect.2015 // If we're not in connected or reconnecting then the next ensureReconnectingState check will fail and will return.2016 // Therefore we don't want to change that failure code path.2017 if ((connection.state === signalR.connectionState.connected ||2018 connection.state === signalR.connectionState.reconnecting) &&2019 !transportLogic.verifyLastActive(connection)) {2020 return;2021 }2022 // Transition into the reconnecting state2023 // If this fails then that means that the user transitioned the connection into the disconnected or connecting state within the above error handler trigger.2024 if (!transportLogic.ensureReconnectingState(instance)) {2025 return;2026 }2027 // Call poll with the raiseReconnect flag as true after the reconnect delay2028 privateData.pollTimeoutId = window.setTimeout(function () {2029 poll(instance, true);2030 }, that.reconnectDelay);2031 }2032 }2033 });2034 // This will only ever pass after an error has occurred via the poll ajax procedure.2035 if (reconnecting && raiseReconnect === true) {2036 // We wait to reconnect depending on how many times we've failed to reconnect.2037 // This is essentially a heuristic that will exponentially increase in wait time before2038 // triggering reconnected. This depends on the "error" handler of Poll to cancel this2039 // timeout if it triggers before the Reconnected event fires.2040 // The Math.min at the end is to ensure that the reconnect timeout does not overflow.2041 privateData.reconnectTimeoutId = window.setTimeout(function () { fireReconnected(instance); }, Math.min(1000 * (Math.pow(2, reconnectErrors) - 1), maxFireReconnectedTimeout));2042 }2043 }(connection));2044 }, 250); // Have to delay initial poll so Chrome doesn't show loader spinner in tab2045 },2046 lostConnection: function (connection) {2047 if (connection.pollXhr) {2048 connection.pollXhr.abort("lostConnection");2049 }2050 },2051 send: function (connection, data) {2052 transportLogic.ajaxSend(connection, data);2053 },2054 stop: function (connection) {2055 /// <summary>Stops the long polling connection</summary>2056 /// <param name="connection" type="signalR">The SignalR connection to stop</param>2057 window.clearTimeout(connection._.pollTimeoutId);2058 window.clearTimeout(connection._.reconnectTimeoutId);2059 delete connection._.pollTimeoutId;2060 delete connection._.reconnectTimeoutId;2061 if (connection.pollXhr) {2062 connection.pollXhr.abort();2063 connection.pollXhr = null;2064 delete connection.pollXhr;2065 }2066 },2067 abort: function (connection, async) {2068 transportLogic.ajaxAbort(connection, async);2069 }2070 };2071}(window.jQuery, window));2072/* jquery.signalR.hubs.js */2073// Copyright (c) .NET Foundation. All rights reserved.2074// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.2075/*global window:false */2076/// <reference path="jquery.signalR.core.js" />2077(function ($, window, undefined) {2078 var eventNamespace = ".hubProxy",2079 signalR = $.signalR;2080 function makeEventName(event) {2081 return event + eventNamespace;2082 }2083 // Equivalent to Array.prototype.map2084 function map(arr, fun, thisp) {2085 var i,2086 length = arr.length,2087 result = [];2088 for (i = 0; i < length; i += 1) {2089 if (arr.hasOwnProperty(i)) {2090 result[i] = fun.call(thisp, arr[i], i, arr);2091 }2092 }2093 return result;2094 }2095 function getArgValue(a) {2096 return $.isFunction(a) ? null : ($.type(a) === "undefined" ? null : a);2097 }2098 function hasMembers(obj) {2099 for (var key in obj) {2100 // If we have any properties in our callback map then we have callbacks and can exit the loop via return2101 if (obj.hasOwnProperty(key)) {2102 return true;2103 }2104 }2105 return false;2106 }2107 function clearInvocationCallbacks(connection, error) {2108 /// <param name="connection" type="hubConnection" />2109 var callbacks = connection._.invocationCallbacks,2110 callback;2111 if (hasMembers(callbacks)) {2112 connection.log("Clearing hub invocation callbacks with error: " + error + ".");2113 }2114 // Reset the callback cache now as we have a local var referencing it2115 connection._.invocationCallbackId = 0;2116 delete connection._.invocationCallbacks;2117 connection._.invocationCallbacks = {};2118 // Loop over the callbacks and invoke them.2119 // We do this using a local var reference and *after* we've cleared the cache2120 // so that if a fail callback itself tries to invoke another method we don't2121 // end up with its callback in the list we're looping over.2122 for (var callbackId in callbacks) {2123 callback = callbacks[callbackId];2124 callback.method.call(callback.scope, { E: error });2125 }2126 }2127 // hubProxy2128 function hubProxy(hubConnection, hubName) {2129 /// <summary>2130 /// Creates a new proxy object for the given hub connection that can be used to invoke2131 /// methods on server hubs and handle client method invocation requests from the server.2132 /// </summary>2133 return new hubProxy.fn.init(hubConnection, hubName);2134 }2135 hubProxy.fn = hubProxy.prototype = {2136 init: function (connection, hubName) {2137 this.state = {};2138 this.connection = connection;2139 this.hubName = hubName;2140 this._ = {2141 callbackMap: {}2142 };2143 },2144 constructor: hubProxy,2145 hasSubscriptions: function () {2146 return hasMembers(this._.callbackMap);2147 },2148 on: function (eventName, callback) {2149 /// <summary>Wires up a callback to be invoked when a invocation request is received from the server hub.</summary>2150 /// <param name="eventName" type="String">The name of the hub event to register the callback for.</param>2151 /// <param name="callback" type="Function">The callback to be invoked.</param>2152 var that = this,2153 callbackMap = that._.callbackMap;2154 // Normalize the event name to lowercase2155 eventName = eventName.toLowerCase();2156 // If there is not an event registered for this callback yet we want to create its event space in the callback map.2157 if (!callbackMap[eventName]) {2158 callbackMap[eventName] = {};2159 }2160 // Map the callback to our encompassed function2161 callbackMap[eventName][callback] = function (e, data) {2162 callback.apply(that, data);2163 };2164 $(that).bind(makeEventName(eventName), callbackMap[eventName][callback]);2165 return that;2166 },2167 off: function (eventName, callback) {2168 /// <summary>Removes the callback invocation request from the server hub for the given event name.</summary>2169 /// <param name="eventName" type="String">The name of the hub event to unregister the callback for.</param>2170 /// <param name="callback" type="Function">The callback to be invoked.</param>2171 var that = this,2172 callbackMap = that._.callbackMap,2173 callbackSpace;2174 // Normalize the event name to lowercase2175 eventName = eventName.toLowerCase();2176 callbackSpace = callbackMap[eventName];2177 // Verify that there is an event space to unbind2178 if (callbackSpace) {2179 // Only unbind if there's an event bound with eventName and a callback with the specified callback2180 if (callbackSpace[callback]) {2181 $(that).unbind(makeEventName(eventName), callbackSpace[callback]);2182 // Remove the callback from the callback map2183 delete callbackSpace[callback];2184 // Check if there are any members left on the event, if not we need to destroy it.2185 if (!hasMembers(callbackSpace)) {2186 delete callbackMap[eventName];2187 }2188 } else if (!callback) { // Check if we're removing the whole event and we didn't error because of an invalid callback2189 $(that).unbind(makeEventName(eventName));2190 delete callbackMap[eventName];2191 }2192 }2193 return that;2194 },2195 invoke: function (methodName) {2196 /// <summary>Invokes a server hub method with the given arguments.</summary>2197 /// <param name="methodName" type="String">The name of the server hub method.</param>2198 var that = this,2199 connection = that.connection,2200 args = $.makeArray(arguments).slice(1),2201 argValues = map(args, getArgValue),2202 data = { H: that.hubName, M: methodName, A: argValues, I: connection._.invocationCallbackId },2203 d = $.Deferred(),2204 callback = function (minResult) {2205 var result = that._maximizeHubResponse(minResult),2206 source,2207 error;2208 // Update the hub state2209 $.extend(that.state, result.State);2210 if (result.Progress) {2211 if (d.notifyWith) {2212 // Progress is only supported in jQuery 1.7+2213 d.notifyWith(that, [result.Progress.Data]);2214 } else if(!connection._.progressjQueryVersionLogged) {2215 connection.log("A hub method invocation progress update was received but the version of jQuery in use (" + $.prototype.jquery + ") does not support progress updates. Upgrade to jQuery 1.7+ to receive progress notifications.");2216 connection._.progressjQueryVersionLogged = true;2217 }2218 } else if (result.Error) {2219 // Server hub method threw an exception, log it & reject the deferred2220 if (result.StackTrace) {2221 connection.log(result.Error + "\n" + result.StackTrace + ".");2222 }2223 // result.ErrorData is only set if a HubException was thrown2224 source = result.IsHubException ? "HubException" : "Exception";2225 error = signalR._.error(result.Error, source);2226 error.data = result.ErrorData;2227 connection.log(that.hubName + "." + methodName + " failed to execute. Error: " + error.message);2228 d.rejectWith(that, [error]);2229 } else {2230 // Server invocation succeeded, resolve the deferred2231 connection.log("Invoked " + that.hubName + "." + methodName);2232 d.resolveWith(that, [result.Result]);2233 }2234 };2235 connection._.invocationCallbacks[connection._.invocationCallbackId.toString()] = { scope: that, method: callback };2236 connection._.invocationCallbackId += 1;2237 if (!$.isEmptyObject(that.state)) {2238 data.S = that.state;2239 }2240 connection.log("Invoking " + that.hubName + "." + methodName);2241 connection.send(data);2242 return d.promise();2243 },2244 _maximizeHubResponse: function (minHubResponse) {2245 return {2246 State: minHubResponse.S,2247 Result: minHubResponse.R,2248 Progress: minHubResponse.P ? {2249 Id: minHubResponse.P.I,2250 Data: minHubResponse.P.D2251 } : null,2252 Id: minHubResponse.I,2253 IsHubException: minHubResponse.H,2254 Error: minHubResponse.E,2255 StackTrace: minHubResponse.T,2256 ErrorData: minHubResponse.D2257 };2258 }2259 };2260 hubProxy.fn.init.prototype = hubProxy.fn;2261 // hubConnection2262 function hubConnection(url, options) {2263 /// <summary>Creates a new hub connection.</summary>2264 /// <param name="url" type="String">[Optional] The hub route url, defaults to "/signalr".</param>2265 /// <param name="options" type="Object">[Optional] Settings to use when creating the hubConnection.</param>2266 var settings = {2267 qs: null,2268 logging: false,2269 useDefaultPath: true2270 };2271 $.extend(settings, options);2272 if (!url || settings.useDefaultPath) {2273 url = (url || "") + "/signalr";2274 }2275 return new hubConnection.fn.init(url, settings);2276 }...
jquery.signalR-2.2.0.js
Source:jquery.signalR-2.2.0.js
...826 // Check if the keep alive has completely timed out827 if (timeElapsed >= keepAliveData.timeout) {828 connection.log("Keep alive timed out. Notifying transport that connection has been lost.");829 // Notify transport that the connection has been lost830 connection.transport.lostConnection(connection);831 } else if (timeElapsed >= keepAliveData.timeoutWarning) {832 // This is to assure that the user only gets a single warning833 if (!keepAliveData.userNotified) {834 connection.log("Keep alive has been missed, connection may be dead/slow.");835 $(connection).triggerHandler(events.onConnectionSlow);836 keepAliveData.userNotified = true;837 }838 } else {839 keepAliveData.userNotified = false;840 }841 }842 }843 function getAjaxUrl(connection, path) {844 var url = connection.url + path;845 if (connection.transport) {846 url += "?transport=" + connection.transport.name;847 }848 return transportLogic.prepareQueryString(connection, url);849 }850 function InitHandler(connection) {851 this.connection = connection;852 this.startRequested = false;853 this.startCompleted = false;854 this.connectionStopped = false;855 }856 InitHandler.prototype = {857 start: function (transport, onSuccess, onFallback) {858 var that = this,859 connection = that.connection,860 failCalled = false;861 if (that.startRequested || that.connectionStopped) {862 connection.log("WARNING! " + transport.name + " transport cannot be started. Initialization ongoing or completed.");863 return;864 }865 connection.log(transport.name + " transport starting.");866 that.transportTimeoutHandle = window.setTimeout(function () {867 if (!failCalled) {868 failCalled = true;869 connection.log(transport.name + " transport timed out when trying to connect.");870 that.transportFailed(transport, undefined, onFallback);871 }872 }, connection._.totalTransportConnectTimeout);873 transport.start(connection, function () {874 if (!failCalled) {875 that.initReceived(transport, onSuccess);876 }877 }, function (error) {878 // Don't allow the same transport to cause onFallback to be called twice879 if (!failCalled) {880 failCalled = true;881 that.transportFailed(transport, error, onFallback);882 }883 // Returns true if the transport should stop;884 // false if it should attempt to reconnect885 return !that.startCompleted || that.connectionStopped;886 });887 },888 stop: function () {889 this.connectionStopped = true;890 window.clearTimeout(this.transportTimeoutHandle);891 signalR.transports._logic.tryAbortStartRequest(this.connection);892 },893 initReceived: function (transport, onSuccess) {894 var that = this,895 connection = that.connection;896 if (that.startRequested) {897 connection.log("WARNING! The client received multiple init messages.");898 return;899 }900 if (that.connectionStopped) {901 return;902 }903 that.startRequested = true;904 window.clearTimeout(that.transportTimeoutHandle);905 connection.log(transport.name + " transport connected. Initiating start request.");906 signalR.transports._logic.ajaxStart(connection, function () {907 that.startCompleted = true;908 onSuccess();909 });910 },911 transportFailed: function (transport, error, onFallback) {912 var connection = this.connection,913 deferred = connection._deferral,914 wrappedError;915 if (this.connectionStopped) {916 return;917 }918 window.clearTimeout(this.transportTimeoutHandle);919 if (!this.startRequested) {920 transport.stop(connection);921 connection.log(transport.name + " transport failed to connect. Attempting to fall back.");922 onFallback();923 } else if (!this.startCompleted) {924 // Do not attempt to fall back if a start request is ongoing during a transport failure.925 // Instead, trigger an error and stop the connection.926 wrappedError = signalR._.error(signalR.resources.errorDuringStartRequest, error);927 connection.log(transport.name + " transport failed during the start request. Stopping the connection.");928 $(connection).triggerHandler(events.onError, [wrappedError]);929 if (deferred) {930 deferred.reject(wrappedError);931 }932 connection.stop();933 } else {934 // The start request has completed, but the connection has not stopped.935 // No need to do anything here. The transport should attempt its normal reconnect logic.936 }937 }938 };939 transportLogic = signalR.transports._logic = {940 ajax: function (connection, options) {941 return $.ajax(942 $.extend(/*deep copy*/ true, {}, $.signalR.ajaxDefaults, {943 type: "GET",944 data: {},945 xhrFields: { withCredentials: connection.withCredentials },946 contentType: connection.contentType,947 dataType: connection.ajaxDataType948 }, options));949 },950 pingServer: function (connection) {951 /// <summary>Pings the server</summary>952 /// <param name="connection" type="signalr">Connection associated with the server ping</param>953 /// <returns type="signalR" />954 var url,955 xhr,956 deferral = $.Deferred();957 if (connection.transport) {958 url = connection.url + "/ping";959 url = transportLogic.addQs(url, connection.qs);960 xhr = transportLogic.ajax(connection, {961 url: url,962 success: function (result) {963 var data;964 try {965 data = connection._parseResponse(result);966 }967 catch (error) {968 deferral.reject(969 signalR._.transportError(970 signalR.resources.pingServerFailedParse,971 connection.transport,972 error,973 xhr974 )975 );976 connection.stop();977 return;978 }979 if (data.Response === "pong") {980 deferral.resolve();981 }982 else {983 deferral.reject(984 signalR._.transportError(985 signalR._.format(signalR.resources.pingServerFailedInvalidResponse, result),986 connection.transport,987 null /* error */,988 xhr989 )990 );991 }992 },993 error: function (error) {994 if (error.status === 401 || error.status === 403) {995 deferral.reject(996 signalR._.transportError(997 signalR._.format(signalR.resources.pingServerFailedStatusCode, error.status),998 connection.transport,999 error,1000 xhr1001 )1002 );1003 connection.stop();1004 }1005 else {1006 deferral.reject(1007 signalR._.transportError(1008 signalR.resources.pingServerFailed,1009 connection.transport,1010 error,1011 xhr1012 )1013 );1014 }1015 }1016 });1017 }1018 else {1019 deferral.reject(1020 signalR._.transportError(1021 signalR.resources.noConnectionTransport,1022 connection.transport1023 )1024 );1025 }1026 return deferral.promise();1027 },1028 prepareQueryString: function (connection, url) {1029 var preparedUrl;1030 // Use addQs to start since it handles the ?/& prefix for us1031 preparedUrl = transportLogic.addQs(url, "clientProtocol=" + connection.clientProtocol);1032 // Add the user-specified query string params if any1033 preparedUrl = transportLogic.addQs(preparedUrl, connection.qs);1034 if (connection.token) {1035 preparedUrl += "&connectionToken=" + window.encodeURIComponent(connection.token);1036 }1037 if (connection.data) {1038 preparedUrl += "&connectionData=" + window.encodeURIComponent(connection.data);1039 }1040 return preparedUrl;1041 },1042 addQs: function (url, qs) {1043 var appender = url.indexOf("?") !== -1 ? "&" : "?",1044 firstChar;1045 if (!qs) {1046 return url;1047 }1048 if (typeof (qs) === "object") {1049 return url + appender + $.param(qs);1050 }1051 if (typeof (qs) === "string") {1052 firstChar = qs.charAt(0);1053 if (firstChar === "?" || firstChar === "&") {1054 appender = "";1055 }1056 return url + appender + qs;1057 }1058 throw new Error("Query string property must be either a string or object.");1059 },1060 // BUG #2953: The url needs to be same otherwise it will cause a memory leak1061 getUrl: function (connection, transport, reconnecting, poll, ajaxPost) {1062 /// <summary>Gets the url for making a GET based connect request</summary>1063 var baseUrl = transport === "webSockets" ? "" : connection.baseUrl,1064 url = baseUrl + connection.appRelativeUrl,1065 qs = "transport=" + transport;1066 if (!ajaxPost && connection.groupsToken) {1067 qs += "&groupsToken=" + window.encodeURIComponent(connection.groupsToken);1068 }1069 if (!reconnecting) {1070 url += "/connect";1071 } else {1072 if (poll) {1073 // longPolling transport specific1074 url += "/poll";1075 } else {1076 url += "/reconnect";1077 }1078 if (!ajaxPost && connection.messageId) {1079 qs += "&messageId=" + window.encodeURIComponent(connection.messageId);1080 }1081 }1082 url += "?" + qs;1083 url = transportLogic.prepareQueryString(connection, url);1084 if (!ajaxPost) {1085 url += "&tid=" + Math.floor(Math.random() * 11);1086 }1087 return url;1088 },1089 maximizePersistentResponse: function (minPersistentResponse) {1090 return {1091 MessageId: minPersistentResponse.C,1092 Messages: minPersistentResponse.M,1093 Initialized: typeof (minPersistentResponse.S) !== "undefined" ? true : false,1094 ShouldReconnect: typeof (minPersistentResponse.T) !== "undefined" ? true : false,1095 LongPollDelay: minPersistentResponse.L,1096 GroupsToken: minPersistentResponse.G1097 };1098 },1099 updateGroups: function (connection, groupsToken) {1100 if (groupsToken) {1101 connection.groupsToken = groupsToken;1102 }1103 },1104 stringifySend: function (connection, message) {1105 if (typeof (message) === "string" || typeof (message) === "undefined" || message === null) {1106 return message;1107 }1108 return connection.json.stringify(message);1109 },1110 ajaxSend: function (connection, data) {1111 var payload = transportLogic.stringifySend(connection, data),1112 url = getAjaxUrl(connection, "/send"),1113 xhr,1114 onFail = function (error, connection) {1115 $(connection).triggerHandler(events.onError, [signalR._.transportError(signalR.resources.sendFailed, connection.transport, error, xhr), data]);1116 };1117 xhr = transportLogic.ajax(connection, {1118 url: url,1119 type: connection.ajaxDataType === "jsonp" ? "GET" : "POST",1120 contentType: signalR._.defaultContentType,1121 data: {1122 data: payload1123 },1124 success: function (result) {1125 var res;1126 if (result) {1127 try {1128 res = connection._parseResponse(result);1129 }1130 catch (error) {1131 onFail(error, connection);1132 connection.stop();1133 return;1134 }1135 transportLogic.triggerReceived(connection, res);1136 }1137 },1138 error: function (error, textStatus) {1139 if (textStatus === "abort" || textStatus === "parsererror") {1140 // The parsererror happens for sends that don't return any data, and hence1141 // don't write the jsonp callback to the response. This is harder to fix on the server1142 // so just hack around it on the client for now.1143 return;1144 }1145 onFail(error, connection);1146 }1147 });1148 return xhr;1149 },1150 ajaxAbort: function (connection, async) {1151 if (typeof (connection.transport) === "undefined") {1152 return;1153 }1154 // Async by default unless explicitly overidden1155 async = typeof async === "undefined" ? true : async;1156 var url = getAjaxUrl(connection, "/abort");1157 transportLogic.ajax(connection, {1158 url: url,1159 async: async,1160 timeout: 1000,1161 type: "POST"1162 });1163 connection.log("Fired ajax abort async = " + async + ".");1164 },1165 ajaxStart: function (connection, onSuccess) {1166 var rejectDeferred = function (error) {1167 var deferred = connection._deferral;1168 if (deferred) {1169 deferred.reject(error);1170 }1171 },1172 triggerStartError = function (error) {1173 connection.log("The start request failed. Stopping the connection.");1174 $(connection).triggerHandler(events.onError, [error]);1175 rejectDeferred(error);1176 connection.stop();1177 };1178 connection._.startRequest = transportLogic.ajax(connection, {1179 url: getAjaxUrl(connection, "/start"),1180 success: function (result, statusText, xhr) {1181 var data;1182 try {1183 data = connection._parseResponse(result);1184 } catch (error) {1185 triggerStartError(signalR._.error(1186 signalR._.format(signalR.resources.errorParsingStartResponse, result),1187 error, xhr));1188 return;1189 }1190 if (data.Response === "started") {1191 onSuccess();1192 } else {1193 triggerStartError(signalR._.error(1194 signalR._.format(signalR.resources.invalidStartResponse, result),1195 null /* error */, xhr));1196 }1197 },1198 error: function (xhr, statusText, error) {1199 if (statusText !== startAbortText) {1200 triggerStartError(signalR._.error(1201 signalR.resources.errorDuringStartRequest,1202 error, xhr));1203 } else {1204 // Stop has been called, no need to trigger the error handler1205 // or stop the connection again with onStartError1206 connection.log("The start request aborted because connection.stop() was called.");1207 rejectDeferred(signalR._.error(1208 signalR.resources.stoppedDuringStartRequest,1209 null /* error */, xhr));1210 }1211 }1212 });1213 },1214 tryAbortStartRequest: function (connection) {1215 if (connection._.startRequest) {1216 // If the start request has already completed this will noop.1217 connection._.startRequest.abort(startAbortText);1218 delete connection._.startRequest;1219 }1220 },1221 tryInitialize: function (persistentResponse, onInitialized) {1222 if (persistentResponse.Initialized) {1223 onInitialized();1224 }1225 },1226 triggerReceived: function (connection, data) {1227 if (!connection._.connectingMessageBuffer.tryBuffer(data)) {1228 $(connection).triggerHandler(events.onReceived, [data]);1229 }1230 },1231 processMessages: function (connection, minData, onInitialized) {1232 var data;1233 // Update the last message time stamp1234 transportLogic.markLastMessage(connection);1235 if (minData) {1236 data = transportLogic.maximizePersistentResponse(minData);1237 transportLogic.updateGroups(connection, data.GroupsToken);1238 if (data.MessageId) {1239 connection.messageId = data.MessageId;1240 }1241 if (data.Messages) {1242 $.each(data.Messages, function (index, message) {1243 transportLogic.triggerReceived(connection, message);1244 });1245 transportLogic.tryInitialize(data, onInitialized);1246 }1247 }1248 },1249 monitorKeepAlive: function (connection) {1250 var keepAliveData = connection._.keepAliveData;1251 // If we haven't initiated the keep alive timeouts then we need to1252 if (!keepAliveData.monitoring) {1253 keepAliveData.monitoring = true;1254 transportLogic.markLastMessage(connection);1255 // Save the function so we can unbind it on stop1256 connection._.keepAliveData.reconnectKeepAliveUpdate = function () {1257 // Mark a new message so that keep alive doesn't time out connections1258 transportLogic.markLastMessage(connection);1259 };1260 // Update Keep alive on reconnect1261 $(connection).bind(events.onReconnect, connection._.keepAliveData.reconnectKeepAliveUpdate);1262 connection.log("Now monitoring keep alive with a warning timeout of " + keepAliveData.timeoutWarning + ", keep alive timeout of " + keepAliveData.timeout + " and disconnecting timeout of " + connection.disconnectTimeout);1263 } else {1264 connection.log("Tried to monitor keep alive but it's already being monitored.");1265 }1266 },1267 stopMonitoringKeepAlive: function (connection) {1268 var keepAliveData = connection._.keepAliveData;1269 // Only attempt to stop the keep alive monitoring if its being monitored1270 if (keepAliveData.monitoring) {1271 // Stop monitoring1272 keepAliveData.monitoring = false;1273 // Remove the updateKeepAlive function from the reconnect event1274 $(connection).unbind(events.onReconnect, connection._.keepAliveData.reconnectKeepAliveUpdate);1275 // Clear all the keep alive data1276 connection._.keepAliveData = {};1277 connection.log("Stopping the monitoring of the keep alive.");1278 }1279 },1280 startHeartbeat: function (connection) {1281 connection._.lastActiveAt = new Date().getTime();1282 beat(connection);1283 },1284 markLastMessage: function (connection) {1285 connection._.lastMessageAt = new Date().getTime();1286 },1287 markActive: function (connection) {1288 if (transportLogic.verifyLastActive(connection)) {1289 connection._.lastActiveAt = new Date().getTime();1290 return true;1291 }1292 return false;1293 },1294 isConnectedOrReconnecting: function (connection) {1295 return connection.state === signalR.connectionState.connected ||1296 connection.state === signalR.connectionState.reconnecting;1297 },1298 ensureReconnectingState: function (connection) {1299 if (changeState(connection,1300 signalR.connectionState.connected,1301 signalR.connectionState.reconnecting) === true) {1302 $(connection).triggerHandler(events.onReconnecting);1303 }1304 return connection.state === signalR.connectionState.reconnecting;1305 },1306 clearReconnectTimeout: function (connection) {1307 if (connection && connection._.reconnectTimeout) {1308 window.clearTimeout(connection._.reconnectTimeout);1309 delete connection._.reconnectTimeout;1310 }1311 },1312 verifyLastActive: function (connection) {1313 if (new Date().getTime() - connection._.lastActiveAt >= connection.reconnectWindow) {1314 var message = signalR._.format(signalR.resources.reconnectWindowTimeout, new Date(connection._.lastActiveAt), connection.reconnectWindow);1315 connection.log(message);1316 $(connection).triggerHandler(events.onError, [signalR._.error(message, /* source */ "TimeoutException")]);1317 connection.stop(/* async */ false, /* notifyServer */ false);1318 return false;1319 }1320 return true;1321 },1322 reconnect: function (connection, transportName) {1323 var transport = signalR.transports[transportName];1324 // We should only set a reconnectTimeout if we are currently connected1325 // and a reconnectTimeout isn't already set.1326 if (transportLogic.isConnectedOrReconnecting(connection) && !connection._.reconnectTimeout) {1327 // Need to verify before the setTimeout occurs because an application sleep could occur during the setTimeout duration.1328 if (!transportLogic.verifyLastActive(connection)) {1329 return;1330 }1331 connection._.reconnectTimeout = window.setTimeout(function () {1332 if (!transportLogic.verifyLastActive(connection)) {1333 return;1334 }1335 transport.stop(connection);1336 if (transportLogic.ensureReconnectingState(connection)) {1337 connection.log(transportName + " reconnecting.");1338 transport.start(connection);1339 }1340 }, connection.reconnectDelay);1341 }1342 },1343 handleParseFailure: function (connection, result, error, onFailed, context) {1344 var wrappedError = signalR._.transportError(1345 signalR._.format(signalR.resources.parseFailed, result),1346 connection.transport,1347 error,1348 context);1349 // If we're in the initialization phase trigger onFailed, otherwise stop the connection.1350 if (onFailed && onFailed(wrappedError)) {1351 connection.log("Failed to parse server response while attempting to connect.");1352 } else {1353 $(connection).triggerHandler(events.onError, [wrappedError]);1354 connection.stop();1355 }1356 },1357 initHandler: function (connection) {1358 return new InitHandler(connection);1359 },1360 foreverFrame: {1361 count: 0,1362 connections: {}1363 }1364 };1365}(window.jQuery, window));1366/* jquery.signalR.transports.webSockets.js */1367// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.md in the project root for license information.1368/*global window:false */1369/// <reference path="jquery.signalR.transports.common.js" />1370(function ($, window, undefined) {1371 var signalR = $.signalR,1372 events = $.signalR.events,1373 changeState = $.signalR.changeState,1374 transportLogic = signalR.transports._logic;1375 signalR.transports.webSockets = {1376 name: "webSockets",1377 supportsKeepAlive: function () {1378 return true;1379 },1380 send: function (connection, data) {1381 var payload = transportLogic.stringifySend(connection, data);1382 try {1383 connection.socket.send(payload);1384 } catch (ex) {1385 $(connection).triggerHandler(events.onError,1386 [signalR._.transportError(1387 signalR.resources.webSocketsInvalidState,1388 connection.transport,1389 ex,1390 connection.socket1391 ),1392 data]);1393 }1394 },1395 start: function (connection, onSuccess, onFailed) {1396 var url,1397 opened = false,1398 that = this,1399 reconnecting = !onSuccess,1400 $connection = $(connection);1401 if (!window.WebSocket) {1402 onFailed();1403 return;1404 }1405 if (!connection.socket) {1406 if (connection.webSocketServerUrl) {1407 url = connection.webSocketServerUrl;1408 } else {1409 url = connection.wsProtocol + connection.host;1410 }1411 url += transportLogic.getUrl(connection, this.name, reconnecting);1412 connection.log("Connecting to websocket endpoint '" + url + "'.");1413 connection.socket = new window.WebSocket(url);1414 connection.socket.onopen = function () {1415 opened = true;1416 connection.log("Websocket opened.");1417 transportLogic.clearReconnectTimeout(connection);1418 if (changeState(connection,1419 signalR.connectionState.reconnecting,1420 signalR.connectionState.connected) === true) {1421 $connection.triggerHandler(events.onReconnect);1422 }1423 };1424 connection.socket.onclose = function (event) {1425 var error;1426 // Only handle a socket close if the close is from the current socket.1427 // Sometimes on disconnect the server will push down an onclose event1428 // to an expired socket.1429 if (this === connection.socket) {1430 if (opened && typeof event.wasClean !== "undefined" && event.wasClean === false) {1431 // Ideally this would use the websocket.onerror handler (rather than checking wasClean in onclose) but1432 // I found in some circumstances Chrome won't call onerror. This implementation seems to work on all browsers.1433 error = signalR._.transportError(1434 signalR.resources.webSocketClosed,1435 connection.transport,1436 event);1437 connection.log("Unclean disconnect from websocket: " + (event.reason || "[no reason given]."));1438 } else {1439 connection.log("Websocket closed.");1440 }1441 if (!onFailed || !onFailed(error)) {1442 if (error) {1443 $(connection).triggerHandler(events.onError, [error]);1444 }1445 that.reconnect(connection);1446 }1447 }1448 };1449 connection.socket.onmessage = function (event) {1450 var data;1451 try {1452 data = connection._parseResponse(event.data);1453 }1454 catch (error) {1455 transportLogic.handleParseFailure(connection, event.data, error, onFailed, event);1456 return;1457 }1458 if (data) {1459 // data.M is PersistentResponse.Messages1460 if ($.isEmptyObject(data) || data.M) {1461 transportLogic.processMessages(connection, data, onSuccess);1462 } else {1463 // For websockets we need to trigger onReceived1464 // for callbacks to outgoing hub calls.1465 transportLogic.triggerReceived(connection, data);1466 }1467 }1468 };1469 }1470 },1471 reconnect: function (connection) {1472 transportLogic.reconnect(connection, this.name);1473 },1474 lostConnection: function (connection) {1475 this.reconnect(connection);1476 },1477 stop: function (connection) {1478 // Don't trigger a reconnect after stopping1479 transportLogic.clearReconnectTimeout(connection);1480 if (connection.socket) {1481 connection.log("Closing the Websocket.");1482 connection.socket.close();1483 connection.socket = null;1484 }1485 },1486 abort: function (connection, async) {1487 transportLogic.ajaxAbort(connection, async);1488 }1489 };1490}(window.jQuery, window));1491/* jquery.signalR.transports.serverSentEvents.js */1492// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.md in the project root for license information.1493/*global window:false */1494/// <reference path="jquery.signalR.transports.common.js" />1495(function ($, window, undefined) {1496 var signalR = $.signalR,1497 events = $.signalR.events,1498 changeState = $.signalR.changeState,1499 transportLogic = signalR.transports._logic,1500 clearReconnectAttemptTimeout = function (connection) {1501 window.clearTimeout(connection._.reconnectAttemptTimeoutHandle);1502 delete connection._.reconnectAttemptTimeoutHandle;1503 };1504 signalR.transports.serverSentEvents = {1505 name: "serverSentEvents",1506 supportsKeepAlive: function () {1507 return true;1508 },1509 timeOut: 3000,1510 start: function (connection, onSuccess, onFailed) {1511 var that = this,1512 opened = false,1513 $connection = $(connection),1514 reconnecting = !onSuccess,1515 url;1516 if (connection.eventSource) {1517 connection.log("The connection already has an event source. Stopping it.");1518 connection.stop();1519 }1520 if (!window.EventSource) {1521 if (onFailed) {1522 connection.log("This browser doesn't support SSE.");1523 onFailed();1524 }1525 return;1526 }1527 url = transportLogic.getUrl(connection, this.name, reconnecting);1528 try {1529 connection.log("Attempting to connect to SSE endpoint '" + url + "'.");1530 connection.eventSource = new window.EventSource(url, { withCredentials: connection.withCredentials });1531 }1532 catch (e) {1533 connection.log("EventSource failed trying to connect with error " + e.Message + ".");1534 if (onFailed) {1535 // The connection failed, call the failed callback1536 onFailed();1537 } else {1538 $connection.triggerHandler(events.onError, [signalR._.transportError(signalR.resources.eventSourceFailedToConnect, connection.transport, e)]);1539 if (reconnecting) {1540 // If we were reconnecting, rather than doing initial connect, then try reconnect again1541 that.reconnect(connection);1542 }1543 }1544 return;1545 }1546 if (reconnecting) {1547 connection._.reconnectAttemptTimeoutHandle = window.setTimeout(function () {1548 if (opened === false) {1549 // If we're reconnecting and the event source is attempting to connect,1550 // don't keep retrying. This causes duplicate connections to spawn.1551 if (connection.eventSource.readyState !== window.EventSource.OPEN) {1552 // If we were reconnecting, rather than doing initial connect, then try reconnect again1553 that.reconnect(connection);1554 }1555 }1556 },1557 that.timeOut);1558 }1559 connection.eventSource.addEventListener("open", function (e) {1560 connection.log("EventSource connected.");1561 clearReconnectAttemptTimeout(connection);1562 transportLogic.clearReconnectTimeout(connection);1563 if (opened === false) {1564 opened = true;1565 if (changeState(connection,1566 signalR.connectionState.reconnecting,1567 signalR.connectionState.connected) === true) {1568 $connection.triggerHandler(events.onReconnect);1569 }1570 }1571 }, false);1572 connection.eventSource.addEventListener("message", function (e) {1573 var res;1574 // process messages1575 if (e.data === "initialized") {1576 return;1577 }1578 try {1579 res = connection._parseResponse(e.data);1580 }1581 catch (error) {1582 transportLogic.handleParseFailure(connection, e.data, error, onFailed, e);1583 return;1584 }1585 transportLogic.processMessages(connection, res, onSuccess);1586 }, false);1587 connection.eventSource.addEventListener("error", function (e) {1588 var error = signalR._.transportError(1589 signalR.resources.eventSourceError,1590 connection.transport,1591 e);1592 // Only handle an error if the error is from the current Event Source.1593 // Sometimes on disconnect the server will push down an error event1594 // to an expired Event Source.1595 if (this !== connection.eventSource) {1596 return;1597 }1598 if (onFailed && onFailed(error)) {1599 return;1600 }1601 connection.log("EventSource readyState: " + connection.eventSource.readyState + ".");1602 if (e.eventPhase === window.EventSource.CLOSED) {1603 // We don't use the EventSource's native reconnect function as it1604 // doesn't allow us to change the URL when reconnecting. We need1605 // to change the URL to not include the /connect suffix, and pass1606 // the last message id we received.1607 connection.log("EventSource reconnecting due to the server connection ending.");1608 that.reconnect(connection);1609 } else {1610 // connection error1611 connection.log("EventSource error.");1612 $connection.triggerHandler(events.onError, [error]);1613 }1614 }, false);1615 },1616 reconnect: function (connection) {1617 transportLogic.reconnect(connection, this.name);1618 },1619 lostConnection: function (connection) {1620 this.reconnect(connection);1621 },1622 send: function (connection, data) {1623 transportLogic.ajaxSend(connection, data);1624 },1625 stop: function (connection) {1626 // Don't trigger a reconnect after stopping1627 clearReconnectAttemptTimeout(connection);1628 transportLogic.clearReconnectTimeout(connection);1629 if (connection && connection.eventSource) {1630 connection.log("EventSource calling close().");1631 connection.eventSource.close();1632 connection.eventSource = null;1633 delete connection.eventSource;1634 }1635 },1636 abort: function (connection, async) {1637 transportLogic.ajaxAbort(connection, async);1638 }1639 };1640}(window.jQuery, window));1641/* jquery.signalR.transports.foreverFrame.js */1642// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.md in the project root for license information.1643/*global window:false */1644/// <reference path="jquery.signalR.transports.common.js" />1645(function ($, window, undefined) {1646 var signalR = $.signalR,1647 events = $.signalR.events,1648 changeState = $.signalR.changeState,1649 transportLogic = signalR.transports._logic,1650 createFrame = function () {1651 var frame = window.document.createElement("iframe");1652 frame.setAttribute("style", "position:absolute;top:0;left:0;width:0;height:0;visibility:hidden;");1653 return frame;1654 },1655 // Used to prevent infinite loading icon spins in older versions of ie1656 // We build this object inside a closure so we don't pollute the rest of 1657 // the foreverFrame transport with unnecessary functions/utilities.1658 loadPreventer = (function () {1659 var loadingFixIntervalId = null,1660 loadingFixInterval = 1000,1661 attachedTo = 0;1662 return {1663 prevent: function () {1664 // Prevent additional iframe removal procedures from newer browsers1665 if (signalR._.ieVersion <= 8) {1666 // We only ever want to set the interval one time, so on the first attachedTo1667 if (attachedTo === 0) {1668 // Create and destroy iframe every 3 seconds to prevent loading icon, super hacky1669 loadingFixIntervalId = window.setInterval(function () {1670 var tempFrame = createFrame();1671 window.document.body.appendChild(tempFrame);1672 window.document.body.removeChild(tempFrame);1673 tempFrame = null;1674 }, loadingFixInterval);1675 }1676 attachedTo++;1677 }1678 },1679 cancel: function () {1680 // Only clear the interval if there's only one more object that the loadPreventer is attachedTo1681 if (attachedTo === 1) {1682 window.clearInterval(loadingFixIntervalId);1683 }1684 if (attachedTo > 0) {1685 attachedTo--;1686 }1687 }1688 };1689 })();1690 signalR.transports.foreverFrame = {1691 name: "foreverFrame",1692 supportsKeepAlive: function () {1693 return true;1694 },1695 // Added as a value here so we can create tests to verify functionality1696 iframeClearThreshold: 50,1697 start: function (connection, onSuccess, onFailed) {1698 var that = this,1699 frameId = (transportLogic.foreverFrame.count += 1),1700 url,1701 frame = createFrame(),1702 frameLoadHandler = function () {1703 connection.log("Forever frame iframe finished loading and is no longer receiving messages.");1704 if (!onFailed || !onFailed()) {1705 that.reconnect(connection);1706 }1707 };1708 if (window.EventSource) {1709 // If the browser supports SSE, don't use Forever Frame1710 if (onFailed) {1711 connection.log("Forever Frame is not supported by SignalR on browsers with SSE support.");1712 onFailed();1713 }1714 return;1715 }1716 frame.setAttribute("data-signalr-connection-id", connection.id);1717 // Start preventing loading icon1718 // This will only perform work if the loadPreventer is not attached to another connection.1719 loadPreventer.prevent();1720 // Build the url1721 url = transportLogic.getUrl(connection, this.name);1722 url += "&frameId=" + frameId;1723 // add frame to the document prior to setting URL to avoid caching issues.1724 window.document.documentElement.appendChild(frame);1725 connection.log("Binding to iframe's load event.");1726 if (frame.addEventListener) {1727 frame.addEventListener("load", frameLoadHandler, false);1728 } else if (frame.attachEvent) {1729 frame.attachEvent("onload", frameLoadHandler);1730 }1731 frame.src = url;1732 transportLogic.foreverFrame.connections[frameId] = connection;1733 connection.frame = frame;1734 connection.frameId = frameId;1735 if (onSuccess) {1736 connection.onSuccess = function () {1737 connection.log("Iframe transport started.");1738 onSuccess();1739 };1740 }1741 },1742 reconnect: function (connection) {1743 var that = this;1744 // Need to verify connection state and verify before the setTimeout occurs because an application sleep could occur during the setTimeout duration.1745 if (transportLogic.isConnectedOrReconnecting(connection) && transportLogic.verifyLastActive(connection)) {1746 window.setTimeout(function () {1747 // Verify that we're ok to reconnect.1748 if (!transportLogic.verifyLastActive(connection)) {1749 return;1750 }1751 if (connection.frame && transportLogic.ensureReconnectingState(connection)) {1752 var frame = connection.frame,1753 src = transportLogic.getUrl(connection, that.name, true) + "&frameId=" + connection.frameId;1754 connection.log("Updating iframe src to '" + src + "'.");1755 frame.src = src;1756 }1757 }, connection.reconnectDelay);1758 }1759 },1760 lostConnection: function (connection) {1761 this.reconnect(connection);1762 },1763 send: function (connection, data) {1764 transportLogic.ajaxSend(connection, data);1765 },1766 receive: function (connection, data) {1767 var cw,1768 body,1769 response;1770 if (connection.json !== connection._originalJson) {1771 // If there's a custom JSON parser configured then serialize the object1772 // using the original (browser) JSON parser and then deserialize it using1773 // the custom parser (connection._parseResponse does that). This is so we1774 // can easily send the response from the server as "raw" JSON but still 1775 // support custom JSON deserialization in the browser.1776 data = connection._originalJson.stringify(data);1777 }1778 response = connection._parseResponse(data);1779 transportLogic.processMessages(connection, response, connection.onSuccess);1780 // Protect against connection stopping from a callback trigger within the processMessages above.1781 if (connection.state === $.signalR.connectionState.connected) {1782 // Delete the script & div elements1783 connection.frameMessageCount = (connection.frameMessageCount || 0) + 1;1784 if (connection.frameMessageCount > signalR.transports.foreverFrame.iframeClearThreshold) {1785 connection.frameMessageCount = 0;1786 cw = connection.frame.contentWindow || connection.frame.contentDocument;1787 if (cw && cw.document && cw.document.body) {1788 body = cw.document.body;1789 // Remove all the child elements from the iframe's body to conserver memory1790 while (body.firstChild) {1791 body.removeChild(body.firstChild);1792 }1793 }1794 }1795 }1796 },1797 stop: function (connection) {1798 var cw = null;1799 // Stop attempting to prevent loading icon1800 loadPreventer.cancel();1801 if (connection.frame) {1802 if (connection.frame.stop) {1803 connection.frame.stop();1804 } else {1805 try {1806 cw = connection.frame.contentWindow || connection.frame.contentDocument;1807 if (cw.document && cw.document.execCommand) {1808 cw.document.execCommand("Stop");1809 }1810 }1811 catch (e) {1812 connection.log("Error occured when stopping foreverFrame transport. Message = " + e.message + ".");1813 }1814 }1815 // Ensure the iframe is where we left it1816 if (connection.frame.parentNode === window.document.body) {1817 window.document.body.removeChild(connection.frame);1818 }1819 delete transportLogic.foreverFrame.connections[connection.frameId];1820 connection.frame = null;1821 connection.frameId = null;1822 delete connection.frame;1823 delete connection.frameId;1824 delete connection.onSuccess;1825 delete connection.frameMessageCount;1826 connection.log("Stopping forever frame.");1827 }1828 },1829 abort: function (connection, async) {1830 transportLogic.ajaxAbort(connection, async);1831 },1832 getConnection: function (id) {1833 return transportLogic.foreverFrame.connections[id];1834 },1835 started: function (connection) {1836 if (changeState(connection,1837 signalR.connectionState.reconnecting,1838 signalR.connectionState.connected) === true) {1839 $(connection).triggerHandler(events.onReconnect);1840 }1841 }1842 };1843}(window.jQuery, window));1844/* jquery.signalR.transports.longPolling.js */1845// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.md in the project root for license information.1846/*global window:false */1847/// <reference path="jquery.signalR.transports.common.js" />1848(function ($, window, undefined) {1849 var signalR = $.signalR,1850 events = $.signalR.events,1851 changeState = $.signalR.changeState,1852 isDisconnecting = $.signalR.isDisconnecting,1853 transportLogic = signalR.transports._logic;1854 signalR.transports.longPolling = {1855 name: "longPolling",1856 supportsKeepAlive: function () {1857 return false;1858 },1859 reconnectDelay: 3000,1860 start: function (connection, onSuccess, onFailed) {1861 /// <summary>Starts the long polling connection</summary>1862 /// <param name="connection" type="signalR">The SignalR connection to start</param>1863 var that = this,1864 fireConnect = function () {1865 fireConnect = $.noop;1866 connection.log("LongPolling connected.");1867 onSuccess();1868 },1869 tryFailConnect = function (error) {1870 if (onFailed(error)) {1871 connection.log("LongPolling failed to connect.");1872 return true;1873 }1874 return false;1875 },1876 privateData = connection._,1877 reconnectErrors = 0,1878 fireReconnected = function (instance) {1879 window.clearTimeout(privateData.reconnectTimeoutId);1880 privateData.reconnectTimeoutId = null;1881 if (changeState(instance,1882 signalR.connectionState.reconnecting,1883 signalR.connectionState.connected) === true) {1884 // Successfully reconnected!1885 instance.log("Raising the reconnect event");1886 $(instance).triggerHandler(events.onReconnect);1887 }1888 },1889 // 1 hour1890 maxFireReconnectedTimeout = 3600000;1891 if (connection.pollXhr) {1892 connection.log("Polling xhr requests already exists, aborting.");1893 connection.stop();1894 }1895 connection.messageId = null;1896 privateData.reconnectTimeoutId = null;1897 privateData.pollTimeoutId = window.setTimeout(function () {1898 (function poll(instance, raiseReconnect) {1899 var messageId = instance.messageId,1900 connect = (messageId === null),1901 reconnecting = !connect,1902 polling = !raiseReconnect,1903 url = transportLogic.getUrl(instance, that.name, reconnecting, polling, true /* use Post for longPolling */),1904 postData = {};1905 if (instance.messageId) {1906 postData.messageId = instance.messageId;1907 }1908 if (instance.groupsToken) {1909 postData.groupsToken = instance.groupsToken;1910 }1911 // If we've disconnected during the time we've tried to re-instantiate the poll then stop.1912 if (isDisconnecting(instance) === true) {1913 return;1914 }1915 connection.log("Opening long polling request to '" + url + "'.");1916 instance.pollXhr = transportLogic.ajax(connection, {1917 xhrFields: {1918 onprogress: function () {1919 transportLogic.markLastMessage(connection);1920 }1921 },1922 url: url,1923 type: "POST",1924 contentType: signalR._.defaultContentType,1925 data: postData,1926 timeout: connection._.pollTimeout,1927 success: function (result) {1928 var minData,1929 delay = 0,1930 data,1931 shouldReconnect;1932 connection.log("Long poll complete.");1933 // Reset our reconnect errors so if we transition into a reconnecting state again we trigger1934 // reconnected quickly1935 reconnectErrors = 0;1936 try {1937 // Remove any keep-alives from the beginning of the result1938 minData = connection._parseResponse(result);1939 }1940 catch (error) {1941 transportLogic.handleParseFailure(instance, result, error, tryFailConnect, instance.pollXhr);1942 return;1943 }1944 // If there's currently a timeout to trigger reconnect, fire it now before processing messages1945 if (privateData.reconnectTimeoutId !== null) {1946 fireReconnected(instance);1947 }1948 if (minData) {1949 data = transportLogic.maximizePersistentResponse(minData);1950 }1951 transportLogic.processMessages(instance, minData, fireConnect);1952 if (data &&1953 $.type(data.LongPollDelay) === "number") {1954 delay = data.LongPollDelay;1955 }1956 if (isDisconnecting(instance) === true) {1957 return;1958 }1959 shouldReconnect = data && data.ShouldReconnect;1960 if (shouldReconnect) {1961 // Transition into the reconnecting state1962 // If this fails then that means that the user transitioned the connection into a invalid state in processMessages.1963 if (!transportLogic.ensureReconnectingState(instance)) {1964 return;1965 }1966 }1967 // We never want to pass a raiseReconnect flag after a successful poll. This is handled via the error function1968 if (delay > 0) {1969 privateData.pollTimeoutId = window.setTimeout(function () {1970 poll(instance, shouldReconnect);1971 }, delay);1972 } else {1973 poll(instance, shouldReconnect);1974 }1975 },1976 error: function (data, textStatus) {1977 var error = signalR._.transportError(signalR.resources.longPollFailed, connection.transport, data, instance.pollXhr);1978 // Stop trying to trigger reconnect, connection is in an error state1979 // If we're not in the reconnect state this will noop1980 window.clearTimeout(privateData.reconnectTimeoutId);1981 privateData.reconnectTimeoutId = null;1982 if (textStatus === "abort") {1983 connection.log("Aborted xhr request.");1984 return;1985 }1986 if (!tryFailConnect(error)) {1987 // Increment our reconnect errors, we assume all errors to be reconnect errors1988 // In the case that it's our first error this will cause Reconnect to be fired1989 // after 1 second due to reconnectErrors being = 1.1990 reconnectErrors++;1991 if (connection.state !== signalR.connectionState.reconnecting) {1992 connection.log("An error occurred using longPolling. Status = " + textStatus + ". Response = " + data.responseText + ".");1993 $(instance).triggerHandler(events.onError, [error]);1994 }1995 // We check the state here to verify that we're not in an invalid state prior to verifying Reconnect.1996 // If we're not in connected or reconnecting then the next ensureReconnectingState check will fail and will return.1997 // Therefore we don't want to change that failure code path.1998 if ((connection.state === signalR.connectionState.connected ||1999 connection.state === signalR.connectionState.reconnecting) &&2000 !transportLogic.verifyLastActive(connection)) {2001 return;2002 }2003 // Transition into the reconnecting state2004 // If this fails then that means that the user transitioned the connection into the disconnected or connecting state within the above error handler trigger.2005 if (!transportLogic.ensureReconnectingState(instance)) {2006 return;2007 }2008 // Call poll with the raiseReconnect flag as true after the reconnect delay2009 privateData.pollTimeoutId = window.setTimeout(function () {2010 poll(instance, true);2011 }, that.reconnectDelay);2012 }2013 }2014 });2015 // This will only ever pass after an error has occured via the poll ajax procedure.2016 if (reconnecting && raiseReconnect === true) {2017 // We wait to reconnect depending on how many times we've failed to reconnect.2018 // This is essentially a heuristic that will exponentially increase in wait time before2019 // triggering reconnected. This depends on the "error" handler of Poll to cancel this 2020 // timeout if it triggers before the Reconnected event fires.2021 // The Math.min at the end is to ensure that the reconnect timeout does not overflow.2022 privateData.reconnectTimeoutId = window.setTimeout(function () { fireReconnected(instance); }, Math.min(1000 * (Math.pow(2, reconnectErrors) - 1), maxFireReconnectedTimeout));2023 }2024 }(connection));2025 }, 250); // Have to delay initial poll so Chrome doesn't show loader spinner in tab2026 },2027 lostConnection: function (connection) {2028 if (connection.pollXhr) {2029 connection.pollXhr.abort("lostConnection");2030 }2031 },2032 send: function (connection, data) {2033 transportLogic.ajaxSend(connection, data);2034 },2035 stop: function (connection) {2036 /// <summary>Stops the long polling connection</summary>2037 /// <param name="connection" type="signalR">The SignalR connection to stop</param>2038 window.clearTimeout(connection._.pollTimeoutId);2039 window.clearTimeout(connection._.reconnectTimeoutId);2040 delete connection._.pollTimeoutId;2041 delete connection._.reconnectTimeoutId;2042 if (connection.pollXhr) {2043 connection.pollXhr.abort();2044 connection.pollXhr = null;2045 delete connection.pollXhr;2046 }2047 },2048 abort: function (connection, async) {2049 transportLogic.ajaxAbort(connection, async);2050 }2051 };2052}(window.jQuery, window));2053/* jquery.signalR.hubs.js */2054// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.md in the project root for license information.2055/*global window:false */2056/// <reference path="jquery.signalR.core.js" />2057(function ($, window, undefined) {2058 var eventNamespace = ".hubProxy",2059 signalR = $.signalR;2060 function makeEventName(event) {2061 return event + eventNamespace;2062 }2063 // Equivalent to Array.prototype.map2064 function map(arr, fun, thisp) {2065 var i,2066 length = arr.length,2067 result = [];2068 for (i = 0; i < length; i += 1) {2069 if (arr.hasOwnProperty(i)) {2070 result[i] = fun.call(thisp, arr[i], i, arr);2071 }2072 }2073 return result;2074 }2075 function getArgValue(a) {2076 return $.isFunction(a) ? null : ($.type(a) === "undefined" ? null : a);2077 }2078 function hasMembers(obj) {2079 for (var key in obj) {2080 // If we have any properties in our callback map then we have callbacks and can exit the loop via return2081 if (obj.hasOwnProperty(key)) {2082 return true;2083 }2084 }2085 return false;2086 }2087 function clearInvocationCallbacks(connection, error) {2088 /// <param name="connection" type="hubConnection" />2089 var callbacks = connection._.invocationCallbacks,2090 callback;2091 if (hasMembers(callbacks)) {2092 connection.log("Clearing hub invocation callbacks with error: " + error + ".");2093 }2094 // Reset the callback cache now as we have a local var referencing it2095 connection._.invocationCallbackId = 0;2096 delete connection._.invocationCallbacks;2097 connection._.invocationCallbacks = {};2098 // Loop over the callbacks and invoke them.2099 // We do this using a local var reference and *after* we've cleared the cache2100 // so that if a fail callback itself tries to invoke another method we don't 2101 // end up with its callback in the list we're looping over.2102 for (var callbackId in callbacks) {2103 callback = callbacks[callbackId];2104 callback.method.call(callback.scope, { E: error });2105 }2106 }2107 // hubProxy2108 function hubProxy(hubConnection, hubName) {2109 /// <summary>2110 /// Creates a new proxy object for the given hub connection that can be used to invoke2111 /// methods on server hubs and handle client method invocation requests from the server.2112 /// </summary>2113 return new hubProxy.fn.init(hubConnection, hubName);2114 }2115 hubProxy.fn = hubProxy.prototype = {2116 init: function (connection, hubName) {2117 this.state = {};2118 this.connection = connection;2119 this.hubName = hubName;2120 this._ = {2121 callbackMap: {}2122 };2123 },2124 constructor: hubProxy,2125 hasSubscriptions: function () {2126 return hasMembers(this._.callbackMap);2127 },2128 on: function (eventName, callback) {2129 /// <summary>Wires up a callback to be invoked when a invocation request is received from the server hub.</summary>2130 /// <param name="eventName" type="String">The name of the hub event to register the callback for.</param>2131 /// <param name="callback" type="Function">The callback to be invoked.</param>2132 var that = this,2133 callbackMap = that._.callbackMap;2134 // Normalize the event name to lowercase2135 eventName = eventName.toLowerCase();2136 // If there is not an event registered for this callback yet we want to create its event space in the callback map.2137 if (!callbackMap[eventName]) {2138 callbackMap[eventName] = {};2139 }2140 // Map the callback to our encompassed function2141 callbackMap[eventName][callback] = function (e, data) {2142 callback.apply(that, data);2143 };2144 $(that).bind(makeEventName(eventName), callbackMap[eventName][callback]);2145 return that;2146 },2147 off: function (eventName, callback) {2148 /// <summary>Removes the callback invocation request from the server hub for the given event name.</summary>2149 /// <param name="eventName" type="String">The name of the hub event to unregister the callback for.</param>2150 /// <param name="callback" type="Function">The callback to be invoked.</param>2151 var that = this,2152 callbackMap = that._.callbackMap,2153 callbackSpace;2154 // Normalize the event name to lowercase2155 eventName = eventName.toLowerCase();2156 callbackSpace = callbackMap[eventName];2157 // Verify that there is an event space to unbind2158 if (callbackSpace) {2159 // Only unbind if there's an event bound with eventName and a callback with the specified callback2160 if (callbackSpace[callback]) {2161 $(that).unbind(makeEventName(eventName), callbackSpace[callback]);2162 // Remove the callback from the callback map2163 delete callbackSpace[callback];2164 // Check if there are any members left on the event, if not we need to destroy it.2165 if (!hasMembers(callbackSpace)) {2166 delete callbackMap[eventName];2167 }2168 } else if (!callback) { // Check if we're removing the whole event and we didn't error because of an invalid callback2169 $(that).unbind(makeEventName(eventName));2170 delete callbackMap[eventName];2171 }2172 }2173 return that;2174 },2175 invoke: function (methodName) {2176 /// <summary>Invokes a server hub method with the given arguments.</summary>2177 /// <param name="methodName" type="String">The name of the server hub method.</param>2178 var that = this,2179 connection = that.connection,2180 args = $.makeArray(arguments).slice(1),2181 argValues = map(args, getArgValue),2182 data = { H: that.hubName, M: methodName, A: argValues, I: connection._.invocationCallbackId },2183 d = $.Deferred(),2184 callback = function (minResult) {2185 var result = that._maximizeHubResponse(minResult),2186 source,2187 error;2188 // Update the hub state2189 $.extend(that.state, result.State);2190 if (result.Progress) {2191 if (d.notifyWith) {2192 // Progress is only supported in jQuery 1.7+2193 d.notifyWith(that, [result.Progress.Data]);2194 } else if(!connection._.progressjQueryVersionLogged) {2195 connection.log("A hub method invocation progress update was received but the version of jQuery in use (" + $.prototype.jquery + ") does not support progress updates. Upgrade to jQuery 1.7+ to receive progress notifications.");2196 connection._.progressjQueryVersionLogged = true;2197 }2198 } else if (result.Error) {2199 // Server hub method threw an exception, log it & reject the deferred2200 if (result.StackTrace) {2201 connection.log(result.Error + "\n" + result.StackTrace + ".");2202 }2203 // result.ErrorData is only set if a HubException was thrown2204 source = result.IsHubException ? "HubException" : "Exception";2205 error = signalR._.error(result.Error, source);2206 error.data = result.ErrorData;2207 connection.log(that.hubName + "." + methodName + " failed to execute. Error: " + error.message);2208 d.rejectWith(that, [error]);2209 } else {2210 // Server invocation succeeded, resolve the deferred2211 connection.log("Invoked " + that.hubName + "." + methodName);2212 d.resolveWith(that, [result.Result]);2213 }2214 };2215 connection._.invocationCallbacks[connection._.invocationCallbackId.toString()] = { scope: that, method: callback };2216 connection._.invocationCallbackId += 1;2217 if (!$.isEmptyObject(that.state)) {2218 data.S = that.state;2219 }2220 connection.log("Invoking " + that.hubName + "." + methodName);2221 connection.send(data);2222 return d.promise();2223 },2224 _maximizeHubResponse: function (minHubResponse) {2225 return {2226 State: minHubResponse.S,2227 Result: minHubResponse.R,2228 Progress: minHubResponse.P ? {2229 Id: minHubResponse.P.I,2230 Data: minHubResponse.P.D2231 } : null,2232 Id: minHubResponse.I,2233 IsHubException: minHubResponse.H,2234 Error: minHubResponse.E,2235 StackTrace: minHubResponse.T,2236 ErrorData: minHubResponse.D2237 };2238 }2239 };2240 hubProxy.fn.init.prototype = hubProxy.fn;2241 // hubConnection2242 function hubConnection(url, options) {2243 /// <summary>Creates a new hub connection.</summary>2244 /// <param name="url" type="String">[Optional] The hub route url, defaults to "/signalr".</param>2245 /// <param name="options" type="Object">[Optional] Settings to use when creating the hubConnection.</param>2246 var settings = {2247 qs: null,2248 logging: false,2249 useDefaultPath: true2250 };2251 $.extend(settings, options);2252 if (!url || settings.useDefaultPath) {2253 url = (url || "") + "/signalr";2254 }2255 return new hubConnection.fn.init(url, settings);2256 }...
jquery.signalR-1.1.2.js
Source:jquery.signalR-1.1.2.js
...587 // Check if the keep alive has completely timed out588 if (timeElapsed >= keepAliveData.timeout) {589 connection.log("Keep alive timed out. Notifying transport that connection has been lost.");590 // Notify transport that the connection has been lost591 connection.transport.lostConnection(connection);592 }593 else if (timeElapsed >= keepAliveData.timeoutWarning) {594 // This is to assure that the user only gets a single warning595 if (!keepAliveData.userNotified) {596 connection.log("Keep alive has been missed, connection may be dead/slow.");597 $(connection).triggerHandler(events.onConnectionSlow);598 keepAliveData.userNotified = true;599 }600 }601 else {602 keepAliveData.userNotified = false;603 }604 }605 // Verify we're monitoring the keep alive606 // We don't want this as a part of the inner if statement above because we want keep alives to continue to be checked607 // in the event that the server comes back online (if it goes offline).608 if (keepAliveData.monitoring) {609 window.setTimeout(function () {610 checkIfAlive(connection);611 }, keepAliveData.checkInterval);612 }613 }614 function isConnectedOrReconnecting(connection) {615 return connection.state === signalR.connectionState.connected ||616 connection.state === signalR.connectionState.reconnecting;617 }618 signalR.transports._logic = {619 pingServer: function (connection, transport) {620 /// <summary>Pings the server</summary>621 /// <param name="connection" type="signalr">Connection associated with the server ping</param>622 /// <returns type="signalR" />623 var baseUrl = transport === "webSockets" ? "" : connection.baseUrl,624 url = baseUrl + connection.appRelativeUrl + "/ping",625 deferral = $.Deferred();626 url = this.addQs(url, connection);627 $.ajax({628 url: url,629 global: false,630 cache: false,631 type: "GET",632 contentType: connection.contentType,633 data: {},634 dataType: connection.ajaxDataType,635 success: function (data) {636 if (data.Response === "pong") {637 deferral.resolve();638 }639 else {640 deferral.reject("SignalR: Invalid ping response when pinging server: " + (data.responseText || data.statusText));641 }642 },643 error: function (data) {644 deferral.reject("SignalR: Error pinging server: " + (data.responseText || data.statusText));645 }646 });647 return deferral.promise();648 },649 addQs: function (url, connection) {650 var appender = url.indexOf("?") !== -1 ? "&" : "?",651 firstChar;652 if (!connection.qs) {653 return url;654 }655 if (typeof (connection.qs) === "object") {656 return url + appender + $.param(connection.qs);657 }658 if (typeof (connection.qs) === "string") {659 firstChar = connection.qs.charAt(0);660 if (firstChar === "?" || firstChar === "&") {661 appender = "";662 }663 return url + appender + connection.qs;664 }665 throw new Error("Connections query string property must be either a string or object.");666 },667 getUrl: function (connection, transport, reconnecting, poll) {668 /// <summary>Gets the url for making a GET based connect request</summary>669 var baseUrl = transport === "webSockets" ? "" : connection.baseUrl,670 url = baseUrl + connection.appRelativeUrl,671 qs = "transport=" + transport + "&connectionToken=" + window.encodeURIComponent(connection.token);672 if (connection.data) {673 qs += "&connectionData=" + window.encodeURIComponent(connection.data);674 }675 if (connection.groupsToken) {676 qs += "&groupsToken=" + window.encodeURIComponent(connection.groupsToken);677 }678 if (!reconnecting) {679 url += "/connect";680 } else {681 if (poll) {682 // longPolling transport specific683 url += "/poll";684 } else {685 url += "/reconnect";686 }687 if (connection.messageId) {688 qs += "&messageId=" + window.encodeURIComponent(connection.messageId);689 }690 }691 url += "?" + qs;692 url = this.addQs(url, connection);693 url += "&tid=" + Math.floor(Math.random() * 11);694 return url;695 },696 maximizePersistentResponse: function (minPersistentResponse) {697 return {698 MessageId: minPersistentResponse.C,699 Messages: minPersistentResponse.M,700 Disconnect: typeof (minPersistentResponse.D) !== "undefined" ? true : false,701 TimedOut: typeof (minPersistentResponse.T) !== "undefined" ? true : false,702 LongPollDelay: minPersistentResponse.L,703 GroupsToken: minPersistentResponse.G704 };705 },706 updateGroups: function (connection, groupsToken) {707 if (groupsToken) {708 connection.groupsToken = groupsToken;709 }710 },711 ajaxSend: function (connection, data) {712 var url = connection.url + "/send" + "?transport=" + connection.transport.name + "&connectionToken=" + window.encodeURIComponent(connection.token);713 url = this.addQs(url, connection);714 return $.ajax({715 url: url,716 global: false,717 type: connection.ajaxDataType === "jsonp" ? "GET" : "POST",718 contentType: signalR._.defaultContentType,719 dataType: connection.ajaxDataType,720 data: {721 data: data722 },723 success: function (result) {724 if (result) {725 $(connection).triggerHandler(events.onReceived, [result]);726 }727 },728 error: function (errData, textStatus) {729 if (textStatus === "abort" || textStatus === "parsererror") {730 // The parsererror happens for sends that don't return any data, and hence731 // don't write the jsonp callback to the response. This is harder to fix on the server732 // so just hack around it on the client for now.733 return;734 }735 $(connection).triggerHandler(events.onError, [errData]);736 }737 });738 },739 ajaxAbort: function (connection, async) {740 if (typeof (connection.transport) === "undefined") {741 return;742 }743 // Async by default unless explicitly overidden744 async = typeof async === "undefined" ? true : async;745 var url = connection.url + "/abort" + "?transport=" + connection.transport.name + "&connectionToken=" + window.encodeURIComponent(connection.token);746 url = this.addQs(url, connection);747 $.ajax({748 url: url,749 async: async,750 timeout: 1000,751 global: false,752 type: "POST",753 contentType: connection.contentType,754 dataType: connection.ajaxDataType,755 data: {}756 });757 connection.log("Fired ajax abort async = " + async);758 },759 processMessages: function (connection, minData) {760 var data;761 // Transport can be null if we've just closed the connection762 if (connection.transport) {763 var $connection = $(connection);764 // If our transport supports keep alive then we need to update the last keep alive time stamp.765 // Very rarely the transport can be null.766 if (connection.transport.supportsKeepAlive && connection.keepAliveData.activated) {767 this.updateKeepAlive(connection);768 }769 if (!minData) {770 return;771 }772 data = this.maximizePersistentResponse(minData);773 if (data.Disconnect) {774 connection.log("Disconnect command received from server");775 // Disconnected by the server776 connection.stop(false, false);777 return;778 }779 this.updateGroups(connection, data.GroupsToken);780 if (data.Messages) {781 $.each(data.Messages, function (index, message) {782 $connection.triggerHandler(events.onReceived, [message]);783 });784 }785 if (data.MessageId) {786 connection.messageId = data.MessageId;787 }788 }789 },790 monitorKeepAlive: function (connection) {791 var keepAliveData = connection.keepAliveData,792 that = this;793 // If we haven't initiated the keep alive timeouts then we need to794 if (!keepAliveData.monitoring) {795 keepAliveData.monitoring = true;796 // Initialize the keep alive time stamp ping797 that.updateKeepAlive(connection);798 // Save the function so we can unbind it on stop799 connection.keepAliveData.reconnectKeepAliveUpdate = function () {800 that.updateKeepAlive(connection);801 };802 // Update Keep alive on reconnect803 $(connection).bind(events.onReconnect, connection.keepAliveData.reconnectKeepAliveUpdate);804 connection.log("Now monitoring keep alive with a warning timeout of " + keepAliveData.timeoutWarning + " and a connection lost timeout of " + keepAliveData.timeout);805 // Start the monitoring of the keep alive806 checkIfAlive(connection);807 }808 else {809 connection.log("Tried to monitor keep alive but it's already being monitored");810 }811 },812 stopMonitoringKeepAlive: function (connection) {813 var keepAliveData = connection.keepAliveData;814 // Only attempt to stop the keep alive monitoring if its being monitored815 if (keepAliveData.monitoring) {816 // Stop monitoring817 keepAliveData.monitoring = false;818 // Remove the updateKeepAlive function from the reconnect event819 $(connection).unbind(events.onReconnect, connection.keepAliveData.reconnectKeepAliveUpdate);820 // Clear all the keep alive data821 connection.keepAliveData = {};822 connection.log("Stopping the monitoring of the keep alive");823 }824 },825 updateKeepAlive: function (connection) {826 connection.keepAliveData.lastKeepAlive = new Date();827 },828 ensureReconnectingState: function (connection) {829 if (changeState(connection,830 signalR.connectionState.connected,831 signalR.connectionState.reconnecting) === true) {832 $(connection).triggerHandler(events.onReconnecting);833 }834 return connection.state === signalR.connectionState.reconnecting;835 },836 clearReconnectTimeout: function (connection) {837 if (connection && connection._.reconnectTimeout) {838 window.clearTimeout(connection._.reconnectTimeout);839 delete connection._.reconnectTimeout;840 }841 },842 reconnect: function (connection, transportName) {843 var transport = signalR.transports[transportName],844 that = this;845 // We should only set a reconnectTimeout if we are currently connected846 // and a reconnectTimeout isn't already set.847 if (isConnectedOrReconnecting(connection) && !connection._.reconnectTimeout) {848 connection._.reconnectTimeout = window.setTimeout(function () {849 transport.stop(connection);850 if (that.ensureReconnectingState(connection)) {851 connection.log(transportName + " reconnecting");852 transport.start(connection);853 }854 }, connection.reconnectDelay);855 }856 },857 foreverFrame: {858 count: 0,859 connections: {}860 }861 };862}(window.jQuery, window));863/* jquery.signalR.transports.webSockets.js */864// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.md in the project root for license information.865/*global window:false */866/// <reference path="jquery.signalR.transports.common.js" />867(function ($, window) {868 "use strict";869 var signalR = $.signalR,870 events = $.signalR.events,871 changeState = $.signalR.changeState,872 transportLogic = signalR.transports._logic;873 signalR.transports.webSockets = {874 name: "webSockets",875 supportsKeepAlive: true,876 send: function (connection, data) {877 connection.socket.send(data);878 },879 start: function (connection, onSuccess, onFailed) {880 var url,881 opened = false,882 that = this,883 reconnecting = !onSuccess,884 $connection = $(connection);885 if (!window.WebSocket) {886 onFailed();887 return;888 }889 if (!connection.socket) {890 if (connection.webSocketServerUrl) {891 url = connection.webSocketServerUrl;892 }893 else {894 url = connection.wsProtocol + connection.host;895 }896 url += transportLogic.getUrl(connection, this.name, reconnecting);897 connection.log("Connecting to websocket endpoint '" + url + "'");898 connection.socket = new window.WebSocket(url);899 connection.socket.onopen = function () {900 opened = true;901 connection.log("Websocket opened");902 transportLogic.clearReconnectTimeout(connection);903 if (onSuccess) {904 onSuccess();905 } else if (changeState(connection,906 signalR.connectionState.reconnecting,907 signalR.connectionState.connected) === true) {908 $connection.triggerHandler(events.onReconnect);909 }910 };911 connection.socket.onclose = function (event) {912 // Only handle a socket close if the close is from the current socket.913 // Sometimes on disconnect the server will push down an onclose event914 // to an expired socket.915 if (this === connection.socket) {916 if (!opened) {917 if (onFailed) {918 onFailed();919 }920 else if (reconnecting) {921 that.reconnect(connection);922 }923 return;924 }925 else if (typeof event.wasClean !== "undefined" && event.wasClean === false) {926 // Ideally this would use the websocket.onerror handler (rather than checking wasClean in onclose) but927 // I found in some circumstances Chrome won't call onerror. This implementation seems to work on all browsers.928 $(connection).triggerHandler(events.onError, [event.reason]);929 connection.log("Unclean disconnect from websocket." + event.reason);930 }931 else {932 connection.log("Websocket closed");933 }934 that.reconnect(connection);935 }936 };937 connection.socket.onmessage = function (event) {938 var data = window.JSON.parse(event.data),939 $connection = $(connection);940 if (data) {941 // data.M is PersistentResponse.Messages942 if ($.isEmptyObject(data) || data.M) {943 transportLogic.processMessages(connection, data);944 } else {945 // For websockets we need to trigger onReceived946 // for callbacks to outgoing hub calls.947 $connection.triggerHandler(events.onReceived, [data]);948 }949 }950 };951 }952 },953 reconnect: function (connection) {954 transportLogic.reconnect(connection, this.name);955 },956 lostConnection: function (connection) {957 this.reconnect(connection);958 },959 stop: function (connection) {960 // Don't trigger a reconnect after stopping961 transportLogic.clearReconnectTimeout(connection);962 if (connection.socket !== null) {963 connection.log("Closing the Websocket");964 connection.socket.close();965 connection.socket = null;966 }967 },968 abort: function (connection) {969 }970 };971}(window.jQuery, window));972/* jquery.signalR.transports.serverSentEvents.js */973// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.md in the project root for license information.974/*global window:false */975/// <reference path="jquery.signalR.transports.common.js" />976(function ($, window) {977 "use strict";978 var signalR = $.signalR,979 events = $.signalR.events,980 changeState = $.signalR.changeState,981 transportLogic = signalR.transports._logic;982 signalR.transports.serverSentEvents = {983 name: "serverSentEvents",984 supportsKeepAlive: true,985 timeOut: 3000,986 start: function (connection, onSuccess, onFailed) {987 var that = this,988 opened = false,989 $connection = $(connection),990 reconnecting = !onSuccess,991 url,992 connectTimeOut;993 if (connection.eventSource) {994 connection.log("The connection already has an event source. Stopping it.");995 connection.stop();996 }997 if (!window.EventSource) {998 if (onFailed) {999 connection.log("This browser doesn't support SSE.");1000 onFailed();1001 }1002 return;1003 }1004 url = transportLogic.getUrl(connection, this.name, reconnecting);1005 try {1006 connection.log("Attempting to connect to SSE endpoint '" + url + "'");1007 connection.eventSource = new window.EventSource(url);1008 }1009 catch (e) {1010 connection.log("EventSource failed trying to connect with error " + e.Message);1011 if (onFailed) {1012 // The connection failed, call the failed callback1013 onFailed();1014 }1015 else {1016 $connection.triggerHandler(events.onError, [e]);1017 if (reconnecting) {1018 // If we were reconnecting, rather than doing initial connect, then try reconnect again1019 that.reconnect(connection);1020 }1021 }1022 return;1023 }1024 // After connecting, if after the specified timeout there's no response stop the connection1025 // and raise on failed1026 connectTimeOut = window.setTimeout(function () {1027 if (opened === false) {1028 connection.log("EventSource timed out trying to connect");1029 connection.log("EventSource readyState: " + connection.eventSource.readyState);1030 if (!reconnecting) {1031 that.stop(connection);1032 }1033 if (reconnecting) {1034 // If we're reconnecting and the event source is attempting to connect,1035 // don't keep retrying. This causes duplicate connections to spawn.1036 if (connection.eventSource.readyState !== window.EventSource.CONNECTING &&1037 connection.eventSource.readyState !== window.EventSource.OPEN) {1038 // If we were reconnecting, rather than doing initial connect, then try reconnect again1039 that.reconnect(connection);1040 }1041 } else if (onFailed) {1042 onFailed();1043 }1044 }1045 },1046 that.timeOut);1047 connection.eventSource.addEventListener("open", function (e) {1048 connection.log("EventSource connected");1049 if (connectTimeOut) {1050 window.clearTimeout(connectTimeOut);1051 }1052 transportLogic.clearReconnectTimeout(connection);1053 if (opened === false) {1054 opened = true;1055 if (onSuccess) {1056 onSuccess();1057 } else if (changeState(connection,1058 signalR.connectionState.reconnecting,1059 signalR.connectionState.connected) === true) {1060 // If there's no onSuccess handler we assume this is a reconnect1061 $connection.triggerHandler(events.onReconnect);1062 }1063 }1064 }, false);1065 connection.eventSource.addEventListener("message", function (e) {1066 // process messages1067 if (e.data === "initialized") {1068 return;1069 }1070 transportLogic.processMessages(connection, window.JSON.parse(e.data));1071 }, false);1072 connection.eventSource.addEventListener("error", function (e) {1073 // Only handle an error if the error is from the current Event Source.1074 // Sometimes on disconnect the server will push down an error event1075 // to an expired Event Source.1076 if (this === connection.eventSource) {1077 if (!opened) {1078 if (onFailed) {1079 onFailed();1080 }1081 return;1082 }1083 connection.log("EventSource readyState: " + connection.eventSource.readyState);1084 if (e.eventPhase === window.EventSource.CLOSED) {1085 // We don't use the EventSource's native reconnect function as it1086 // doesn't allow us to change the URL when reconnecting. We need1087 // to change the URL to not include the /connect suffix, and pass1088 // the last message id we received.1089 connection.log("EventSource reconnecting due to the server connection ending");1090 that.reconnect(connection);1091 } else {1092 // connection error1093 connection.log("EventSource error");1094 $connection.triggerHandler(events.onError);1095 }1096 }1097 }, false);1098 },1099 reconnect: function (connection) {1100 transportLogic.reconnect(connection, this.name);1101 },1102 lostConnection: function (connection) {1103 this.reconnect(connection);1104 },1105 send: function (connection, data) {1106 transportLogic.ajaxSend(connection, data);1107 },1108 stop: function (connection) {1109 // Don't trigger a reconnect after stopping1110 transportLogic.clearReconnectTimeout(connection);1111 if (connection && connection.eventSource) {1112 connection.log("EventSource calling close()");1113 connection.eventSource.close();1114 connection.eventSource = null;1115 delete connection.eventSource;1116 }1117 },1118 abort: function (connection, async) {1119 transportLogic.ajaxAbort(connection, async);1120 }1121 };1122}(window.jQuery, window));1123/* jquery.signalR.transports.foreverFrame.js */1124// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.md in the project root for license information.1125/*global window:false */1126/// <reference path="jquery.signalR.transports.common.js" />1127(function ($, window) {1128 "use strict";1129 var signalR = $.signalR,1130 events = $.signalR.events,1131 changeState = $.signalR.changeState,1132 transportLogic = signalR.transports._logic,1133 // Used to prevent infinite loading icon spins in older versions of ie1134 // We build this object inside a closure so we don't pollute the rest of 1135 // the foreverFrame transport with unnecessary functions/utilities.1136 loadPreventer = (function () {1137 var loadingFixIntervalId = null,1138 loadingFixInterval = 1000,1139 attachedTo = 0;1140 return {1141 prevent: function () {1142 // Prevent additional iframe removal procedures from newer browsers1143 if (signalR._.ieVersion <= 8) {1144 // We only ever want to set the interval one time, so on the first attachedTo1145 if (attachedTo === 0) {1146 // Create and destroy iframe every 3 seconds to prevent loading icon, super hacky1147 loadingFixIntervalId = window.setInterval(function () {1148 var tempFrame = $("<iframe style='position:absolute;top:0;left:0;width:0;height:0;visibility:hidden;' src=''></iframe>");1149 $("body").append(tempFrame);1150 tempFrame.remove();1151 tempFrame = null;1152 }, loadingFixInterval);1153 }1154 attachedTo++;1155 }1156 },1157 cancel: function () { 1158 // Only clear the interval if there's only one more object that the loadPreventer is attachedTo1159 if (attachedTo === 1) {1160 window.clearInterval(loadingFixIntervalId);1161 }1162 if (attachedTo > 0) {1163 attachedTo--;1164 }1165 }1166 };1167 })();1168 signalR.transports.foreverFrame = {1169 name: "foreverFrame",1170 supportsKeepAlive: true,1171 timeOut: 3000,1172 start: function (connection, onSuccess, onFailed) {1173 var that = this,1174 frameId = (transportLogic.foreverFrame.count += 1),1175 url,1176 frame = $("<iframe data-signalr-connection-id='" + connection.id + "' style='position:absolute;top:0;left:0;width:0;height:0;visibility:hidden;' src=''></iframe>");1177 if (window.EventSource) {1178 // If the browser supports SSE, don't use Forever Frame1179 if (onFailed) {1180 connection.log("This browser supports SSE, skipping Forever Frame.");1181 onFailed();1182 }1183 return;1184 }1185 // Start preventing loading icon1186 // This will only perform work if the loadPreventer is not attached to another connection.1187 loadPreventer.prevent();1188 // Build the url1189 url = transportLogic.getUrl(connection, this.name);1190 url += "&frameId=" + frameId;1191 // Set body prior to setting URL to avoid caching issues.1192 $("body").append(frame);1193 frame.prop("src", url);1194 transportLogic.foreverFrame.connections[frameId] = connection;1195 connection.log("Binding to iframe's readystatechange event.");1196 frame.bind("readystatechange", function () {1197 if ($.inArray(this.readyState, ["loaded", "complete"]) >= 0) {1198 connection.log("Forever frame iframe readyState changed to " + this.readyState + ", reconnecting");1199 that.reconnect(connection);1200 }1201 });1202 connection.frame = frame[0];1203 connection.frameId = frameId;1204 if (onSuccess) {1205 connection.onSuccess = onSuccess;1206 }1207 // After connecting, if after the specified timeout there's no response stop the connection1208 // and raise on failed1209 window.setTimeout(function () {1210 if (connection.onSuccess) {1211 connection.log("Failed to connect using forever frame source, it timed out after " + that.timeOut + "ms.");1212 that.stop(connection);1213 if (onFailed) {1214 onFailed();1215 }1216 }1217 }, that.timeOut);1218 },1219 reconnect: function (connection) {1220 var that = this;1221 window.setTimeout(function () {1222 if (connection.frame && transportLogic.ensureReconnectingState(connection)) {1223 var frame = connection.frame,1224 src = transportLogic.getUrl(connection, that.name, true) + "&frameId=" + connection.frameId;1225 connection.log("Updating iframe src to '" + src + "'.");1226 frame.src = src;1227 }1228 }, connection.reconnectDelay);1229 },1230 lostConnection: function (connection) {1231 this.reconnect(connection);1232 },1233 send: function (connection, data) {1234 transportLogic.ajaxSend(connection, data);1235 },1236 receive: function (connection, data) {1237 var cw;1238 transportLogic.processMessages(connection, data);1239 // Delete the script & div elements1240 connection.frameMessageCount = (connection.frameMessageCount || 0) + 1;1241 if (connection.frameMessageCount > 50) {1242 connection.frameMessageCount = 0;1243 cw = connection.frame.contentWindow || connection.frame.contentDocument;1244 if (cw && cw.document) {1245 $("body", cw.document).empty();1246 }1247 }1248 },1249 stop: function (connection) {1250 var cw = null;1251 // Stop attempting to prevent loading icon1252 loadPreventer.cancel();1253 if (connection.frame) {1254 if (connection.frame.stop) {1255 connection.frame.stop();1256 } else {1257 try {1258 cw = connection.frame.contentWindow || connection.frame.contentDocument;1259 if (cw.document && cw.document.execCommand) {1260 cw.document.execCommand("Stop");1261 }1262 }1263 catch (e) {1264 connection.log("SignalR: Error occured when stopping foreverFrame transport. Message = " + e.message);1265 }1266 }1267 $(connection.frame).remove();1268 delete transportLogic.foreverFrame.connections[connection.frameId];1269 connection.frame = null;1270 connection.frameId = null;1271 delete connection.frame;1272 delete connection.frameId;1273 connection.log("Stopping forever frame");1274 }1275 },1276 abort: function (connection, async) {1277 transportLogic.ajaxAbort(connection, async);1278 },1279 getConnection: function (id) {1280 return transportLogic.foreverFrame.connections[id];1281 },