PageSourceSearch

https://super.9453job.com/Scripts/jquery.signalR-2.2.2.js

js 9453job.com collected 2026-10-02 15:08:29 UTC 126,534 bytes, 2,958 lines download raw bytes

vendor: 4,829 bytes, lines 1-105
1/* jquery.signalR.core.js */
2/*global window:false */
3/*!
4 * ASP.NET SignalR JavaScript Library v2.2.2
5 * http://signalr.net/
6 *
7 * Copyright (c) .NET Foundation. All rights reserved.
8 * Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
9 *
10 */
11
12/// <reference path="Scripts/jquery-1.6.4.js" />
13/// <reference path="jquery.signalR.version.js" />
14(function ($, window, undefined) {
15
16    var resources = {
17        nojQuery: "jQuery was not found. Please ensure jQuery is referenced before the SignalR client JavaScript file.",
18        noTransportOnInit: "No transport could be initialized successfully. Try specifying a different transport or none at all for auto initialization.",
19        errorOnNegotiate: "Error during negotiation request.",
20        stoppedWhileLoading: "The connection was stopped during page load.",
21        stoppedWhileNegotiating: "The connection was stopped during the negotiate request.",
22        errorParsingNegotiateResponse: "Error parsing negotiate response.",
23        errorDuringStartRequest: "Error during start request. Stopping the connection.",
24        stoppedDuringStartRequest: "The connection was stopped during the start request.",
25        errorParsingStartResponse: "Error parsing start response: '{0}'. Stopping the connection.",
26        invalidStartResponse: "Invalid start response: '{0}'. Stopping the connection.",
27        protocolIncompatible: "You are using a version of the client that isn't compatible with the server. Client version {0}, server version {1}.",
28        sendFailed: "Send failed.",
29        parseFailed: "Failed at parsing response: {0}",
30        longPollFailed: "Long polling request failed.",
31        eventSourceFailedToConnect: "EventSource failed to connect.",
32        eventSourceError: "Error raised by EventSource",
33        webSocketClosed: "WebSocket closed.",
34        pingServerFailedInvalidResponse: "Invalid ping response when pinging server: '{0}'.",
35        pingServerFailed: "Failed to ping server.",
36        pingServerFailedStatusCode: "Failed to ping server.  Server responded with status code {0}, stopping the connection.",
37        pingServerFailedParse: "Failed to parse ping server response, stopping the connection.",
38        noConnectionTransport: "Connection is in an invalid state, there is no transport active.",
39        webSocketsInvalidState: "The Web Socket transport is in an invalid state, transitioning into reconnecting.",
40        reconnectTimeout: "Couldn't reconnect within the configured timeout of {0} ms, disconnecting.",
41        reconnectWindowTimeout: "The client has been inactive since {0} and it has exceeded the inactivity timeout of {1} ms. Stopping the connection."
42    };
43
44    if (typeof ($) !== "function") {
45        // no jQuery!
46        throw new Error(resources.nojQuery);
47    }
48
49    var signalR,
50        _connection,
51        _pageLoaded = (window.document.readyState === "complete"),
52        _pageWindow = $(window),
53        _negotiateAbortText = "__Negotiate Aborted__",
54        events = {
55            onStart: "onStart",
56            onStarting: "onStarting",
57            onReceived: "onReceived",
58            onError: "onError",
59            onConnectionSlow: "onConnectionSlow",
60            onReconnecting: "onReconnecting",
61            onReconnect: "onReconnect",
62            onStateChanged: "onStateChanged",
63            onDisconnect: "onDisconnect"
64        },
65        ajaxDefaults = {
66            processData: true,
67            timeout: null,
68            async: true,
69            global: false,
70            cache: false
71        },
72        log = function (msg, logging) {
73            if (logging === false) {
74                return;
75            }
76            var m;
77            if (typeof (window.console) === "undefined") {
78                return;
79            }
80            m = "[" + new Date().toTimeString() + "] SignalR: " + msg;
81            if (window.console.debug) {
82                window.console.debug(m);
83            } else if (window.console.log) {
84                window.console.log(m);
85            }
86        },
87
88        changeState = function (connection, expectedState, newState) {
89            if (expectedState === connection.state) {
90                connection.state = newState;
91
92                $(connection).triggerHandler(events.onStateChanged, [{ oldState: expectedState, newState: newState }]);
93                return true;
94            }
95
96            return false;
97        },
98
99        isDisconnecting = function (connection) {
100            return connection.state === signalR.connectionState.disconnected;
101        },
102
103        supportsKeepAlive = function (connection) {
104            return connection._.keepAliveData.activated &&
105   
vendor: 6,071 bytes, lines 105-253
105                connection.transport.supportsKeepAlive(connection);
106        },
107
108        configureStopReconnectingTimeout = function (connection) {
109            var stopReconnectingTimeout,
110                onReconnectTimeout;
111
112            // Check if this connection has already been configured to stop reconnecting after a specified timeout.
113            // Without this check if a connection is stopped then started events will be bound multiple times.
114            if (!connection._.configuredStopReconnectingTimeout) {
115                onReconnectTimeout = function (connection) {
116                    var message = signalR._.format(signalR.resources.reconnectTimeout, connection.disconnectTimeout);
117                    connection.log(message);
118                    $(connection).triggerHandler(events.onError, [signalR._.error(message, /* source */ "TimeoutException")]);
119                    connection.stop(/* async */ false, /* notifyServer */ false);
120                };
121
122                connection.reconnecting(function () {
123                    var connection = this;
124
125                    // Guard against state changing in a previous user defined even handler
126                    if (connection.state === signalR.connectionState.reconnecting) {
127                        stopReconnectingTimeout = window.setTimeout(function () { onReconnectTimeout(connection); }, connection.disconnectTimeout);
128                    }
129                });
130
131                connection.stateChanged(function (data) {
132                    if (data.oldState === signalR.connectionState.reconnecting) {
133                        // Clear the pending reconnect timeout check
134                        window.clearTimeout(stopReconnectingTimeout);
135                    }
136                });
137
138                connection._.configuredStopReconnectingTimeout = true;
139            }
140        };
141
142    signalR = function (url, qs, logging) {
143        /// <summary>Creates a new SignalR connection for the given url</summary>
144        /// <param name="url" type="String">The URL of the long polling endpoint</param>
145        /// <param name="qs" type="Object">
146        ///     [Optional] Custom querystring parameters to add to the connection URL.
147        ///     If an object, every non-function member will be added to the querystring.
148        ///     If a string, it's added to the QS as specified.
149        /// </param>
150        /// <param name="logging" type="Boolean">
151        ///     [Optional] A flag indicating whether connection logging is enabled to the browser
152        ///     console/log. Defaults to false.
153        /// </param>
154
155        return new signalR.fn.init(url, qs, logging);
156    };
157
158    signalR._ = {
159        defaultContentType: "application/x-www-form-urlencoded; charset=UTF-8",
160
161        ieVersion: (function () {
162            var version,
163                matches;
164
165            if (window.navigator.appName === 'Microsoft Internet Explorer') {
166                // Check if the user agent has the pattern "MSIE (one or more numbers).(one or more numbers)";
167                matches = /MSIE ([0-9]+\.[0-9]+)/.exec(window.navigator.userAgent);
168
169                if (matches) {
170                    version = window.parseFloat(matches[1]);
171                }
172            }
173
174            // undefined value means not IE
175            return version;
176        })(),
177
178        error: function (message, source, context) {
179            var e = new Error(message);
180            e.source = source;
181
182            if (typeof context !== "undefined") {
183                e.context = context;
184            }
185
186            return e;
187        },
188
189        transportError: function (message, transport, source, context) {
190            var e = this.error(message, source, context);
191            e.transport = transport ? transport.name : undefined;
192            return e;
193        },
194
195        format: function () {
196            /// <summary>Usage: format("Hi {0}, you are {1}!", "Foo", 100) </summary>
197            var s = arguments[0];
198            for (var i = 0; i < arguments.length - 1; i++) {
199                s = s.replace("{" + i + "}", arguments[i + 1]);
200            }
201            return s;
202        },
203
204        firefoxMajorVersion: function (userAgent) {
205            // Firefox user agents: http://useragentstring.com/pages/Firefox/
206            var matches = userAgent.match(/Firefox\/(\d+)/);
207            if (!matches || !matches.length || matches.length < 2) {
208                return 0;
209            }
210            return parseInt(matches[1], 10 /* radix */);
211        },
212
213        configurePingInterval: function (connection) {
214            var config = connection._.config,
215                onFail = function (error) {
216                    $(connection).triggerHandler(events.onError, [error]);
217                };
218
219            if (config && !connection._.pingIntervalId && config.pingInterval) {
220                connection._.pingIntervalId = window.setInterval(function () {
221                    signalR.transports._logic.pingServer(connection).fail(onFail);
222                }, config.pingInterval);
223            }
224        }
225    };
226
227    signalR.events = events;
228
229    signalR.resources = resources;
230
231    signalR.ajaxDefaults = ajaxDefaults;
232
233    signalR.changeState = changeState;
234
235    signalR.isDisconnecting = isDisconnecting;
236
237    signalR.connectionState = {
238        connecting: 0,
239        connected: 1,
240        reconnecting: 2,
241        disconnected: 4
242    };
243
244    signalR.hub = {
245        start: function () {
246            // This will get replaced with the real hub connection start method when hubs is referenced correctly
247            throw new Error("SignalR: Error loading hubs. Ensure your hubs reference is correct, e.g. <script src='/signalr/js'></script>.");
248        }
249    };
250
251    // .on() was added in version 1.7.0, .load() was removed in version 3.0.0 so we fallback to .load() if .on() does
252    // not exist to not break existing applications
253    if (typeof _pageWindow.on ==
vendor: 32,824 bytes, lines 253-955
253 "function") {
254        _pageWindow.on("load", function () { _pageLoaded = true; });
255    }
256    else {
257        _pageWindow.load(function () { _pageLoaded = true; });
258    }
259
260    function validateTransport(requestedTransport, connection) {
261        /// <summary>Validates the requested transport by cross checking it with the pre-defined signalR.transports</summary>
262        /// <param name="requestedTransport" type="Object">The designated transports that the user has specified.</param>
263        /// <param name="connection" type="signalR">The connection that will be using the requested transports.  Used for logging purposes.</param>
264        /// <returns type="Object" />
265
266        if ($.isArray(requestedTransport)) {
267            // Go through transport array and remove an "invalid" tranports
268            for (var i = requestedTransport.length - 1; i >= 0; i--) {
269                var transport = requestedTransport[i];
270                if ($.type(transport) !== "string" || !signalR.transports[transport]) {
271                    connection.log("Invalid transport: " + transport + ", removing it from the transports list.");
272                    requestedTransport.splice(i, 1);
273                }
274            }
275
276            // Verify we still have transports left, if we dont then we have invalid transports
277            if (requestedTransport.length === 0) {
278                connection.log("No transports remain within the specified transport array.");
279                requestedTransport = null;
280            }
281        } else if (!signalR.transports[requestedTransport] && requestedTransport !== "auto") {
282            connection.log("Invalid transport: " + requestedTransport.toString() + ".");
283            requestedTransport = null;
284        } else if (requestedTransport === "auto" && signalR._.ieVersion <= 8) {
285            // If we're doing an auto transport and we're IE8 then force longPolling, #1764
286            return ["longPolling"];
287
288        }
289
290        return requestedTransport;
291    }
292
293    function getDefaultPort(protocol) {
294        if (protocol === "http:") {
295            return 80;
296        } else if (protocol === "https:") {
297            return 443;
298        }
299    }
300
301    function addDefaultPort(protocol, url) {
302        // Remove ports  from url.  We have to check if there's a / or end of line
303        // following the port in order to avoid removing ports such as 8080.
304        if (url.match(/:\d+$/)) {
305            return url;
306        } else {
307            return url + ":" + getDefaultPort(protocol);
308        }
309    }
310
311    function ConnectingMessageBuffer(connection, drainCallback) {
312        var that = this,
313            buffer = [];
314
315        that.tryBuffer = function (message) {
316            if (connection.state === $.signalR.connectionState.connecting) {
317                buffer.push(message);
318
319                return true;
320            }
321
322            return false;
323        };
324
325        that.drain = function () {
326            // Ensure that the connection is connected when we drain (do not want to drain while a connection is not active)
327            if (connection.state === $.signalR.connectionState.connected) {
328                while (buffer.length > 0) {
329                    drainCallback(buffer.shift());
330                }
331            }
332        };
333
334        that.clear = function () {
335            buffer = [];
336        };
337    }
338
339    signalR.fn = signalR.prototype = {
340        init: function (url, qs, logging) {
341            var $connection = $(this);
342
343            this.url = url;
344            this.qs = qs;
345            this.lastError = null;
346            this._ = {
347                keepAliveData: {},
348                connectingMessageBuffer: new ConnectingMessageBuffer(this, function (message) {
349                    $connection.triggerHandler(events.onReceived, [message]);
350                }),
351                lastMessageAt: new Date().getTime(),
352                lastActiveAt: new Date().getTime(),
353                beatInterval: 5000, // Default value, will only be overridden if keep alive is enabled,
354                beatHandle: null,
355                totalTransportConnectTimeout: 0 // This will be the sum of the TransportConnectTimeout sent in response to negotiate and connection.transportConnectTimeout
356            };
357            if (typeof (logging) === "boolean") {
358                this.logging = logging;
359            }
360        },
361
362        _parseResponse: function (response) {
363            var that = this;
364
365            if (!response) {
366                return response;
367            } else if (typeof response === "string") {
368                return that.json.parse(response);
369            } else {
370                return response;
371            }
372        },
373
374        _originalJson: window.JSON,
375
376        json: window.JSON,
377
378        isCrossDomain: function (url, against) {
379            /// <summary>Checks if url is cross domain</summary>
380            /// <param name="url" type="String">The base URL</param>
381            /// <param name="against" type="Object">
382            ///     An optional argument to compare the URL against, if not specified it will be set to window.location.
383            ///     If specified it must contain a protocol and a host property.
384            /// </param>
385            var link;
386
387            url = $.trim(url);
388
389            against = against || window.location;
390
391            if (url.indexOf("http") !== 0) {
392                return false;
393            }
394
395            // Create an anchor tag.
396            link = window.document.createElement("a");
397            link.href = url;
398
399            // When checking for cross domain we have to special case port 80 because the window.location will remove the
400            return link.protocol + addDefaultPort(link.protocol, link.host) !== against.protocol + addDefaultPort(against.protocol, against.host);
401        },
402
403        ajaxDataType: "text",
404
405        contentType: "application/json; charset=UTF-8",
406
407        logging: false,
408
409        state: signalR.connectionState.disconnected,
410
411        clientProtocol: "1.5",
412
413        reconnectDelay: 2000,
414
415        transportConnectTimeout: 0,
416
417        disconnectTimeout: 30000, // This should be set by the server in response to the negotiate request (30s default)
418
419        reconnectWindow: 30000, // This should be set by the server in response to the negotiate request
420
421        keepAliveWarnAt: 2 / 3, // Warn user of slow connection if we breach the X% mark of the keep alive timeout
422
423        start: function (options, callback) {
424            /// <summary>Starts the connection</summary>
425            /// <param name="options" type="Object">Options map</param>
426            /// <param name="callback" type="Function">A callback function to execute when the connection has started</param>
427            var connection = this,
428                config = {
429                    pingInterval: 300000,
430                    waitForPageLoad: true,
431                    transport: "auto",
432                    jsonp: false
433                },
434                initialize,
435                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
436                parser = window.document.createElement("a");
437
438            connection.lastError = null;
439
440            // Persist the deferral so that if start is called multiple times the same deferral is used.
441            connection._deferral = deferred;
442
443            if (!connection.json) {
444                // no JSON!
445                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.");
446            }
447
448            if ($.type(options) === "function") {
449                // Support calling with single callback parameter
450                callback = options;
451            } else if ($.type(options) === "object") {
452                $.extend(config, options);
453                if ($.type(config.callback) === "function") {
454                    callback = config.callback;
455                }
456            }
457
458            config.transport = validateTransport(config.transport, connection);
459
460            // If the transport is invalid throw an error and abort start
461            if (!config.transport) {
462                throw new Error("SignalR: Invalid transport(s) specified, aborting start.");
463            }
464
465            connection._.config = config;
466
467            // Check to see if start is being called prior to page load
468            // If waitForPageLoad is true we then want to re-direct function call to the window load event
469            if (!_pageLoaded && config.waitForPageLoad === true) {
470                connection._.deferredStartHandler = function () {
471                    connection.start(options, callback);
472                };
473                _pageWindow.bind("load", connection._.deferredStartHandler);
474
475                return deferred.promise();
476            }
477
478            // If we're already connecting just return the same deferral as the original connection start
479            if (connection.state === signalR.connectionState.connecting) {
480                return deferred.promise();
481            } else if (changeState(connection,
482                            signalR.connectionState.disconnected,
483                            signalR.connectionState.connecting) === false) {
484                // We're not connecting so try and transition into connecting.
485                // If we fail to transition then we're either in connected or reconnecting.
486
487                deferred.resolve(connection);
488                return deferred.promise();
489            }
490
491            configureStopReconnectingTimeout(connection);
492
493            // Resolve the full url
494            parser.href = connection.url;
495            if (!parser.protocol || parser.protocol === ":") {
496                connection.protocol = window.document.location.protocol;
497                connection.host = parser.host || window.document.location.host;
498            } else {
499                connection.protocol = parser.protocol;
500                connection.host = parser.host;
501            }
502
503            connection.baseUrl = connection.protocol + "//" + connection.host;
504
505            // Set the websocket protocol
506            connection.wsProtocol = connection.protocol === "https:" ? "wss://" : "ws://";
507
508            // If jsonp with no/auto transport is specified, then set the transport to long polling
509            // since that is the only transport for which jsonp really makes sense.
510            // Some developers might actually choose to specify jsonp for same origin requests
511            // as demonstrated by Issue #623.
512            if (config.transport === "auto" && config.jsonp === true) {
513                config.transport = "longPolling";
514            }
515
516            // If the url is protocol relative, prepend the current windows protocol to the url.
517            if (connection.url.indexOf("//") === 0) {
518                connection.url = window.location.protocol + connection.url;
519                connection.log("Protocol relative URL detected, normalizing it to '" + connection.url + "'.");
520            }
521
522            if (this.isCrossDomain(connection.url)) {
523                connection.log("Auto detected cross domain url.");
524
525                if (config.transport === "auto") {
526                    // TODO: Support XDM with foreverFrame
527                    config.transport = ["webSockets", "serverSentEvents", "longPolling"];
528                }
529
530                if (typeof (config.withCredentials) === "undefined") {
531                    config.withCredentials = true;
532                }
533
534                // Determine if jsonp is the only choice for negotiation, ajaxSend and ajaxAbort.
535                // i.e. if the browser doesn't supports CORS
536                // If it is, ignore any preference to the contrary, and switch to jsonp.
537                if (!config.jsonp) {
538                    config.jsonp = !$.support.cors;
539
540                    if (config.jsonp) {
541                        connection.log("Using jsonp because this browser doesn't support CORS.");
542                    }
543                }
544
545                connection.contentType = signalR._.defaultContentType;
546            }
547
548            connection.withCredentials = config.withCredentials;
549
550            connection.ajaxDataType = config.jsonp ? "jsonp" : "text";
551
552            $(connection).bind(events.onStart, function (e, data) {
553                if ($.type(callback) === "function") {
554                    callback.call(connection);
555                }
556                deferred.resolve(connection);
557            });
558
559            connection._.initHandler = signalR.transports._logic.initHandler(connection);
560
561            initialize = function (transports, index) {
562                var noTransportError = signalR._.error(resources.noTransportOnInit);
563
564                index = index || 0;
565                if (index >= transports.length) {
566                    if (index === 0) {
567                        connection.log("No transports supported by the server were selected.");
568                    } else if (index === 1) {
569                        connection.log("No fallback transports were selected.");
570                    } else {
571                        connection.log("Fallback transports exhausted.");
572                    }
573
574                    // No transport initialized successfully
575                    $(connection).triggerHandler(events.onError, [noTransportError]);
576                    deferred.reject(noTransportError);
577                    // Stop the connection if it has connected and move it into the disconnected state
578                    connection.stop();
579                    return;
580                }
581
582                // The connection was aborted
583                if (connection.state === signalR.connectionState.disconnected) {
584                    return;
585                }
586
587                var transportName = transports[index],
588                    transport = signalR.transports[transportName],
589                    onFallback = function () {
590                        initialize(transports, index + 1);
591                    };
592
593                connection.transport = transport;
594
595                try {
596                    connection._.initHandler.start(transport, function () { // success
597                        // Firefox 11+ doesn't allow sync XHR withCredentials: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#withCredentials
598                        var isFirefox11OrGreater = signalR._.firefoxMajorVersion(window.navigator.userAgent) >= 11,
599                            asyncAbort = !!connection.withCredentials && isFirefox11OrGreater;
600
601                        connection.log("The start request succeeded. Transitioning to the connected state.");
602
603                        if (supportsKeepAlive(connection)) {
604                            signalR.transports._logic.monitorKeepAlive(connection);
605                        }
606
607                        signalR.transports._logic.startHeartbeat(connection);
608
609                        // Used to ensure low activity clients maintain their authentication.
610                        // Must be configured once a transport has been decided to perform valid ping requests.
611                        signalR._.configurePingInterval(connection);
612
613                        if (!changeState(connection,
614                                            signalR.connectionState.connecting,
615                                            signalR.connectionState.connected)) {
616                            connection.log("WARNING! The connection was not in the connecting state.");
617                        }
618
619                        // Drain any incoming buffered messages (messages that came in prior to connect)
620                        connection._.connectingMessageBuffer.drain();
621
622                        $(connection).triggerHandler(events.onStart);
623
624                        // wire the stop handler for when the user leaves the page
625                        _pageWindow.bind("unload", function () {
626                            connection.log("Window unloading, stopping the connection.");
627
628                            connection.stop(asyncAbort);
629                        });
630
631                        if (isFirefox11OrGreater) {
632                            // Firefox does not fire cross-domain XHRs in the normal unload handler on tab close.
633                            // #2400
634                            _pageWindow.bind("beforeunload", function () {
635                                // If connection.stop() runs runs in beforeunload and fails, it will also fail
636                                // in unload unless connection.stop() runs after a timeout.
637                                window.setTimeout(function () {
638                                    connection.stop(asyncAbort);
639                                }, 0);
640                            });
641                        }
642                    }, onFallback);
643                }
644                catch (error) {
645                    connection.log(transport.name + " transport threw '" + error.message + "' when attempting to start.");
646                    onFallback();
647                }
648            };
649
650            var url = connection.url + "/negotiate",
651                onFailed = function (error, connection) {
652                    var err = signalR._.error(resources.errorOnNegotiate, error, connection._.negotiateRequest);
653
654                    $(connection).triggerHandler(events.onError, err);
655                    deferred.reject(err);
656                    // Stop the connection if negotiate failed
657                    connection.stop();
658                };
659
660            $(connection).triggerHandler(events.onStarting);
661
662            url = signalR.transports._logic.prepareQueryString(connection, url);
663
664            connection.log("Negotiating with '" + url + "'.");
665
666            // Save the ajax negotiate request object so we can abort it if stop is called while the request is in flight.
667            connection._.negotiateRequest = signalR.transports._logic.ajax(connection, {
668                url: url,
669                error: function (error, statusText) {
670                    // We don't want to cause any errors if we're aborting our own negotiate request.
671                    if (statusText !== _negotiateAbortText) {
672                        onFailed(error, connection);
673                    } else {
674                        // This rejection will noop if the deferred has already been resolved or rejected.
675                        deferred.reject(signalR._.error(resources.stoppedWhileNegotiating, null /* error */, connection._.negotiateRequest));
676                    }
677                },
678                success: function (result) {
679                    var res,
680                        keepAliveData,
681                        protocolError,
682                        transports = [],
683                        supportedTransports = [];
684
685                    try {
686                        res = connection._parseResponse(result);
687                    } catch (error) {
688                        onFailed(signalR._.error(resources.errorParsingNegotiateResponse, error), connection);
689                        return;
690                    }
691
692                    keepAliveData = connection._.keepAliveData;
693                    connection.appRelativeUrl = res.Url;
694                    connection.id = res.ConnectionId;
695                    connection.token = res.ConnectionToken;
696                    connection.webSocketServerUrl = res.WebSocketServerUrl;
697
698                    // The long poll timeout is the ConnectionTimeout plus 10 seconds
699                    connection._.pollTimeout = res.ConnectionTimeout * 1000 + 10000; // in ms
700
701                    // Once the server has labeled the PersistentConnection as Disconnected, we should stop attempting to reconnect
702                    // after res.DisconnectTimeout seconds.
703                    connection.disconnectTimeout = res.DisconnectTimeout * 1000; // in ms
704
705                    // Add the TransportConnectTimeout from the response to the transportConnectTimeout from the client to calculate the total timeout
706                    connection._.totalTransportConnectTimeout = connection.transportConnectTimeout + res.TransportConnectTimeout * 1000;
707
708                    // If we have a keep alive
709                    if (res.KeepAliveTimeout) {
710                        // Register the keep alive data as activated
711                        keepAliveData.activated = true;
712
713                        // Timeout to designate when to force the connection into reconnecting converted to milliseconds
714                        keepAliveData.timeout = res.KeepAliveTimeout * 1000;
715
716                        // Timeout to designate when to warn the developer that the connection may be dead or is not responding.
717                        keepAliveData.timeoutWarning = keepAliveData.timeout * connection.keepAliveWarnAt;
718
719                        // Instantiate the frequency in which we check the keep alive.  It must be short in order to not miss/pick up any changes
720                        connection._.beatInterval = (keepAliveData.timeout - keepAliveData.timeoutWarning) / 3;
721                    } else {
722                        keepAliveData.activated = false;
723                    }
724
725                    connection.reconnectWindow = connection.disconnectTimeout + (keepAliveData.timeout || 0);
726
727                    if (!res.ProtocolVersion || res.ProtocolVersion !== connection.clientProtocol) {
728                        protocolError = signalR._.error(signalR._.format(resources.protocolIncompatible, connection.clientProtocol, res.ProtocolVersion));
729                        $(connection).triggerHandler(events.onError, [protocolError]);
730                        deferred.reject(protocolError);
731
732                        return;
733                    }
734
735                    $.each(signalR.transports, function (key) {
736                        if ((key.indexOf("_") === 0) || (key === "webSockets" && !res.TryWebSockets)) {
737                            return true;
738                        }
739                        supportedTransports.push(key);
740                    });
741
742                    if ($.isArray(config.transport)) {
743                        $.each(config.transport, function (_, transport) {
744                            if ($.inArray(transport, supportedTransports) >= 0) {
745                                transports.push(transport);
746                            }
747                        });
748                    } else if (config.transport === "auto") {
749                        transports = supportedTransports;
750                    } else if ($.inArray(config.transport, supportedTransports) >= 0) {
751                        transports.push(config.transport);
752                    }
753
754                    initialize(transports);
755                }
756            });
757
758            return deferred.promise();
759        },
760
761        starting: function (callback) {
762            /// <summary>Adds a callback that will be invoked before anything is sent over the connection</summary>
763            /// <param name="callback" type="Function">A callback function to execute before the connection is fully instantiated.</param>
764            /// <returns type="signalR" />
765            var connection = this;
766            $(connection).bind(events.onStarting, function (e, data) {
767                callback.call(connection);
768            });
769            return connection;
770        },
771
772        send: function (data) {
773            /// <summary>Sends data over the connection</summary>
774            /// <param name="data" type="String">The data to send over the connection</param>
775            /// <returns type="signalR" />
776            var connection = this;
777
778            if (connection.state === signalR.connectionState.disconnected) {
779                // Connection hasn't been started yet
780                throw new Error("SignalR: Connection must be started before data can be sent. Call .start() before .send()");
781            }
782
783            if (connection.state === signalR.connectionState.connecting) {
784                // Connection hasn't been started yet
785                throw new Error("SignalR: Connection has not been fully initialized. Use .start().done() or .start().fail() to run logic after the connection has started.");
786            }
787
788            connection.transport.send(connection, data);
789            // REVIEW: Should we return deferred here?
790            return connection;
791        },
792
793        received: function (callback) {
794            /// <summary>Adds a callback that will be invoked after anything is received over the connection</summary>
795            /// <param name="callback" type="Function">A callback function to execute when any data is received on the connection</param>
796            /// <returns type="signalR" />
797            var connection = this;
798            $(connection).bind(events.onReceived, function (e, data) {
799                callback.call(connection, data);
800            });
801            return connection;
802        },
803
804        stateChanged: function (callback) {
805            /// <summary>Adds a callback that will be invoked when the connection state changes</summary>
806            /// <param name="callback" type="Function">A callback function to execute when the connection state changes</param>
807            /// <returns type="signalR" />
808            var connection = this;
809            $(connection).bind(events.onStateChanged, function (e, data) {
810                callback.call(connection, data);
811            });
812            return connection;
813        },
814
815        error: function (callback) {
816            /// <summary>Adds a callback that will be invoked after an error occurs with the connection</summary>
817            /// <param name="callback" type="Function">A callback function to execute when an error occurs on the connection</param>
818            /// <returns type="signalR" />
819            var connection = this;
820            $(connection).bind(events.onError, function (e, errorData, sendData) {
821                connection.lastError = errorData;
822                // In practice 'errorData' is the SignalR built error object.
823                // In practice 'sendData' is undefined for all error events except those triggered by
824                // 'ajaxSend' and 'webSockets.send'.'sendData' is the original send payload.
825                callback.call(connection, errorData, sendData);
826            });
827            return connection;
828        },
829
830        disconnected: function (callback) {
831            /// <summary>Adds a callback that will be invoked when the client disconnects</summary>
832            /// <param name="callback" type="Function">A callback function to execute when the connection is broken</param>
833            /// <returns type="signalR" />
834            var connection = this;
835            $(connection).bind(events.onDisconnect, function (e, data) {
836                callback.call(connection);
837            });
838            return connection;
839        },
840
841        connectionSlow: function (callback) {
842            /// <summary>Adds a callback that will be invoked when the client detects a slow connection</summary>
843            /// <param name="callback" type="Function">A callback function to execute when the connection is slow</param>
844            /// <returns type="signalR" />
845            var connection = this;
846            $(connection).bind(events.onConnectionSlow, function (e, data) {
847                callback.call(connection);
848            });
849
850            return connection;
851        },
852
853        reconnecting: function (callback) {
854            /// <summary>Adds a callback that will be invoked when the underlying transport begins reconnecting</summary>
855            /// <param name="callback" type="Function">A callback function to execute when the connection enters a reconnecting state</param>
856            /// <returns type="signalR" />
857            var connection = this;
858            $(connection).bind(events.onReconnecting, function (e, data) {
859                callback.call(connection);
860            });
861            return connection;
862        },
863
864        reconnected: function (callback) {
865            /// <summary>Adds a callback that will be invoked when the underlying transport reconnects</summary>
866            /// <param name="callback" type="Function">A callback function to execute when the connection is restored</param>
867            /// <returns type="signalR" />
868            var connection = this;
869            $(connection).bind(events.onReconnect, function (e, data) {
870                callback.call(connection);
871            });
872            return connection;
873        },
874
875        stop: function (async, notifyServer) {
876            /// <summary>Stops listening</summary>
877            /// <param name="async" type="Boolean">Whether or not to asynchronously abort the connection</param>
878            /// <param name="notifyServer" type="Boolean">Whether we want to notify the server that we are aborting the connection</param>
879            /// <returns type="signalR" />
880            var connection = this,
881                // Save deferral because this is always cleaned up
882                deferral = connection._deferral;
883
884            // Verify that we've bound a load event.
885            if (connection._.deferredStartHandler) {
886                // Unbind the event.
887                _pageWindow.unbind("load", connection._.deferredStartHandler);
888            }
889
890            // Always clean up private non-timeout based state.
891            delete connection._.config;
892            delete connection._.deferredStartHandler;
893
894            // This needs to be checked despite the connection state because a connection start can be deferred until page load.
895            // If we've deferred the start due to a page load we need to unbind the "onLoad" -> start event.
896            if (!_pageLoaded && (!connection._.config || connection._.config.waitForPageLoad === true)) {
897                connection.log("Stopping connection prior to negotiate.");
898
899                // If we have a deferral we should reject it
900                if (deferral) {
901                    deferral.reject(signalR._.error(resources.stoppedWhileLoading));
902                }
903
904                // Short-circuit because the start has not been fully started.
905                return;
906            }
907
908            if (connection.state === signalR.connectionState.disconnected) {
909                return;
910            }
911
912            connection.log("Stopping connection.");
913
914            // Clear this no matter what
915            window.clearTimeout(connection._.beatHandle);
916            window.clearInterval(connection._.pingIntervalId);
917
918            if (connection.transport) {
919                connection.transport.stop(connection);
920
921                if (notifyServer !== false) {
922                    connection.transport.abort(connection, async);
923                }
924
925                if (supportsKeepAlive(connection)) {
926                    signalR.transports._logic.stopMonitoringKeepAlive(connection);
927                }
928
929                connection.transport = null;
930            }
931
932            if (connection._.negotiateRequest) {
933                // If the negotiation request has already completed this will noop.
934                connection._.negotiateRequest.abort(_negotiateAbortText);
935                delete connection._.negotiateRequest;
936            }
937
938            // Ensure that initHandler.stop() is called before connection._deferral is deleted
939            if (connection._.initHandler) {
940                connection._.initHandler.stop();
941            }
942
943            delete connection._deferral;
944            delete connection.messageId;
945            delete connection.groupsToken;
946            delete connection.id;
947            delete connection._.pingIntervalId;
948            delete connection._.lastMessageAt;
949            delete connection._.lastActiveAt;
950
951            // Clear out our message buffer
952            connection._.connectingMessageBuffer.clear();
953            
954            // Clean up this event
955            $(connection).unbind(events.onStart)
vendor: 8,847 bytes, lines 955-1191
955;
956
957            // Trigger the disconnect event
958            changeState(connection, connection.state, signalR.connectionState.disconnected);
959            $(connection).triggerHandler(events.onDisconnect);
960
961            return connection;
962        },
963
964        log: function (msg) {
965            log(msg, this.logging);
966        }
967    };
968
969    signalR.fn.init.prototype = signalR.fn;
970
971    signalR.noConflict = function () {
972        /// <summary>Reinstates the original value of $.connection and returns the signalR object for manual assignment</summary>
973        /// <returns type="signalR" />
974        if ($.connection === signalR) {
975            $.connection = _connection;
976        }
977        return signalR;
978    };
979
980    if ($.connection) {
981        _connection = $.connection;
982    }
983
984    $.connection = $.signalR = signalR;
985
986}(window.jQuery, window));
987/* jquery.signalR.transports.common.js */
988// Copyright (c) .NET Foundation. All rights reserved.
989// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
990
991/*global window:false */
992/// <reference path="jquery.signalR.core.js" />
993
994(function ($, window, undefined) {
995
996    var signalR = $.signalR,
997        events = $.signalR.events,
998        changeState = $.signalR.changeState,
999        startAbortText = "__Start Aborted__",
1000        transportLogic;
1001
1002    signalR.transports = {};
1003
1004    function beat(connection) {
1005        if (connection._.keepAliveData.monitoring) {
1006            checkIfAlive(connection);
1007        }
1008
1009        // Ensure that we successfully marked active before continuing the heartbeat.
1010        if (transportLogic.markActive(connection)) {
1011            connection._.beatHandle = window.setTimeout(function () {
1012                beat(connection);
1013            }, connection._.beatInterval);
1014        }
1015    }
1016
1017    function checkIfAlive(connection) {
1018        var keepAliveData = connection._.keepAliveData,
1019            timeElapsed;
1020
1021        // Only check if we're connected
1022        if (connection.state === signalR.connectionState.connected) {
1023            timeElapsed = new Date().getTime() - connection._.lastMessageAt;
1024
1025            // Check if the keep alive has completely timed out
1026            if (timeElapsed >= keepAliveData.timeout) {
1027                connection.log("Keep alive timed out.  Notifying transport that connection has been lost.");
1028
1029                // Notify transport that the connection has been lost
1030                connection.transport.lostConnection(connection);
1031            } else if (timeElapsed >= keepAliveData.timeoutWarning) {
1032                // This is to assure that the user only gets a single warning
1033                if (!keepAliveData.userNotified) {
1034                    connection.log("Keep alive has been missed, connection may be dead/slow.");
1035                    $(connection).triggerHandler(events.onConnectionSlow);
1036                    keepAliveData.userNotified = true;
1037                }
1038            } else {
1039                keepAliveData.userNotified = false;
1040            }
1041        }
1042    }
1043
1044    function getAjaxUrl(connection, path) {
1045        var url = connection.url + path;
1046
1047        if (connection.transport) {
1048            url += "?transport=" + connection.transport.name;
1049        }
1050
1051        return transportLogic.prepareQueryString(connection, url);
1052    }
1053
1054    function InitHandler(connection) {
1055        this.connection = connection;
1056
1057        this.startRequested = false;
1058        this.startCompleted = false;
1059        this.connectionStopped = false;
1060    }
1061
1062    InitHandler.prototype = {
1063        start: function (transport, onSuccess, onFallback) {
1064            var that = this,
1065                connection = that.connection,
1066                failCalled = false;
1067
1068            if (that.startRequested || that.connectionStopped) {
1069                connection.log("WARNING! " + transport.name + " transport cannot be started. Initialization ongoing or completed.");
1070                return;
1071            }
1072
1073            connection.log(transport.name + " transport starting.");
1074
1075            transport.start(connection, function () {
1076                if (!failCalled) {
1077                    that.initReceived(transport, onSuccess);
1078                }
1079            }, function (error) {
1080                // Don't allow the same transport to cause onFallback to be called twice
1081                if (!failCalled) {
1082                    failCalled = true;
1083                    that.transportFailed(transport, error, onFallback);
1084                }
1085
1086                // Returns true if the transport should stop;
1087                // false if it should attempt to reconnect
1088                return !that.startCompleted || that.connectionStopped;
1089            });
1090
1091            that.transportTimeoutHandle = window.setTimeout(function () {
1092                if (!failCalled) {
1093                    failCalled = true;
1094                    connection.log(transport.name + " transport timed out when trying to connect.");
1095                    that.transportFailed(transport, undefined, onFallback);
1096                }
1097            }, connection._.totalTransportConnectTimeout);
1098        },
1099
1100        stop: function () {
1101            this.connectionStopped = true;
1102            window.clearTimeout(this.transportTimeoutHandle);
1103            signalR.transports._logic.tryAbortStartRequest(this.connection);
1104        },
1105
1106        initReceived: function (transport, onSuccess) {
1107            var that = this,
1108                connection = that.connection;
1109
1110            if (that.startRequested) {
1111                connection.log("WARNING! The client received multiple init messages.");
1112                return;
1113            }
1114
1115            if (that.connectionStopped) {
1116                return;
1117            }
1118
1119            that.startRequested = true;
1120            window.clearTimeout(that.transportTimeoutHandle);
1121
1122            connection.log(transport.name + " transport connected. Initiating start request.");
1123            signalR.transports._logic.ajaxStart(connection, function () {
1124                that.startCompleted = true;
1125                onSuccess();
1126            });
1127        },
1128
1129        transportFailed: function (transport, error, onFallback) {
1130            var connection = this.connection,
1131                deferred = connection._deferral,
1132                wrappedError;
1133
1134            if (this.connectionStopped) {
1135                return;
1136            }
1137
1138            window.clearTimeout(this.transportTimeoutHandle);
1139
1140            if (!this.startRequested) {
1141                transport.stop(connection);
1142
1143                connection.log(transport.name + " transport failed to connect. Attempting to fall back.");
1144                onFallback();
1145            } else if (!this.startCompleted) {
1146                // Do not attempt to fall back if a start request is ongoing during a transport failure.
1147                // Instead, trigger an error and stop the connection.
1148                wrappedError = signalR._.error(signalR.resources.errorDuringStartRequest, error);
1149
1150                connection.log(transport.name + " transport failed during the start request. Stopping the connection.");
1151                $(connection).triggerHandler(events.onError, [wrappedError]);
1152                if (deferred) {
1153                    deferred.reject(wrappedError);
1154                }
1155
1156                connection.stop();
1157            } else {
1158                // The start request has completed, but the connection has not stopped.
1159                // No need to do anything here. The transport should attempt its normal reconnect logic.
1160            }
1161        }
1162    };
1163
1164    transportLogic = signalR.transports._logic = {
1165        ajax: function (connection, options) {
1166            return $.ajax(
1167                $.extend(/*deep copy*/ true, {}, $.signalR.ajaxDefaults, {
1168                    type: "GET",
1169                    data: {},
1170                    xhrFields: { withCredentials: connection.withCredentials },
1171                    contentType: connection.contentType,
1172                    dataType: connection.ajaxDataType
1173                }, options));
1174        },
1175
1176        pingServer: function (connection) {
1177            /// <summary>Pings the server</summary>
1178            /// <param name="connection" type="signalr">Connection associated with the server ping</param>
1179            /// <returns type="signalR" />
1180            var url,
1181                xhr,
1182                deferral = $.Deferred();
1183
1184            if (connection.transport) {
1185                url = connection.url + "/ping";
1186
1187                url = transportLogic.addQs(url, connection.qs);
1188
1189                xhr = transportLogic.ajax(connection, {
1190                    url: url,
1191                    
1191success: function (result) {
1192                        var data;
1193
1194                        try {
1195                            data = connection._parseResponse(result);
1196                        }
1197                        catch (error) {
1198                            deferral.reject(
1199                                signalR._.transportError(
1200                                    signalR.resources.pingServerFailedParse,
1201                                    connection.transport,
1202                                    error,
1203                                    xhr
1204                                )
1205                            );
1206                            connection.stop();
1207                            return;
1208                        }
1209
1210                        if (data.Response === "pong") {
1211                            deferral.resolve();
1212                        }
1213                        else {
1214                            deferral.reject(
1215                                signalR._.transportError(
1216                                    signalR._.format(signalR.resources.pingServerFailedInvalidResponse, result),
1217                                    connection.transport,
1218                                    null /* error */,
1219                                    xhr
1220                                )
1221                            );
1222                        }
1223                    },
1224                    error: function (error) {
1225                        if (error.status === 401 || error.status === 403) {
1226                            deferral.reject(
1227                                signalR._.transportError(
1228                                    signalR._.format(signalR.resources.pingServerFailedStatusCode, error.status),
1229                                    connection.transport,
1230                                    error,
1231                                    xhr
1232                                )
1233                            );
1234                            connection.stop();
1235                        }
1236                        else {
1237                            deferral.reject(
1238                                signalR._.transportError(
1239                                    signalR.resources.pingServerFailed,
1240                                    connection.transport,
vendor: 15,235 bytes, lines 1241-1622
1241                                    error,
1242                                    xhr
1243                                )
1244                            );
1245                        }
1246                    }
1247                });
1248            }
1249            else {
1250                deferral.reject(
1251                    signalR._.transportError(
1252                        signalR.resources.noConnectionTransport,
1253                        connection.transport
1254                    )
1255                );
1256            }
1257
1258            return deferral.promise();
1259        },
1260
1261        prepareQueryString: function (connection, url) {
1262            var preparedUrl;
1263
1264            // Use addQs to start since it handles the ?/& prefix for us
1265            preparedUrl = transportLogic.addQs(url, "clientProtocol=" + connection.clientProtocol);
1266
1267            // Add the user-specified query string params if any
1268            preparedUrl = transportLogic.addQs(preparedUrl, connection.qs);
1269
1270            if (connection.token) {
1271                preparedUrl += "&connectionToken=" + window.encodeURIComponent(connection.token);
1272            }
1273
1274            if (connection.data) {
1275                preparedUrl += "&connectionData=" + window.encodeURIComponent(connection.data);
1276            }
1277
1278            return preparedUrl;
1279        },
1280
1281        addQs: function (url, qs) {
1282            var appender = url.indexOf("?") !== -1 ? "&" : "?",
1283                firstChar;
1284
1285            if (!qs) {
1286                return url;
1287            }
1288
1289            if (typeof (qs) === "object") {
1290                return url + appender + $.param(qs);
1291            }
1292
1293            if (typeof (qs) === "string") {
1294                firstChar = qs.charAt(0);
1295
1296                if (firstChar === "?" || firstChar === "&") {
1297                    appender = "";
1298                }
1299
1300                return url + appender + qs;
1301            }
1302
1303            throw new Error("Query string property must be either a string or object.");
1304        },
1305
1306        // BUG #2953: The url needs to be same otherwise it will cause a memory leak
1307        getUrl: function (connection, transport, reconnecting, poll, ajaxPost) {
1308            /// <summary>Gets the url for making a GET based connect request</summary>
1309            var baseUrl = transport === "webSockets" ? "" : connection.baseUrl,
1310                url = baseUrl + connection.appRelativeUrl,
1311                qs = "transport=" + transport;
1312
1313            if (!ajaxPost && connection.groupsToken) {
1314                qs += "&groupsToken=" + window.encodeURIComponent(connection.groupsToken);
1315            }
1316
1317            if (!reconnecting) {
1318                url += "/connect";
1319            } else {
1320                if (poll) {
1321                    // longPolling transport specific
1322                    url += "/poll";
1323                } else {
1324                    url += "/reconnect";
1325                }
1326
1327                if (!ajaxPost && connection.messageId) {
1328                    qs += "&messageId=" + window.encodeURIComponent(connection.messageId);
1329                }
1330            }
1331            url += "?" + qs;
1332            url = transportLogic.prepareQueryString(connection, url);
1333
1334            if (!ajaxPost) {
1335                url += "&tid=" + Math.floor(Math.random() * 11);
1336            }
1337
1338            return url;
1339        },
1340
1341        maximizePersistentResponse: function (minPersistentResponse) {
1342            return {
1343                MessageId: minPersistentResponse.C,
1344                Messages: minPersistentResponse.M,
1345                Initialized: typeof (minPersistentResponse.S) !== "undefined" ? true : false,
1346                ShouldReconnect: typeof (minPersistentResponse.T) !== "undefined" ? true : false,
1347                LongPollDelay: minPersistentResponse.L,
1348                GroupsToken: minPersistentResponse.G
1349            };
1350        },
1351
1352        updateGroups: function (connection, groupsToken) {
1353            if (groupsToken) {
1354                connection.groupsToken = groupsToken;
1355            }
1356        },
1357
1358        stringifySend: function (connection, message) {
1359            if (typeof (message) === "string" || typeof (message) === "undefined" || message === null) {
1360                return message;
1361            }
1362            return connection.json.stringify(message);
1363        },
1364
1365        ajaxSend: function (connection, data) {
1366            var payload = transportLogic.stringifySend(connection, data),
1367                url = getAjaxUrl(connection, "/send"),
1368                xhr,
1369                onFail = function (error, connection) {
1370                    $(connection).triggerHandler(events.onError, [signalR._.transportError(signalR.resources.sendFailed, connection.transport, error, xhr), data]);
1371                };
1372
1373
1374            xhr = transportLogic.ajax(connection, {
1375                url: url,
1376                type: connection.ajaxDataType === "jsonp" ? "GET" : "POST",
1377                contentType: signalR._.defaultContentType,
1378                data: {
1379                    data: payload
1380                },
1381                success: function (result) {
1382                    var res;
1383
1384                    if (result) {
1385                        try {
1386                            res = connection._parseResponse(result);
1387                        }
1388                        catch (error) {
1389                            onFail(error, connection);
1390                            connection.stop();
1391                            return;
1392                        }
1393
1394                        transportLogic.triggerReceived(connection, res);
1395                    }
1396                },
1397                error: function (error, textStatus) {
1398                    if (textStatus === "abort" || textStatus === "parsererror") {
1399                        // The parsererror happens for sends that don't return any data, and hence
1400                        // don't write the jsonp callback to the response. This is harder to fix on the server
1401                        // so just hack around it on the client for now.
1402                        return;
1403                    }
1404
1405                    onFail(error, connection);
1406                }
1407            });
1408
1409            return xhr;
1410        },
1411
1412        ajaxAbort: function (connection, async) {
1413            if (typeof (connection.transport) === "undefined") {
1414                return;
1415            }
1416
1417            // Async by default unless explicitly overidden
1418            async = typeof async === "undefined" ? true : async;
1419
1420            var url = getAjaxUrl(connection, "/abort");
1421
1422            transportLogic.ajax(connection, {
1423                url: url,
1424                async: async,
1425                timeout: 1000,
1426                type: "POST"
1427            });
1428
1429            connection.log("Fired ajax abort async = " + async + ".");
1430        },
1431
1432        ajaxStart: function (connection, onSuccess) {
1433            var rejectDeferred = function (error) {
1434                    var deferred = connection._deferral;
1435                    if (deferred) {
1436                        deferred.reject(error);
1437                    }
1438                },
1439                triggerStartError = function (error) {
1440                    connection.log("The start request failed. Stopping the connection.");
1441                    $(connection).triggerHandler(events.onError, [error]);
1442                    rejectDeferred(error);
1443                    connection.stop();
1444                };
1445
1446            connection._.startRequest = transportLogic.ajax(connection, {
1447                url: getAjaxUrl(connection, "/start"),
1448                success: function (result, statusText, xhr) {
1449                    var data;
1450
1451                    try {
1452                        data = connection._parseResponse(result);
1453                    } catch (error) {
1454                        triggerStartError(signalR._.error(
1455                            signalR._.format(signalR.resources.errorParsingStartResponse, result),
1456                            error, xhr));
1457                        return;
1458                    }
1459
1460                    if (data.Response === "started") {
1461                        onSuccess();
1462                    } else {
1463                        triggerStartError(signalR._.error(
1464                            signalR._.format(signalR.resources.invalidStartResponse, result),
1465                            null /* error */, xhr));
1466                    }
1467                },
1468                error: function (xhr, statusText, error) {
1469                    if (statusText !== startAbortText) {
1470                        triggerStartError(signalR._.error(
1471                            signalR.resources.errorDuringStartRequest,
1472                            error, xhr));
1473                    } else {
1474                        // Stop has been called, no need to trigger the error handler
1475                        // or stop the connection again with onStartError
1476                        connection.log("The start request aborted because connection.stop() was called.");
1477                        rejectDeferred(signalR._.error(
1478                            signalR.resources.stoppedDuringStartRequest,
1479                            null /* error */, xhr));
1480                    }
1481                }
1482            });
1483        },
1484
1485        tryAbortStartRequest: function (connection) {
1486            if (connection._.startRequest) {
1487                // If the start request has already completed this will noop.
1488                connection._.startRequest.abort(startAbortText);
1489                delete connection._.startRequest;
1490            }
1491        },
1492
1493        tryInitialize: function (connection, persistentResponse, onInitialized) {
1494            if (persistentResponse.Initialized && onInitialized) {
1495                onInitialized();
1496            } else if (persistentResponse.Initialized) {
1497                connection.log("WARNING! The client received an init message after reconnecting.");
1498            }
1499
1500        },
1501
1502        triggerReceived: function (connection, data) {
1503            if (!connection._.connectingMessageBuffer.tryBuffer(data)) {
1504                $(connection).triggerHandler(events.onReceived, [data]);
1505            }
1506        },
1507
1508        processMessages: function (connection, minData, onInitialized) {
1509            var data;
1510
1511            // Update the last message time stamp
1512            transportLogic.markLastMessage(connection);
1513
1514            if (minData) {
1515                data = transportLogic.maximizePersistentResponse(minData);
1516
1517                transportLogic.updateGroups(connection, data.GroupsToken);
1518
1519                if (data.MessageId) {
1520                    connection.messageId = data.MessageId;
1521                }
1522
1523                if (data.Messages) {
1524                    $.each(data.Messages, function (index, message) {
1525                        transportLogic.triggerReceived(connection, message);
1526                    });
1527
1528                    transportLogic.tryInitialize(connection, data, onInitialized);
1529                }
1530            }
1531        },
1532
1533        monitorKeepAlive: function (connection) {
1534            var keepAliveData = connection._.keepAliveData;
1535
1536            // If we haven't initiated the keep alive timeouts then we need to
1537            if (!keepAliveData.monitoring) {
1538                keepAliveData.monitoring = true;
1539
1540                transportLogic.markLastMessage(connection);
1541
1542                // Save the function so we can unbind it on stop
1543                connection._.keepAliveData.reconnectKeepAliveUpdate = function () {
1544                    // Mark a new message so that keep alive doesn't time out connections
1545                    transportLogic.markLastMessage(connection);
1546                };
1547
1548                // Update Keep alive on reconnect
1549                $(connection).bind(events.onReconnect, connection._.keepAliveData.reconnectKeepAliveUpdate);
1550
1551                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);
1552            } else {
1553                connection.log("Tried to monitor keep alive but it's already being monitored.");
1554            }
1555        },
1556
1557        stopMonitoringKeepAlive: function (connection) {
1558            var keepAliveData = connection._.keepAliveData;
1559
1560            // Only attempt to stop the keep alive monitoring if its being monitored
1561            if (keepAliveData.monitoring) {
1562                // Stop monitoring
1563                keepAliveData.monitoring = false;
1564
1565                // Remove the updateKeepAlive function from the reconnect event
1566                $(connection).unbind(events.onReconnect, connection._.keepAliveData.reconnectKeepAliveUpdate);
1567
1568                // Clear all the keep alive data
1569                connection._.keepAliveData = {};
1570                connection.log("Stopping the monitoring of the keep alive.");
1571            }
1572        },
1573
1574        startHeartbeat: function (connection) {
1575            connection._.lastActiveAt = new Date().getTime();
1576            beat(connection);
1577        },
1578
1579        markLastMessage: function (connection) {
1580            connection._.lastMessageAt = new Date().getTime();
1581        },
1582
1583        markActive: function (connection) {
1584            if (transportLogic.verifyLastActive(connection)) {
1585                connection._.lastActiveAt = new Date().getTime();
1586                return true;
1587            }
1588
1589            return false;
1590        },
1591
1592        isConnectedOrReconnecting: function (connection) {
1593            return connection.state === signalR.connectionState.connected ||
1594                   connection.state === signalR.connectionState.reconnecting;
1595        },
1596
1597        ensureReconnectingState: function (connection) {
1598            if (changeState(connection,
1599                        signalR.connectionState.connected,
1600                        signalR.connectionState.reconnecting) === true) {
1601                $(connection).triggerHandler(events.onReconnecting);
1602            }
1603            return connection.state === signalR.connectionState.reconnecting;
1604        },
1605
1606        clearReconnectTimeout: function (connection) {
1607            if (connection && connection._.reconnectTimeout) {
1608                window.clearTimeout(connection._.reconnectTimeout);
1609                delete connection._.reconnectTimeout;
1610            }
1611        },
1612
1613        verifyLastActive: function (connection) {
1614            if (new Date().getTime() - connection._.lastActiveAt >= connection.reconnectWindow) {
1615                var message = signalR._.format(signalR.resources.reconnectWindowTimeout, new Date(connection._.lastActiveAt), connection.reconnectWindow);
1616                connection.log(message);
1617                $(connection).triggerHandler(events.onError, [signalR._.error(message, /* source */ "TimeoutException")]);
1618                connection.stop(/* async */ false, /* notifyServer */ false);
1619                return false;
1620            }
1621
1622            return tru
vendor: 6,932 bytes, lines 1622-1797
1622e;
1623        },
1624
1625        reconnect: function (connection, transportName) {
1626            var transport = signalR.transports[transportName];
1627
1628            // We should only set a reconnectTimeout if we are currently connected
1629            // and a reconnectTimeout isn't already set.
1630            if (transportLogic.isConnectedOrReconnecting(connection) && !connection._.reconnectTimeout) {
1631                // Need to verify before the setTimeout occurs because an application sleep could occur during the setTimeout duration.
1632                if (!transportLogic.verifyLastActive(connection)) {
1633                    return;
1634                }
1635
1636                connection._.reconnectTimeout = window.setTimeout(function () {
1637                    if (!transportLogic.verifyLastActive(connection)) {
1638                        return;
1639                    }
1640
1641                    transport.stop(connection);
1642
1643                    if (transportLogic.ensureReconnectingState(connection)) {
1644                        connection.log(transportName + " reconnecting.");
1645                        transport.start(connection);
1646                    }
1647                }, connection.reconnectDelay);
1648            }
1649        },
1650
1651        handleParseFailure: function (connection, result, error, onFailed, context) {
1652            var wrappedError = signalR._.transportError(
1653                signalR._.format(signalR.resources.parseFailed, result),
1654                connection.transport,
1655                error,
1656                context);
1657
1658            // If we're in the initialization phase trigger onFailed, otherwise stop the connection.
1659            if (onFailed && onFailed(wrappedError)) {
1660                connection.log("Failed to parse server response while attempting to connect.");
1661            } else {
1662                $(connection).triggerHandler(events.onError, [wrappedError]);
1663                connection.stop();
1664            }
1665        },
1666
1667        initHandler: function (connection) {
1668            return new InitHandler(connection);
1669        },
1670
1671        foreverFrame: {
1672            count: 0,
1673            connections: {}
1674        }
1675    };
1676
1677}(window.jQuery, window));
1678/* jquery.signalR.transports.webSockets.js */
1679// Copyright (c) .NET Foundation. All rights reserved.
1680// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
1681
1682
1683/*global window:false */
1684/// <reference path="jquery.signalR.transports.common.js" />
1685
1686(function ($, window, undefined) {
1687
1688    var signalR = $.signalR,
1689        events = $.signalR.events,
1690        changeState = $.signalR.changeState,
1691        transportLogic = signalR.transports._logic;
1692
1693    signalR.transports.webSockets = {
1694        name: "webSockets",
1695
1696        supportsKeepAlive: function () {
1697            return true;
1698        },
1699
1700        send: function (connection, data) {
1701            var payload = transportLogic.stringifySend(connection, data);
1702
1703            try {
1704                connection.socket.send(payload);
1705            } catch (ex) {
1706                $(connection).triggerHandler(events.onError,
1707                    [signalR._.transportError(
1708                        signalR.resources.webSocketsInvalidState,
1709                        connection.transport,
1710                        ex,
1711                        connection.socket
1712                    ),
1713                    data]);
1714            }
1715        },
1716
1717        start: function (connection, onSuccess, onFailed) {
1718            var url,
1719                opened = false,
1720                that = this,
1721                reconnecting = !onSuccess,
1722                $connection = $(connection);
1723
1724            if (!window.WebSocket) {
1725                onFailed();
1726                return;
1727            }
1728
1729            if (!connection.socket) {
1730                if (connection.webSocketServerUrl) {
1731                    url = connection.webSocketServerUrl;
1732                } else {
1733                    url = connection.wsProtocol + connection.host;
1734                }
1735
1736                url += transportLogic.getUrl(connection, this.name, reconnecting);
1737
1738                connection.log("Connecting to websocket endpoint '" + url + "'.");
1739                connection.socket = new window.WebSocket(url);
1740
1741                connection.socket.onopen = function () {
1742                    opened = true;
1743                    connection.log("Websocket opened.");
1744
1745                    transportLogic.clearReconnectTimeout(connection);
1746
1747                    if (changeState(connection,
1748                                    signalR.connectionState.reconnecting,
1749                                    signalR.connectionState.connected) === true) {
1750                        $connection.triggerHandler(events.onReconnect);
1751                    }
1752                };
1753
1754                connection.socket.onclose = function (event) {
1755                    var error;
1756
1757                    // Only handle a socket close if the close is from the current socket.
1758                    // Sometimes on disconnect the server will push down an onclose event
1759                    // to an expired socket.
1760
1761                    if (this === connection.socket) {
1762                        if (opened && typeof event.wasClean !== "undefined" && event.wasClean === false) {
1763                            // Ideally this would use the websocket.onerror handler (rather than checking wasClean in onclose) but
1764                            // I found in some circumstances Chrome won't call onerror. This implementation seems to work on all browsers.
1765                            error = signalR._.transportError(
1766                                signalR.resources.webSocketClosed,
1767                                connection.transport,
1768                                event);
1769
1770                            connection.log("Unclean disconnect from websocket: " + (event.reason || "[no reason given]."));
1771                        } else {
1772                            connection.log("Websocket closed.");
1773                        }
1774
1775                        if (!onFailed || !onFailed(error)) {
1776                            if (error) {
1777                                $(connection).triggerHandler(events.onError, [error]);
1778                            }
1779
1780                            that.reconnect(connection);
1781                        }
1782                    }
1783                };
1784
1785                connection.socket.onmessage = function (event) {
1786                    var data;
1787
1788                    try {
1789                        data = connection._parseResponse(event.data);
1790                    }
1791                    catch (error) {
1792                        transportLogic.handleParseFailure(connection, event.data, error, onFailed, event);
1793                        return;
1794                    }
1795
1796                    if (data) {
1797                        
1797// data.M is PersistentResponse.Messages
1798                        if ($.isEmptyObject(data) || data.M) {
1799                            transportLogic.processMessages(connection, data, onSuccess);
1800                        } else {
1801                            // For websockets we need to trigger onReceived
1802                            // for callbacks to outgoing hub calls.
1803                            transportLogic.triggerReceived(connection, data);
1804                        }
vendor: 11,128 bytes, lines 1804-2090
1804
1805                    }
1806                };
1807            }
1808        },
1809
1810        reconnect: function (connection) {
1811            transportLogic.reconnect(connection, this.name);
1812        },
1813
1814        lostConnection: function (connection) {
1815            this.reconnect(connection);
1816        },
1817
1818        stop: function (connection) {
1819            // Don't trigger a reconnect after stopping
1820            transportLogic.clearReconnectTimeout(connection);
1821
1822            if (connection.socket) {
1823                connection.log("Closing the Websocket.");
1824                connection.socket.close();
1825                connection.socket = null;
1826            }
1827        },
1828
1829        abort: function (connection, async) {
1830            transportLogic.ajaxAbort(connection, async);
1831        }
1832    };
1833
1834}(window.jQuery, window));
1835/* jquery.signalR.transports.serverSentEvents.js */
1836// Copyright (c) .NET Foundation. All rights reserved.
1837// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
1838
1839
1840/*global window:false */
1841/// <reference path="jquery.signalR.transports.common.js" />
1842
1843(function ($, window, undefined) {
1844
1845    var signalR = $.signalR,
1846        events = $.signalR.events,
1847        changeState = $.signalR.changeState,
1848        transportLogic = signalR.transports._logic,
1849        clearReconnectAttemptTimeout = function (connection) {
1850            window.clearTimeout(connection._.reconnectAttemptTimeoutHandle);
1851            delete connection._.reconnectAttemptTimeoutHandle;
1852        };
1853
1854    signalR.transports.serverSentEvents = {
1855        name: "serverSentEvents",
1856
1857        supportsKeepAlive: function () {
1858            return true;
1859        },
1860
1861        timeOut: 3000,
1862
1863        start: function (connection, onSuccess, onFailed) {
1864            var that = this,
1865                opened = false,
1866                $connection = $(connection),
1867                reconnecting = !onSuccess,
1868                url;
1869
1870            if (connection.eventSource) {
1871                connection.log("The connection already has an event source. Stopping it.");
1872                connection.stop();
1873            }
1874
1875            if (!window.EventSource) {
1876                if (onFailed) {
1877                    connection.log("This browser doesn't support SSE.");
1878                    onFailed();
1879                }
1880                return;
1881            }
1882
1883            url = transportLogic.getUrl(connection, this.name, reconnecting);
1884
1885            try {
1886                connection.log("Attempting to connect to SSE endpoint '" + url + "'.");
1887                connection.eventSource = new window.EventSource(url, { withCredentials: connection.withCredentials });
1888            }
1889            catch (e) {
1890                connection.log("EventSource failed trying to connect with error " + e.Message + ".");
1891                if (onFailed) {
1892                    // The connection failed, call the failed callback
1893                    onFailed();
1894                } else {
1895                    $connection.triggerHandler(events.onError, [signalR._.transportError(signalR.resources.eventSourceFailedToConnect, connection.transport, e)]);
1896                    if (reconnecting) {
1897                        // If we were reconnecting, rather than doing initial connect, then try reconnect again
1898                        that.reconnect(connection);
1899                    }
1900                }
1901                return;
1902            }
1903
1904            if (reconnecting) {
1905                connection._.reconnectAttemptTimeoutHandle = window.setTimeout(function () {
1906                    if (opened === false) {
1907                        // If we're reconnecting and the event source is attempting to connect,
1908                        // don't keep retrying. This causes duplicate connections to spawn.
1909                        if (connection.eventSource.readyState !== window.EventSource.OPEN) {
1910                            // If we were reconnecting, rather than doing initial connect, then try reconnect again
1911                            that.reconnect(connection);
1912                        }
1913                    }
1914                },
1915                that.timeOut);
1916            }
1917
1918            connection.eventSource.addEventListener("open", function (e) {
1919                connection.log("EventSource connected.");
1920
1921                clearReconnectAttemptTimeout(connection);
1922                transportLogic.clearReconnectTimeout(connection);
1923
1924                if (opened === false) {
1925                    opened = true;
1926
1927                    if (changeState(connection,
1928                                         signalR.connectionState.reconnecting,
1929                                         signalR.connectionState.connected) === true) {
1930                        $connection.triggerHandler(events.onReconnect);
1931                    }
1932                }
1933            }, false);
1934
1935            connection.eventSource.addEventListener("message", function (e) {
1936                var res;
1937
1938                // process messages
1939                if (e.data === "initialized") {
1940                    return;
1941                }
1942
1943                try {
1944                    res = connection._parseResponse(e.data);
1945                }
1946                catch (error) {
1947                    transportLogic.handleParseFailure(connection, e.data, error, onFailed, e);
1948                    return;
1949                }
1950
1951                transportLogic.processMessages(connection, res, onSuccess);
1952            }, false);
1953
1954            connection.eventSource.addEventListener("error", function (e) {
1955                var error = signalR._.transportError(
1956                    signalR.resources.eventSourceError,
1957                    connection.transport,
1958                    e);
1959
1960                // Only handle an error if the error is from the current Event Source.
1961                // Sometimes on disconnect the server will push down an error event
1962                // to an expired Event Source.
1963                if (this !== connection.eventSource) {
1964                    return;
1965                }
1966
1967                if (onFailed && onFailed(error)) {
1968                    return;
1969                }
1970
1971                connection.log("EventSource readyState: " + connection.eventSource.readyState + ".");
1972
1973                if (e.eventPhase === window.EventSource.CLOSED) {
1974                    // We don't use the EventSource's native reconnect function as it
1975                    // doesn't allow us to change the URL when reconnecting. We need
1976                    // to change the URL to not include the /connect suffix, and pass
1977                    // the last message id we received.
1978                    connection.log("EventSource reconnecting due to the server connection ending.");
1979                    that.reconnect(connection);
1980                } else {
1981                    // connection error
1982                    connection.log("EventSource error.");
1983                    $connection.triggerHandler(events.onError, [error]);
1984                }
1985            }, false);
1986        },
1987
1988        reconnect: function (connection) {
1989            transportLogic.reconnect(connection, this.name);
1990        },
1991
1992        lostConnection: function (connection) {
1993            this.reconnect(connection);
1994        },
1995
1996        send: function (connection, data) {
1997            transportLogic.ajaxSend(connection, data);
1998        },
1999
2000        stop: function (connection) {
2001            // Don't trigger a reconnect after stopping
2002            clearReconnectAttemptTimeout(connection);
2003            transportLogic.clearReconnectTimeout(connection);
2004
2005            if (connection && connection.eventSource) {
2006                connection.log("EventSource calling close().");
2007                connection.eventSource.close();
2008                connection.eventSource = null;
2009                delete connection.eventSource;
2010            }
2011        },
2012
2013        abort: function (connection, async) {
2014            transportLogic.ajaxAbort(connection, async);
2015        }
2016    };
2017
2018}(window.jQuery, window));
2019/* jquery.signalR.transports.foreverFrame.js */
2020// Copyright (c) .NET Foundation. All rights reserved.
2021// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
2022
2023
2024/*global window:false */
2025/// <reference path="jquery.signalR.transports.common.js" />
2026
2027(function ($, window, undefined) {
2028
2029    var signalR = $.signalR,
2030        events = $.signalR.events,
2031        changeState = $.signalR.changeState,
2032        transportLogic = signalR.transports._logic,
2033        createFrame = function () {
2034            var frame = window.document.createElement("iframe");
2035            frame.setAttribute("style", "position:absolute;top:0;left:0;width:0;height:0;visibility:hidden;");
2036            return frame;
2037        },
2038        // Used to prevent infinite loading icon spins in older versions of ie
2039        // We build this object inside a closure so we don't pollute the rest of
2040        // the foreverFrame transport with unnecessary functions/utilities.
2041        loadPreventer = (function () {
2042            var loadingFixIntervalId = null,
2043                loadingFixInterval = 1000,
2044                attachedTo = 0;
2045
2046            return {
2047                prevent: function () {
2048                    // Prevent additional iframe removal procedures from newer browsers
2049                    if (signalR._.ieVersion <= 8) {
2050                        // We only ever want to set the interval one time, so on the first attachedTo
2051                        if (attachedTo === 0) {
2052                            // Create and destroy iframe every 3 seconds to prevent loading icon, super hacky
2053                            loadingFixIntervalId = window.setInterval(function () {
2054                                var tempFrame = createFrame();
2055
2056                                window.document.body.appendChild(tempFrame);
2057                                window.document.body.removeChild(tempFrame);
2058
2059                                tempFrame = null;
2060                            }, loadingFixInterval);
2061                        }
2062
2063                        attachedTo++;
2064                    }
2065                },
2066                cancel: function () {
2067                    // Only clear the interval if there's only one more object that the loadPreventer is attachedTo
2068                    if (attachedTo === 1) {
2069                        window.clearInterval(loadingFixIntervalId);
2070                    }
2071
2072                    if (attachedTo > 0) {
2073                        attachedTo--;
2074                    }
2075                }
2076            };
2077        })();
2078
2079    signalR.transports.foreverFrame = {
2080        name: "foreverFrame",
2081
2082        supportsKeepAlive: function () {
2083            return true;
2084        },
2085
2086        // Added as a value here so we can create tests to verify functionality
2087        iframeClearThreshold: 50,
2088
2089        start: function (connection, onSuccess, onFailed) {
2090            
vendor: 11,868 bytes, lines 2090-2374
2090var that = this,
2091                frameId = (transportLogic.foreverFrame.count += 1),
2092                url,
2093                frame = createFrame(),
2094                frameLoadHandler = function () {
2095                    connection.log("Forever frame iframe finished loading and is no longer receiving messages.");
2096                    if (!onFailed || !onFailed()) {
2097                        that.reconnect(connection);
2098                    }
2099                };
2100
2101            if (window.EventSource) {
2102                // If the browser supports SSE, don't use Forever Frame
2103                if (onFailed) {
2104                    connection.log("Forever Frame is not supported by SignalR on browsers with SSE support.");
2105                    onFailed();
2106                }
2107                return;
2108            }
2109
2110            frame.setAttribute("data-signalr-connection-id", connection.id);
2111
2112            // Start preventing loading icon
2113            // This will only perform work if the loadPreventer is not attached to another connection.
2114            loadPreventer.prevent();
2115
2116            // Build the url
2117            url = transportLogic.getUrl(connection, this.name);
2118            url += "&frameId=" + frameId;
2119
2120            // add frame to the document prior to setting URL to avoid caching issues.
2121            window.document.documentElement.appendChild(frame);
2122
2123            connection.log("Binding to iframe's load event.");
2124
2125            if (frame.addEventListener) {
2126                frame.addEventListener("load", frameLoadHandler, false);
2127            } else if (frame.attachEvent) {
2128                frame.attachEvent("onload", frameLoadHandler);
2129            }
2130
2131            frame.src = url;
2132            transportLogic.foreverFrame.connections[frameId] = connection;
2133
2134            connection.frame = frame;
2135            connection.frameId = frameId;
2136
2137            if (onSuccess) {
2138                connection.onSuccess = function () {
2139                    connection.log("Iframe transport started.");
2140                    onSuccess();
2141                };
2142            }
2143        },
2144
2145        reconnect: function (connection) {
2146            var that = this;
2147
2148            // Need to verify connection state and verify before the setTimeout occurs because an application sleep could occur during the setTimeout duration.
2149            if (transportLogic.isConnectedOrReconnecting(connection) && transportLogic.verifyLastActive(connection)) {
2150                window.setTimeout(function () {
2151                    // Verify that we're ok to reconnect.
2152                    if (!transportLogic.verifyLastActive(connection)) {
2153                        return;
2154                    }
2155
2156                    if (connection.frame && transportLogic.ensureReconnectingState(connection)) {
2157                        var frame = connection.frame,
2158                            src = transportLogic.getUrl(connection, that.name, true) + "&frameId=" + connection.frameId;
2159                        connection.log("Updating iframe src to '" + src + "'.");
2160                        frame.src = src;
2161                    }
2162                }, connection.reconnectDelay);
2163            }
2164        },
2165
2166        lostConnection: function (connection) {
2167            this.reconnect(connection);
2168        },
2169
2170        send: function (connection, data) {
2171            transportLogic.ajaxSend(connection, data);
2172        },
2173
2174        receive: function (connection, data) {
2175            var cw,
2176                body,
2177                response;
2178
2179            if (connection.json !== connection._originalJson) {
2180                // If there's a custom JSON parser configured then serialize the object
2181                // using the original (browser) JSON parser and then deserialize it using
2182                // the custom parser (connection._parseResponse does that). This is so we
2183                // can easily send the response from the server as "raw" JSON but still
2184                // support custom JSON deserialization in the browser.
2185                data = connection._originalJson.stringify(data);
2186            }
2187
2188            response = connection._parseResponse(data);
2189
2190            transportLogic.processMessages(connection, response, connection.onSuccess);
2191
2192            // Protect against connection stopping from a callback trigger within the processMessages above.
2193            if (connection.state === $.signalR.connectionState.connected) {
2194                // Delete the script & div elements
2195                connection.frameMessageCount = (connection.frameMessageCount || 0) + 1;
2196                if (connection.frameMessageCount > signalR.transports.foreverFrame.iframeClearThreshold) {
2197                    connection.frameMessageCount = 0;
2198                    cw = connection.frame.contentWindow || connection.frame.contentDocument;
2199                    if (cw && cw.document && cw.document.body) {
2200                        body = cw.document.body;
2201
2202                        // Remove all the child elements from the iframe's body to conserver memory
2203                        while (body.firstChild) {
2204                            body.removeChild(body.firstChild);
2205                        }
2206                    }
2207                }
2208            }
2209        },
2210
2211        stop: function (connection) {
2212            var cw = null;
2213
2214            // Stop attempting to prevent loading icon
2215            loadPreventer.cancel();
2216
2217            if (connection.frame) {
2218                if (connection.frame.stop) {
2219                    connection.frame.stop();
2220                } else {
2221                    try {
2222                        cw = connection.frame.contentWindow || connection.frame.contentDocument;
2223                        if (cw.document && cw.document.execCommand) {
2224                            cw.document.execCommand("Stop");
2225                        }
2226                    }
2227                    catch (e) {
2228                        connection.log("Error occurred when stopping foreverFrame transport. Message = " + e.message + ".");
2229                    }
2230                }
2231
2232                // Ensure the iframe is where we left it
2233                if (connection.frame.parentNode === window.document.documentElement) {
2234                    window.document.documentElement.removeChild(connection.frame);
2235                }
2236
2237                delete transportLogic.foreverFrame.connections[connection.frameId];
2238                connection.frame = null;
2239                connection.frameId = null;
2240                delete connection.frame;
2241                delete connection.frameId;
2242                delete connection.onSuccess;
2243                delete connection.frameMessageCount;
2244                connection.log("Stopping forever frame.");
2245            }
2246        },
2247
2248        abort: function (connection, async) {
2249            transportLogic.ajaxAbort(connection, async);
2250        },
2251
2252        getConnection: function (id) {
2253            return transportLogic.foreverFrame.connections[id];
2254        },
2255
2256        started: function (connection) {
2257            if (changeState(connection,
2258                signalR.connectionState.reconnecting,
2259                signalR.connectionState.connected) === true) {
2260
2261                $(connection).triggerHandler(events.onReconnect);
2262            }
2263        }
2264    };
2265
2266}(window.jQuery, window));
2267/* jquery.signalR.transports.longPolling.js */
2268// Copyright (c) .NET Foundation. All rights reserved.
2269// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
2270
2271
2272/*global window:false */
2273/// <reference path="jquery.signalR.transports.common.js" />
2274
2275(function ($, window, undefined) {
2276
2277    var signalR = $.signalR,
2278        events = $.signalR.events,
2279        changeState = $.signalR.changeState,
2280        isDisconnecting = $.signalR.isDisconnecting,
2281        transportLogic = signalR.transports._logic;
2282
2283    signalR.transports.longPolling = {
2284        name: "longPolling",
2285
2286        supportsKeepAlive: function () {
2287            return false;
2288        },
2289
2290        reconnectDelay: 3000,
2291
2292        start: function (connection, onSuccess, onFailed) {
2293            /// <summary>Starts the long polling connection</summary>
2294            /// <param name="connection" type="signalR">The SignalR connection to start</param>
2295            var that = this,
2296                fireConnect = function () {
2297                    fireConnect = $.noop;
2298
2299                    connection.log("LongPolling connected.");
2300
2301                    if (onSuccess) {
2302                        onSuccess();
2303                    } else {
2304                        connection.log("WARNING! The client received an init message after reconnecting.");
2305                    }
2306                },
2307                tryFailConnect = function (error) {
2308                    if (onFailed(error)) {
2309                        connection.log("LongPolling failed to connect.");
2310                        return true;
2311                    }
2312
2313                    return false;
2314                },
2315                privateData = connection._,
2316                reconnectErrors = 0,
2317                fireReconnected = function (instance) {
2318                    window.clearTimeout(privateData.reconnectTimeoutId);
2319                    privateData.reconnectTimeoutId = null;
2320
2321                    if (changeState(instance,
2322                                    signalR.connectionState.reconnecting,
2323                                    signalR.connectionState.connected) === true) {
2324                        // Successfully reconnected!
2325                        instance.log("Raising the reconnect event");
2326                        $(instance).triggerHandler(events.onReconnect);
2327                    }
2328                },
2329                // 1 hour
2330                maxFireReconnectedTimeout = 3600000;
2331
2332            if (connection.pollXhr) {
2333                connection.log("Polling xhr requests already exists, aborting.");
2334                connection.stop();
2335            }
2336
2337            connection.messageId = null;
2338
2339            privateData.reconnectTimeoutId = null;
2340
2341            privateData.pollTimeoutId = window.setTimeout(function () {
2342                (function poll(instance, raiseReconnect) {
2343                    var messageId = instance.messageId,
2344                        connect = (messageId === null),
2345                        reconnecting = !connect,
2346                        polling = !raiseReconnect,
2347                        url = transportLogic.getUrl(instance, that.name, reconnecting, polling, true /* use Post for longPolling */),
2348                        postData = {};
2349
2350                    if (instance.messageId) {
2351                        postData.messageId = instance.messageId;
2352                    }
2353
2354                    if (instance.groupsToken) {
2355                        postData.groupsToken = instance.groupsToken;
2356                    }
2357
2358                    // If we've disconnected during the time we've tried to re-instantiate the poll then stop.
2359                    if (isDisconnecting(instance) === true) {
2360                        return;
2361                    }
2362
2363                    connection.log("Opening long polling request to '" + url + "'.");
2364                    instance.pollXhr = transportLogic.ajax(connection, {
2365                        xhrFields: {
2366                            onprogress: function () {
2367                                transportLogic.markLastMessage(connection);
2368                            }
2369                        },
2370                        url: url,
2371                        type: "POST",
2372                        contentType: signalR._.defaultContentType,
2373                        data: postData,
2374                        timeout: connection._.pollTimeout
vendor: 8,663 bytes, lines 2374-2538
2374,
2375                        success: function (result) {
2376                            var minData,
2377                                delay = 0,
2378                                data,
2379                                shouldReconnect;
2380
2381                            connection.log("Long poll complete.");
2382
2383                            // Reset our reconnect errors so if we transition into a reconnecting state again we trigger
2384                            // reconnected quickly
2385                            reconnectErrors = 0;
2386
2387                            try {
2388                                // Remove any keep-alives from the beginning of the result
2389                                minData = connection._parseResponse(result);
2390                            }
2391                            catch (error) {
2392                                transportLogic.handleParseFailure(instance, result, error, tryFailConnect, instance.pollXhr);
2393                                return;
2394                            }
2395
2396                            // If there's currently a timeout to trigger reconnect, fire it now before processing messages
2397                            if (privateData.reconnectTimeoutId !== null) {
2398                                fireReconnected(instance);
2399                            }
2400
2401                            if (minData) {
2402                                data = transportLogic.maximizePersistentResponse(minData);
2403                            }
2404
2405                            transportLogic.processMessages(instance, minData, fireConnect);
2406
2407                            if (data &&
2408                                $.type(data.LongPollDelay) === "number") {
2409                                delay = data.LongPollDelay;
2410                            }
2411
2412                            if (isDisconnecting(instance) === true) {
2413                                return;
2414                            }
2415
2416                            shouldReconnect = data && data.ShouldReconnect;
2417                            if (shouldReconnect) {
2418                                // Transition into the reconnecting state
2419                                // If this fails then that means that the user transitioned the connection into a invalid state in processMessages.
2420                                if (!transportLogic.ensureReconnectingState(instance)) {
2421                                    return;
2422                                }
2423                            }
2424
2425                            // We never want to pass a raiseReconnect flag after a successful poll.  This is handled via the error function
2426                            if (delay > 0) {
2427                                privateData.pollTimeoutId = window.setTimeout(function () {
2428                                    poll(instance, shouldReconnect);
2429                                }, delay);
2430                            } else {
2431                                poll(instance, shouldReconnect);
2432                            }
2433                        },
2434
2435                        error: function (data, textStatus) {
2436                            var error = signalR._.transportError(signalR.resources.longPollFailed, connection.transport, data, instance.pollXhr);
2437
2438                            // Stop trying to trigger reconnect, connection is in an error state
2439                            // If we're not in the reconnect state this will noop
2440                            window.clearTimeout(privateData.reconnectTimeoutId);
2441                            privateData.reconnectTimeoutId = null;
2442
2443                            if (textStatus === "abort") {
2444                                connection.log("Aborted xhr request.");
2445                                return;
2446                            }
2447
2448                            if (!tryFailConnect(error)) {
2449
2450                                // Increment our reconnect errors, we assume all errors to be reconnect errors
2451                                // In the case that it's our first error this will cause Reconnect to be fired
2452                                // after 1 second due to reconnectErrors being = 1.
2453                                reconnectErrors++;
2454
2455                                if (connection.state !== signalR.connectionState.reconnecting) {
2456                                    connection.log("An error occurred using longPolling. Status = " + textStatus + ".  Response = " + data.responseText + ".");
2457                                    $(instance).triggerHandler(events.onError, [error]);
2458                                }
2459
2460                                // We check the state here to verify that we're not in an invalid state prior to verifying Reconnect.
2461                                // If we're not in connected or reconnecting then the next ensureReconnectingState check will fail and will return.
2462                                // Therefore we don't want to change that failure code path.
2463                                if ((connection.state === signalR.connectionState.connected ||
2464                                    connection.state === signalR.connectionState.reconnecting) &&
2465                                    !transportLogic.verifyLastActive(connection)) {
2466                                    return;
2467                                }
2468
2469                                // Transition into the reconnecting state
2470                                // If this fails then that means that the user transitioned the connection into the disconnected or connecting state within the above error handler trigger.
2471                                if (!transportLogic.ensureReconnectingState(instance)) {
2472                                    return;
2473                                }
2474
2475                                // Call poll with the raiseReconnect flag as true after the reconnect delay
2476                                privateData.pollTimeoutId = window.setTimeout(function () {
2477                                    poll(instance, true);
2478                                }, that.reconnectDelay);
2479                            }
2480                        }
2481                    });
2482
2483                    // This will only ever pass after an error has occurred via the poll ajax procedure.
2484                    if (reconnecting && raiseReconnect === true) {
2485                        // We wait to reconnect depending on how many times we've failed to reconnect.
2486                        // This is essentially a heuristic that will exponentially increase in wait time before
2487                        // triggering reconnected.  This depends on the "error" handler of Poll to cancel this
2488                        // timeout if it triggers before the Reconnected event fires.
2489                        // The Math.min at the end is to ensure that the reconnect timeout does not overflow.
2490                        privateData.reconnectTimeoutId = window.setTimeout(function () { fireReconnected(instance); }, Math.min(1000 * (Math.pow(2, reconnectErrors) - 1), maxFireReconnectedTimeout));
2491                    }
2492                }(connection));
2493            }, 250); // Have to delay initial poll so Chrome doesn't show loader spinner in tab
2494        },
2495
2496        lostConnection: function (connection) {
2497            if (connection.pollXhr) {
2498                connection.pollXhr.abort("lostConnection");
2499            }
2500        },
2501
2502        send: function (connection, data) {
2503            transportLogic.ajaxSend(connection, data);
2504        },
2505
2506        stop: function (connection) {
2507            /// <summary>Stops the long polling connection</summary>
2508            /// <param name="connection" type="signalR">The SignalR connection to stop</param>
2509
2510            window.clearTimeout(connection._.pollTimeoutId);
2511            window.clearTimeout(connection._.reconnectTimeoutId);
2512
2513            delete connection._.pollTimeoutId;
2514            delete connection._.reconnectTimeoutId;
2515
2516            if (connection.pollXhr) {
2517                connection.pollXhr.abort();
2518                connection.pollXhr = null;
2519                delete connection.pollXhr;
2520            }
2521        },
2522
2523        abort: function (connection, async) {
2524            transportLogic.ajaxAbort(connection, async);
2525        }
2526    };
2527
2528}(window.jQuery, window));
2529/* jquery.signalR.hubs.js */
2530// Copyright (c) .NET Foundation. All rights reserved.
2531// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
2532
2533/*global window:false */
2534/// <reference path="jquery.signalR.core.js" />
2535
2536(function ($, window, undefined) {
2537
2538    var 
vendor: 2,287 bytes, lines 2538-2601
2538eventNamespace = ".hubProxy",
2539        signalR = $.signalR;
2540
2541    function makeEventName(event) {
2542        return event + eventNamespace;
2543    }
2544
2545    // Equivalent to Array.prototype.map
2546    function map(arr, fun, thisp) {
2547        var i,
2548            length = arr.length,
2549            result = [];
2550        for (i = 0; i < length; i += 1) {
2551            if (arr.hasOwnProperty(i)) {
2552                result[i] = fun.call(thisp, arr[i], i, arr);
2553            }
2554        }
2555        return result;
2556    }
2557
2558    function getArgValue(a) {
2559        return $.isFunction(a) ? null : ($.type(a) === "undefined" ? null : a);
2560    }
2561
2562    function hasMembers(obj) {
2563        for (var key in obj) {
2564            // If we have any properties in our callback map then we have callbacks and can exit the loop via return
2565            if (obj.hasOwnProperty(key)) {
2566                return true;
2567            }
2568        }
2569
2570        return false;
2571    }
2572
2573    function clearInvocationCallbacks(connection, error) {
2574        /// <param name="connection" type="hubConnection" />
2575        var callbacks = connection._.invocationCallbacks,
2576            callback;
2577
2578        if (hasMembers(callbacks)) {
2579            connection.log("Clearing hub invocation callbacks with error: " + error + ".");
2580        }
2581
2582        // Reset the callback cache now as we have a local var referencing it
2583        connection._.invocationCallbackId = 0;
2584        delete connection._.invocationCallbacks;
2585        connection._.invocationCallbacks = {};
2586
2587        // Loop over the callbacks and invoke them.
2588        // We do this using a local var reference and *after* we've cleared the cache
2589        // so that if a fail callback itself tries to invoke another method we don't
2590        // end up with its callback in the list we're looping over.
2591        for (var callbackId in callbacks) {
2592            callback = callbacks[callbackId];
2593            callback.method.call(callback.scope, { E: error });
2594        }
2595    }
2596
2597    // hubProxy
2598    function hubProxy(hubConnection, hubName) {
2599        /// <summary>
2600        ///     Creates a new proxy object for the given hub connection that can be used to invoke
2601        ///     methods on server hubs and handle client method invocation requests from the server.
2602        /// </summary>
2603        return new hubProxy.fn.init(hubConnection, hubName);
2604    }
2605
2606    hubProxy.fn = hubProxy.prototype = {
2607        init: function (connection, hubName) {
2608            this.state = {};
2609            this.connection = connection;
2610            this.hubName = hubName;
2611            this._ = {
2612                callbackMap: {}
2613            };
2614        },
2615
2616        constructor: hubProxy,
2617
2618        hasSubscriptions: function () {
2619            return hasMembers(this._.callbackMap);
2620        },
2621
2622        on: function (eventName, callback) {
2623            /// <summary>Wires up a callback to be invoked when a invocation request is received from the server hub.</summary>
2624            /// <param name="eventName" type="String">The name of the hub event to register the callback for.</param>
2625            /// <param name="callback" type="Function">The callback to be invoked.</param>
2626            var that = this,
2627                callbackMap = that._.callbackMap;
2628
2629            // Normalize the event name to lowercase
2630            eventName = eventName.toLowerCase();
2631
2632            // If there is not an event registered for this callback yet we want to create its event space in the callback map.
2633            if (!callbackMap[eventName]) {
2634                callbackMap[eventName] = {};
2635            }
2636
2637            // Map the callback to our encompassed function
2638            callbackMap[eventName][callback] = function (e, data) {
2639                callback.apply(that, data);
2640            };
2641
2642            $(that).bind(makeEventName(eventName), callbackMap[eventName][callback]);
2643
2644            return that;
2645        },
2646
2647        off: function (eventName, callback) {
2648            /// <summary>Removes the callback invocation request from the server hub for the given event name.</summary>
2649            /// <param name="eventName" type="String">The name of the hub event to unregister the callback for.</param>
2650            /// <param name="callback" type="Function">The callback to be invoked.</param>
2651            var that = this,
2652                callbackMap = that._.callbackMap,
2653                callbackSpace;
2654
2655            // Normalize the event name to lowercase
2656            eventName = eventName.toLowerCase();
2657
2658            callbackSpace = callbackMap[eventName];
2659
2660            // Verify that there is an event space to unbind
2661            if (callbackSpace) {
2662                // Only unbind if there's an event bound with eventName and a callback with the specified callback
2663                if (callbackSpace[callback]) {
2664                    $(that).unbind(makeEventName(eventName), callbackSpace[callback]);
2665
2666                    // Remove the callback from the callback map
2667                    delete callbackSpace[callback];
2668
2669                    // Check if there are any members left on the event, if not we need to destroy it.
2670                    if (!hasMembers(callbackSpace)) {
2671                        delete callbackMap[eventName];
2672                    }
2673                } else if (!callback) { // Check if we're removing the whole event and we didn't error because of an invalid callback
2674                    $(that).unbind(makeEventName(eventName));
2675
2676                    delete callbackMap[eventName];
2677                }
2678            }
2679
2680            return that;
2681        },
2682
2683        invoke: function (methodName) {
2684            /// <summary>Invokes a server hub method with the given arguments.</summary>
2685            /// <param name="methodName" type="String">The name of the server hub method.</param>
2686
2687            var that = this,
2688                connection = that.connection,
2689                args = $.makeArray(arguments).slice(1),
2690                argValues = map(args, getArgValue),
2691                data = { H: that.hubName, M: methodName, A: argValues, I: connection._.invocationCallbackId },
2692                d = $.Deferred(),
2693                callback = function (minResult) {
2694                    var result = that._maximizeHubResponse(minResult),
2695                        source,
2696                        error;
2697
2698                    // Update the hub state
2699                    $.extend(that.state, result.State);
2700
2701                    if (result.Progress) {
2702                        if (d.notifyWith) {
vendor: 10,769 bytes, lines 2703-2958
2703                            // Progress is only supported in jQuery 1.7+
2704                            d.notifyWith(that, [result.Progress.Data]);
2705                        } else if(!connection._.progressjQueryVersionLogged) {
2706                            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.");
2707                            connection._.progressjQueryVersionLogged = true;
2708                        }
2709                    } else if (result.Error) {
2710                        // Server hub method threw an exception, log it & reject the deferred
2711                        if (result.StackTrace) {
2712                            connection.log(result.Error + "\n" + result.StackTrace + ".");
2713                        }
2714
2715                        // result.ErrorData is only set if a HubException was thrown
2716                        source = result.IsHubException ? "HubException" : "Exception";
2717                        error = signalR._.error(result.Error, source);
2718                        error.data = result.ErrorData;
2719
2720                        connection.log(that.hubName + "." + methodName + " failed to execute. Error: " + error.message);
2721                        d.rejectWith(that, [error]);
2722                    } else {
2723                        // Server invocation succeeded, resolve the deferred
2724                        connection.log("Invoked " + that.hubName + "." + methodName);
2725                        d.resolveWith(that, [result.Result]);
2726                    }
2727                };
2728
2729            connection._.invocationCallbacks[connection._.invocationCallbackId.toString()] = { scope: that, method: callback };
2730            connection._.invocationCallbackId += 1;
2731
2732            if (!$.isEmptyObject(that.state)) {
2733                data.S = that.state;
2734            }
2735
2736            connection.log("Invoking " + that.hubName + "." + methodName);
2737            connection.send(data);
2738
2739            return d.promise();
2740        },
2741
2742        _maximizeHubResponse: function (minHubResponse) {
2743            return {
2744                State: minHubResponse.S,
2745                Result: minHubResponse.R,
2746                Progress: minHubResponse.P ? {
2747                    Id: minHubResponse.P.I,
2748                    Data: minHubResponse.P.D
2749                } : null,
2750                Id: minHubResponse.I,
2751                IsHubException: minHubResponse.H,
2752                Error: minHubResponse.E,
2753                StackTrace: minHubResponse.T,
2754                ErrorData: minHubResponse.D
2755            };
2756        }
2757    };
2758
2759    hubProxy.fn.init.prototype = hubProxy.fn;
2760
2761    // hubConnection
2762    function hubConnection(url, options) {
2763        /// <summary>Creates a new hub connection.</summary>
2764        /// <param name="url" type="String">[Optional] The hub route url, defaults to "/signalr".</param>
2765        /// <param name="options" type="Object">[Optional] Settings to use when creating the hubConnection.</param>
2766        var settings = {
2767            qs: null,
2768            logging: false,
2769            useDefaultPath: true
2770        };
2771
2772        $.extend(settings, options);
2773
2774        if (!url || settings.useDefaultPath) {
2775            url = (url || "") + "/signalr";
2776        }
2777        return new hubConnection.fn.init(url, settings);
2778    }
2779
2780    hubConnection.fn = hubConnection.prototype = $.connection();
2781
2782    hubConnection.fn.init = function (url, options) {
2783        var settings = {
2784                qs: null,
2785                logging: false,
2786                useDefaultPath: true
2787            },
2788            connection = this;
2789
2790        $.extend(settings, options);
2791
2792        // Call the base constructor
2793        $.signalR.fn.init.call(connection, url, settings.qs, settings.logging);
2794
2795        // Object to store hub proxies for this connection
2796        connection.proxies = {};
2797
2798        connection._.invocationCallbackId = 0;
2799        connection._.invocationCallbacks = {};
2800
2801        // Wire up the received handler
2802        connection.received(function (minData) {
2803            var data, proxy, dataCallbackId, callback, hubName, eventName;
2804            if (!minData) {
2805                return;
2806            }
2807
2808            // We have to handle progress updates first in order to ensure old clients that receive
2809            // progress updates enter the return value branch and then no-op when they can't find
2810            // the callback in the map (because the minData.I value will not be a valid callback ID)
2811            if (typeof (minData.P) !== "undefined") {
2812                // Process progress notification
2813                dataCallbackId = minData.P.I.toString();
2814                callback = connection._.invocationCallbacks[dataCallbackId];
2815                if (callback) {
2816                    callback.method.call(callback.scope, minData);
2817                }
2818            } else if (typeof (minData.I) !== "undefined") {
2819                // We received the return value from a server method invocation, look up callback by id and call it
2820                dataCallbackId = minData.I.toString();
2821                callback = connection._.invocationCallbacks[dataCallbackId];
2822                if (callback) {
2823                    // Delete the callback from the proxy
2824                    connection._.invocationCallbacks[dataCallbackId] = null;
2825                    delete connection._.invocationCallbacks[dataCallbackId];
2826
2827                    // Invoke the callback
2828                    callback.method.call(callback.scope, minData);
2829                }
2830            } else {
2831                data = this._maximizeClientHubInvocation(minData);
2832
2833                // We received a client invocation request, i.e. broadcast from server hub
2834                connection.log("Triggering client hub event '" + data.Method + "' on hub '" + data.Hub + "'.");
2835
2836                // Normalize the names to lowercase
2837                hubName = data.Hub.toLowerCase();
2838                eventName = data.Method.toLowerCase();
2839
2840                // Trigger the local invocation event
2841                proxy = this.proxies[hubName];
2842
2843                // Update the hub state
2844                $.extend(proxy.state, data.State);
2845                $(proxy).triggerHandler(makeEventName(eventName), [data.Args]);
2846            }
2847        });
2848
2849        connection.error(function (errData, origData) {
2850            var callbackId, callback;
2851
2852            if (!origData) {
2853                // No original data passed so this is not a send error
2854                return;
2855            }
2856
2857            callbackId = origData.I;
2858            callback = connection._.invocationCallbacks[callbackId];
2859
2860            // Verify that there is a callback bound (could have been cleared)
2861            if (callback) {
2862                // Delete the callback
2863                connection._.invocationCallbacks[callbackId] = null;
2864                delete connection._.invocationCallbacks[callbackId];
2865
2866                // Invoke the callback with an error to reject the promise
2867                callback.method.call(callback.scope, { E: errData });
2868            }
2869        });
2870
2871        connection.reconnecting(function () {
2872            if (connection.transport && connection.transport.name === "webSockets") {
2873                clearInvocationCallbacks(connection, "Connection started reconnecting before invocation result was received.");
2874            }
2875        });
2876
2877        connection.disconnected(function () {
2878            clearInvocationCallbacks(connection, "Connection was disconnected before invocation result was received.");
2879        });
2880    };
2881
2882    hubConnection.fn._maximizeClientHubInvocation = function (minClientHubInvocation) {
2883        return {
2884            Hub: minClientHubInvocation.H,
2885            Method: minClientHubInvocation.M,
2886            Args: minClientHubInvocation.A,
2887            State: minClientHubInvocation.S
2888        };
2889    };
2890
2891    hubConnection.fn._registerSubscribedHubs = function () {
2892        /// <summary>
2893        ///     Sets the starting event to loop through the known hubs and register any new hubs
2894        ///     that have been added to the proxy.
2895        /// </summary>
2896        var connection = this;
2897
2898        if (!connection._subscribedToHubs) {
2899            connection._subscribedToHubs = true;
2900            connection.starting(function () {
2901                // Set the connection's data object with all the hub proxies with active subscriptions.
2902                // These proxies will receive notifications from the server.
2903                var subscribedHubs = [];
2904
2905                $.each(connection.proxies, function (key) {
2906                    if (this.hasSubscriptions()) {
2907                        subscribedHubs.push({ name: key });
2908                        connection.log("Client subscribed to hub '" + key + "'.");
2909                    }
2910                });
2911
2912                if (subscribedHubs.length === 0) {
2913                    connection.log("No hubs have been subscribed to.  The client will not receive data from hubs.  To fix, declare at least one client side function prior to connection start for each hub you wish to subscribe to.");
2914                }
2915
2916                connection.data = connection.json.stringify(subscribedHubs);
2917            });
2918        }
2919    };
2920
2921    hubConnection.fn.createHubProxy = function (hubName) {
2922        /// <summary>
2923        ///     Creates a new proxy object for the given hub connection that can be used to invoke
2924        ///     methods on server hubs and handle client method invocation requests from the server.
2925        /// </summary>
2926        /// <param name="hubName" type="String">
2927        ///     The name of the hub on the server to create the proxy for.
2928        /// </param>
2929
2930        // Normalize the name to lowercase
2931        hubName = hubName.toLowerCase();
2932
2933        var proxy = this.proxies[hubName];
2934        if (!proxy) {
2935            proxy = hubProxy(this, hubName);
2936            this.proxies[hubName] = proxy;
2937        }
2938
2939        this._registerSubscribedHubs();
2940
2941        return proxy;
2942    };
2943
2944    hubConnection.fn.init.prototype = hubConnection.fn;
2945
2946    $.hubConnection = hubConnection;
2947
2948}(window.jQuery, window));
2949/* jquery.signalR.version.js */
2950// Copyright (c) .NET Foundation. All rights reserved.
2951// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
2952
2953
2954/*global window:false */
2955/// <reference path="jquery.signalR.core.js" />
2956(function ($, undefined) {
2957    $.signalR.version = "2.2.2";
2958}(window.jQuery));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.