trotzig/diffux

View on GitHub
bower_components/jquery/src/ajax/xhr.js

Summary

Maintainability
F
4 days
Test Coverage
define([
    "../core",
    "../var/support",
    "../ajax"
], function( jQuery, support ) {

jQuery.ajaxSettings.xhr = function() {
    try {
        return new XMLHttpRequest();
    } catch( e ) {}
};

var xhrId = 0,
    xhrCallbacks = {},
    xhrSuccessStatus = {
        // file protocol always yields status code 0, assume 200
        0: 200,
        // Support: IE9
        // #1450: sometimes IE returns 1223 when it should be 204
        1223: 204
    },
    xhrSupported = jQuery.ajaxSettings.xhr();

// Support: IE9
// Open requests must be manually aborted on unload (#5280)
// See https://support.microsoft.com/kb/2856746 for more info
if ( window.attachEvent ) {
    window.attachEvent( "onunload", function() {
        for ( var key in xhrCallbacks ) {
            xhrCallbacks[ key ]();
        }
    });
}

support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
support.ajax = xhrSupported = !!xhrSupported;

jQuery.ajaxTransport(function( options ) {
    var callback;

    // Cross domain only allowed if supported through XMLHttpRequest
    if ( support.cors || xhrSupported && !options.crossDomain ) {
        return {
            send: function( headers, complete ) {
                var i,
                    xhr = options.xhr(),
                    id = ++xhrId;

                xhr.open( options.type, options.url, options.async, options.username, options.password );

                // Apply custom fields if provided
                if ( options.xhrFields ) {
                    for ( i in options.xhrFields ) {
                        xhr[ i ] = options.xhrFields[ i ];
                    }
                }

                // Override mime type if needed
                if ( options.mimeType && xhr.overrideMimeType ) {
                    xhr.overrideMimeType( options.mimeType );
                }

                // X-Requested-With header
                // For cross-domain requests, seeing as conditions for a preflight are
                // akin to a jigsaw puzzle, we simply never set it to be sure.
                // (it can always be set on a per-request basis or even using ajaxSetup)
                // For same-domain requests, won't change header if already provided.
                if ( !options.crossDomain && !headers["X-Requested-With"] ) {
                    headers["X-Requested-With"] = "XMLHttpRequest";
                }

                // Set headers
                for ( i in headers ) {
                    xhr.setRequestHeader( i, headers[ i ] );
                }

                // Callback
                callback = function( type ) {
                    return function() {
                        if ( callback ) {
                            delete xhrCallbacks[ id ];
                            callback = xhr.onload = xhr.onerror = null;

                            if ( type === "abort" ) {
                                xhr.abort();
                            } else if ( type === "error" ) {
                                complete(
                                    // file: protocol always yields status 0; see #8605, #14207
                                    xhr.status,
                                    xhr.statusText
                                );
                            } else {
                                complete(
                                    xhrSuccessStatus[ xhr.status ] || xhr.status,
                                    xhr.statusText,
                                    // Support: IE9
                                    // Accessing binary-data responseText throws an exception
                                    // (#11426)
                                    typeof xhr.responseText === "string" ? {
                                        text: xhr.responseText
                                    } : undefined,
                                    xhr.getAllResponseHeaders()
                                );
                            }
                        }
                    };
                };

                // Listen to events
                xhr.onload = callback();
                xhr.onerror = callback("error");

                // Create the abort callback
                callback = xhrCallbacks[ id ] = callback("abort");

                try {
                    // Do send the request (this may raise an exception)
                    xhr.send( options.hasContent && options.data || null );
                } catch ( e ) {
                    // #14683: Only rethrow if this hasn't been notified as an error yet
                    if ( callback ) {
                        throw e;
                    }
                }
            },

            abort: function() {
                if ( callback ) {
                    callback();
                }
            }
        };
    }
});

});