2956 lines · 120.5 KB · JavaScript
RawDownload
/* jquery.signalR.core.js *//*global window:false *//*! * ASP.NET SignalR JavaScript Library v2.2.2 * http://signalr.net/ * * Copyright (c) .NET Foundation. All rights reserved. * Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. * */ (function ($, window, undefined) {     var resources = {        nojQuery: "jQuery was not found. Please ensure jQuery is referenced before the SignalR client JavaScript file.",        noTransportOnInit: "No transport could be initialized successfully. Try specifying a different transport or none at all for auto initialization.",        errorOnNegotiate: "Error during negotiation request.",        stoppedWhileLoading: "The connection was stopped during page load.",        stoppedWhileNegotiating: "The connection was stopped during the negotiate request.",        errorParsingNegotiateResponse: "Error parsing negotiate response.",        errorDuringStartRequest: "Error during start request. Stopping the connection.",        stoppedDuringStartRequest: "The connection was stopped during the start request.",        errorParsingStartResponse: "Error parsing start response: '{0}'. Stopping the connection.",        invalidStartResponse: "Invalid start response: '{0}'. Stopping the connection.",        protocolIncompatible: "You are using a version of the client that isn't compatible with the server. Client version {0}, server version {1}.",        sendFailed: "Send failed.",        parseFailed: "Failed at parsing response: {0}",        longPollFailed: "Long polling request failed.",        eventSourceFailedToConnect: "EventSource failed to connect.",        eventSourceError: "Error raised by EventSource",        webSocketClosed: "WebSocket closed.",        pingServerFailedInvalidResponse: "Invalid ping response when pinging server: '{0}'.",        pingServerFailed: "Failed to ping server.",        pingServerFailedStatusCode: "Failed to ping server.  Server responded with status code {0}, stopping the connection.",        pingServerFailedParse: "Failed to parse ping server response, stopping the connection.",        noConnectionTransport: "Connection is in an invalid state, there is no transport active.",        webSocketsInvalidState: "The Web Socket transport is in an invalid state, transitioning into reconnecting.",        reconnectTimeout: "Couldn't reconnect within the configured timeout of {0} ms, disconnecting.",        reconnectWindowTimeout: "The client has been inactive since {0} and it has exceeded the inactivity timeout of {1} ms. Stopping the connection."    };     if (typeof ($) !== "function") {        // no jQuery!        throw new Error(resources.nojQuery);    }     var signalR,        _connection,        _pageLoaded = (window.document.readyState === "complete"),        _pageWindow = $(window),        _negotiateAbortText = "__Negotiate Aborted__",        events = {            onStart: "onStart",            onStarting: "onStarting",            onReceived: "onReceived",            onError: "onError",            onConnectionSlow: "onConnectionSlow",            onReconnecting: "onReconnecting",            onReconnect: "onReconnect",            onStateChanged: "onStateChanged",            onDisconnect: "onDisconnect"        },        ajaxDefaults = {            processData: true,            timeout: null,            async: true,            global: false,            cache: false        },        log = function (msg, logging) {            if (logging === false) {                return;            }            var m;            if (typeof (window.console) === "undefined") {                return;            }            m = "[" + new Date().toTimeString() + "] SignalR: " + msg;            if (window.console.debug) {                window.console.debug(m);            } else if (window.console.log) {                window.console.log(m);            }        },         changeState = function (connection, expectedState, newState) {            if (expectedState === connection.state) {                connection.state = newState;                 $(connection).triggerHandler(events.onStateChanged, [{ oldState: expectedState, newState: newState }]);                return true;            }             return false;        },         isDisconnecting = function (connection) {            return connection.state === signalR.connectionState.disconnected;        },         supportsKeepAlive = function (connection) {            return connection._.keepAliveData.activated &&                   connection.transport.supportsKeepAlive(connection);        },         configureStopReconnectingTimeout = function (connection) {            var stopReconnectingTimeout,                onReconnectTimeout;             // Check if this connection has already been configured to stop reconnecting after a specified timeout.            // Without this check if a connection is stopped then started events will be bound multiple times.            if (!connection._.configuredStopReconnectingTimeout) {                onReconnectTimeout = function (connection) {                    var message = signalR._.format(signalR.resources.reconnectTimeout, connection.disconnectTimeout);                    connection.log(message);                    $(connection).triggerHandler(events.onError, [signalR._.error(message, /* source */ "TimeoutException")]);                    connection.stop(/* async */ false, /* notifyServer */ false);                };                 connection.reconnecting(function () {                    var connection = this;                     // Guard against state changing in a previous user defined even handler                    if (connection.state === signalR.connectionState.reconnecting) {                        stopReconnectingTimeout = window.setTimeout(function () { onReconnectTimeout(connection); }, connection.disconnectTimeout);                    }                });                 connection.stateChanged(function (data) {                    if (data.oldState === signalR.connectionState.reconnecting) {                        // Clear the pending reconnect timeout check                        window.clearTimeout(stopReconnectingTimeout);                    }                });                 connection._.configuredStopReconnectingTimeout = true;            }        };     signalR = function (url, qs, logging) {        /// <summary>Creates a new SignalR connection for the given url</summary>        /// <param name="url" type="String">The URL of the long polling endpoint</param>        /// <param name="qs" type="Object">        ///     [Optional] Custom querystring parameters to add to the connection URL.        ///     If an object, every non-function member will be added to the querystring.        ///     If a string, it's added to the QS as specified.        /// </param>        /// <param name="logging" type="Boolean">        ///     [Optional] A flag indicating whether connection logging is enabled to the browser        ///     console/log. Defaults to false.        /// </param>         return new signalR.fn.init(url, qs, logging);    };     signalR._ = {        defaultContentType: "application/x-www-form-urlencoded; charset=UTF-8",         ieVersion: (function () {            var version,                matches;             if (window.navigator.appName === 'Microsoft Internet Explorer') {                // Check if the user agent has the pattern "MSIE (one or more numbers).(one or more numbers)";                matches = /MSIE ([0-9]+\.[0-9]+)/.exec(window.navigator.userAgent);                 if (matches) {                    version = window.parseFloat(matches[1]);                }            }             // undefined value means not IE            return version;        })(),         error: function (message, source, context) {            var e = new Error(message);            e.source = source;             if (typeof context !== "undefined") {                e.context = context;            }             return e;        },         transportError: function (message, transport, source, context) {            var e = this.error(message, source, context);            e.transport = transport ? transport.name : undefined;            return e;        },         format: function () {            /// <summary>Usage: format("Hi {0}, you are {1}!", "Foo", 100) </summary>            var s = arguments[0];            for (var i = 0; i < arguments.length - 1; i++) {                s = s.replace("{" + i + "}", arguments[i + 1]);            }            return s;        },         firefoxMajorVersion: function (userAgent) {            // Firefox user agents: http://useragentstring.com/pages/Firefox/            var matches = userAgent.match(/Firefox\/(\d+)/);            if (!matches || !matches.length || matches.length < 2) {                return 0;            }            return parseInt(matches[1], 10 /* radix */);        },         configurePingInterval: function (connection) {            var config = connection._.config,                onFail = function (error) {                    $(connection).triggerHandler(events.onError, [error]);                };             if (config && !connection._.pingIntervalId && config.pingInterval) {                connection._.pingIntervalId = window.setInterval(function () {                    signalR.transports._logic.pingServer(connection).fail(onFail);                }, config.pingInterval);            }        }    };     signalR.events = events;     signalR.resources = resources;     signalR.ajaxDefaults = ajaxDefaults;     signalR.changeState = changeState;     signalR.isDisconnecting = isDisconnecting;     signalR.connectionState = {        connecting: 0,        connected: 1,        reconnecting: 2,        disconnected: 4    };     signalR.hub = {        start: function () {            // This will get replaced with the real hub connection start method when hubs is referenced correctly            throw new Error("SignalR: Error loading hubs. Ensure your hubs reference is correct, e.g. <script src='/signalr/js'></script>.");        }    };     // .on() was added in version 1.7.0, .load() was removed in version 3.0.0 so we fallback to .load() if .on() does    // not exist to not break existing applications    if (typeof _pageWindow.on == "function") {        _pageWindow.on("load", function () { _pageLoaded = true; });    }    else {        _pageWindow.load(function () { _pageLoaded = true; });    }     function validateTransport(requestedTransport, connection) {        /// <summary>Validates the requested transport by cross checking it with the pre-defined signalR.transports</summary>        /// <param name="requestedTransport" type="Object">The designated transports that the user has specified.</param>        /// <param name="connection" type="signalR">The connection that will be using the requested transports.  Used for logging purposes.</param>        /// <returns type="Object" />         if ($.isArray(requestedTransport)) {            // Go through transport array and remove an "invalid" tranports            for (var i = requestedTransport.length - 1; i >= 0; i--) {                var transport = requestedTransport[i];                if ($.type(transport) !== "string" || !signalR.transports[transport]) {                    connection.log("Invalid transport: " + transport + ", removing it from the transports list.");                    requestedTransport.splice(i, 1);                }            }             // Verify we still have transports left, if we dont then we have invalid transports            if (requestedTransport.length === 0) {                connection.log("No transports remain within the specified transport array.");                requestedTransport = null;            }        } else if (!signalR.transports[requestedTransport] && requestedTransport !== "auto") {            connection.log("Invalid transport: " + requestedTransport.toString() + ".");            requestedTransport = null;        } else if (requestedTransport === "auto" && signalR._.ieVersion <= 8) {            // If we're doing an auto transport and we're IE8 then force longPolling, #1764            return ["longPolling"];         }         return requestedTransport;    }     function getDefaultPort(protocol) {        if (protocol === "http:") {            return 80;        } else if (protocol === "https:") {            return 443;        }    }     function addDefaultPort(protocol, url) {        // Remove ports  from url.  We have to check if there's a / or end of line        // following the port in order to avoid removing ports such as 8080.        if (url.match(/:\d+$/)) {            return url;        } else {            return url + ":" + getDefaultPort(protocol);        }    }     function ConnectingMessageBuffer(connection, drainCallback) {        var that = this,            buffer = [];         that.tryBuffer = function (message) {            if (connection.state === $.signalR.connectionState.connecting) {                buffer.push(message);                 return true;            }             return false;        };         that.drain = function () {            // Ensure that the connection is connected when we drain (do not want to drain while a connection is not active)            if (connection.state === $.signalR.connectionState.connected) {                while (buffer.length > 0) {                    drainCallback(buffer.shift());                }            }        };         that.clear = function () {            buffer = [];        };    }     signalR.fn = signalR.prototype = {        init: function (url, qs, logging) {            var $connection = $(this);             this.url = url;            this.qs = qs;            this.lastError = null;            this._ = {                keepAliveData: {},                connectingMessageBuffer: new ConnectingMessageBuffer(this, function (message) {                    $connection.triggerHandler(events.onReceived, [message]);                }),                lastMessageAt: new Date().getTime(),                lastActiveAt: new Date().getTime(),                beatInterval: 5000, // Default value, will only be overridden if keep alive is enabled,                beatHandle: null,                totalTransportConnectTimeout: 0 // This will be the sum of the TransportConnectTimeout sent in response to negotiate and connection.transportConnectTimeout            };            if (typeof (logging) === "boolean") {                this.logging = logging;            }        },         _parseResponse: function (response) {            var that = this;             if (!response) {                return response;            } else if (typeof response === "string") {                return that.json.parse(response);            } else {                return response;            }        },         _originalJson: window.JSON,         json: window.JSON,         isCrossDomain: function (url, against) {            /// <summary>Checks if url is cross domain</summary>            /// <param name="url" type="String">The base URL</param>            /// <param name="against" type="Object">            ///     An optional argument to compare the URL against, if not specified it will be set to window.location.            ///     If specified it must contain a protocol and a host property.            /// </param>            var link;             url = $.trim(url);             against = against || window.location;             if (url.indexOf("http") !== 0) {                return false;            }             // Create an anchor tag.            link = window.document.createElement("a");            link.href = url;             // When checking for cross domain we have to special case port 80 because the window.location will remove the            return link.protocol + addDefaultPort(link.protocol, link.host) !== against.protocol + addDefaultPort(against.protocol, against.host);        },         ajaxDataType: "text",         contentType: "application/json; charset=UTF-8",         logging: false,         state: signalR.connectionState.disconnected,         clientProtocol: "1.5",         reconnectDelay: 2000,         transportConnectTimeout: 0,         disconnectTimeout: 30000, // This should be set by the server in response to the negotiate request (30s default)         reconnectWindow: 30000, // This should be set by the server in response to the negotiate request         keepAliveWarnAt: 2 / 3, // Warn user of slow connection if we breach the X% mark of the keep alive timeout         start: function (options, callback) {            /// <summary>Starts the connection</summary>            /// <param name="options" type="Object">Options map</param>            /// <param name="callback" type="Function">A callback function to execute when the connection has started</param>            var connection = this,                config = {                    pingInterval: 300000,                    waitForPageLoad: true,                    transport: "auto",                    jsonp: false                },                initialize,                deferred = connection._deferral || $.Deferred(), // Check to see if there is a pre-existing deferral that's being built on, if so we want to keep using it                parser = window.document.createElement("a");             connection.lastError = null;             // Persist the deferral so that if start is called multiple times the same deferral is used.            connection._deferral = deferred;             if (!connection.json) {                // no JSON!                throw new Error("SignalR: No JSON parser found. Please ensure json2.js is referenced before the SignalR.js file if you need to support clients without native JSON parsing support, e.g. IE<8.");            }             if ($.type(options) === "function") {                // Support calling with single callback parameter                callback = options;            } else if ($.type(options) === "object") {                $.extend(config, options);                if ($.type(config.callback) === "function") {                    callback = config.callback;                }            }             config.transport = validateTransport(config.transport, connection);             // If the transport is invalid throw an error and abort start            if (!config.transport) {                throw new Error("SignalR: Invalid transport(s) specified, aborting start.");            }             connection._.config = config;             // Check to see if start is being called prior to page load            // If waitForPageLoad is true we then want to re-direct function call to the window load event            if (!_pageLoaded && config.waitForPageLoad === true) {                connection._.deferredStartHandler = function () {                    connection.start(options, callback);                };                _pageWindow.bind("load", connection._.deferredStartHandler);                 return deferred.promise();            }             // If we're already connecting just return the same deferral as the original connection start            if (connection.state === signalR.connectionState.connecting) {                return deferred.promise();            } else if (changeState(connection,                            signalR.connectionState.disconnected,                            signalR.connectionState.connecting) === false) {                // We're not connecting so try and transition into connecting.                // If we fail to transition then we're either in connected or reconnecting.                 deferred.resolve(connection);                return deferred.promise();            }             configureStopReconnectingTimeout(connection);             // Resolve the full url            parser.href = connection.url;            if (!parser.protocol || parser.protocol === ":") {                connection.protocol = window.document.location.protocol;                connection.host = parser.host || window.document.location.host;            } else {                connection.protocol = parser.protocol;                connection.host = parser.host;            } 

Lines 1–500 of 2956.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t