(function( jQuery ) { var jsc = jQuery.now(), rscript = //gi, rselectTextarea = /select|textarea/i, rinput = /color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i, jsre = /\=\?(&|$)/, rquery = /\?/, rts = /(\?|&)_=.*?(&|$)/, rurl = /^(\w+:)?\/\/([^\/?#]+)/, r20 = /%20/g, // Keep a copy of the old load method _load = jQuery.fn.load; jQuery.fn.extend({ load: function( url, params, callback ) { if ( typeof url !== "string" && _load ) { return _load.apply( this, arguments ); // Don't do a request if no elements are being requested } else if ( !this.length ) { return this; } var off = url.indexOf(" "); if ( off >= 0 ) { var selector = url.slice(off, url.length); url = url.slice(0, off); } // Default to a GET request var type = "GET"; // If the second parameter was provided if ( params ) { // If it's a function if ( jQuery.isFunction( params ) ) { // We assume that it's the callback callback = params; params = null; // Otherwise, build a param string } else if ( typeof params === "object" ) { params = jQuery.param( params, jQuery.ajaxSettings.traditional ); type = "POST"; } } var self = this; // Request the remote document jQuery.ajax({ url: url, type: type, dataType: "html", data: params, complete: function( res, status ) { // If successful, inject the HTML into all the matched elements if ( status === "success" || status === "notmodified" ) { // See if a selector was specified self.html( selector ? // Create a dummy div to hold the results jQuery("
") // inject the contents of the document in, removing the scripts // to avoid any 'Permission Denied' errors in IE .append(res.responseText.replace(rscript, "")) // Locate the specified elements .find(selector) : // If not, just inject the full result res.responseText ); } if ( callback ) { self.each( callback, [res.responseText, status, res] ); } } }); return this; }, serialize: function() { return jQuery.param(this.serializeArray()); }, serializeArray: function() { return this.map(function() { return this.elements ? jQuery.makeArray(this.elements) : this; }) .filter(function() { return this.name && !this.disabled && (this.checked || rselectTextarea.test(this.nodeName) || rinput.test(this.type)); }) .map(function( i, elem ) { var val = jQuery(this).val(); return val == null ? null : jQuery.isArray(val) ? jQuery.map( val, function( val, i ) { return { name: elem.name, value: val }; }) : { name: elem.name, value: val }; }).get(); } }); // Attach a bunch of functions for handling common AJAX events jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), function( i, o ) { jQuery.fn[o] = function( f ) { return this.bind(o, f); }; }); jQuery.extend({ get: function( url, data, callback, type ) { // shift arguments if data argument was omited if ( jQuery.isFunction( data ) ) { type = type || callback; callback = data; data = null; } return jQuery.ajax({ type: "GET", url: url, data: data, success: callback, dataType: type }); }, getScript: function( url, callback ) { return jQuery.get(url, null, callback, "script"); }, getJSON: function( url, data, callback ) { return jQuery.get(url, data, callback, "json"); }, post: function( url, data, callback, type ) { // shift arguments if data argument was omited if ( jQuery.isFunction( data ) ) { type = type || callback; callback = data; data = {}; } return jQuery.ajax({ type: "POST", url: url, data: data, success: callback, dataType: type }); }, ajaxSetup: function( settings ) { jQuery.extend( jQuery.ajaxSettings, settings ); }, ajaxSettings: { url: location.href, global: true, type: "GET", contentType: "application/x-www-form-urlencoded", processData: true, async: true, /* timeout: 0, data: null, username: null, password: null, traditional: false, */ // Create the request object; Microsoft failed to properly // implement the XMLHttpRequest in IE7 (can't request local files), // so we use the ActiveXObject when it is available // This function can be overriden by calling jQuery.ajaxSetup xhr: window.XMLHttpRequest && (window.location.protocol !== "file:" || !window.ActiveXObject) ? function() { return new window.XMLHttpRequest(); } : function() { try { return new window.ActiveXObject("Microsoft.XMLHTTP"); } catch(e) {} }, accepts: { xml: "application/xml, text/xml", html: "text/html", script: "text/javascript, application/javascript", json: "application/json, text/javascript", text: "text/plain", _default: "*/*" } }, ajax: function( origSettings ) { var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings), jsonp, status, data, type = s.type.toUpperCase(); s.context = origSettings && origSettings.context || s; // convert data if not already a string if ( s.data && s.processData && typeof s.data !== "string" ) { s.data = jQuery.param( s.data, s.traditional ); } // Handle JSONP Parameter Callbacks if ( s.dataType === "jsonp" ) { if ( type === "GET" ) { if ( !jsre.test( s.url ) ) { s.url += (rquery.test( s.url ) ? "&" : "?") + (s.jsonp || "callback") + "=?"; } } else if ( !s.data || !jsre.test(s.data) ) { s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?"; } s.dataType = "json"; } // Build temporary JSONP function if ( s.dataType === "json" && (s.data && jsre.test(s.data) || jsre.test(s.url)) ) { jsonp = s.jsonpCallback || ("jsonp" + jsc++); // Replace the =? sequence both in the query string and the data if ( s.data ) { s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1"); } s.url = s.url.replace(jsre, "=" + jsonp + "$1"); // We need to make sure // that a JSONP style response is executed properly s.dataType = "script"; // Handle JSONP-style loading var customJsonp = window[ jsonp ]; window[ jsonp ] = function( tmp ) { data = tmp; jQuery.ajax.handleSuccess( s, xhr, status, data ); jQuery.ajax.handleComplete( s, xhr, status, data ); if ( jQuery.isFunction( customJsonp ) ) { customJsonp( tmp ); } else { // Garbage collect window[ jsonp ] = undefined; try { delete window[ jsonp ]; } catch( jsonpError ) {} } if ( head ) { head.removeChild( script ); } }; } if ( s.dataType === "script" && s.cache === null ) { s.cache = false; } if ( s.cache === false && type === "GET" ) { var ts = jQuery.now(); // try replacing _= if it is there var ret = s.url.replace(rts, "$1_=" + ts + "$2"); // if nothing was replaced, add timestamp to the end s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : ""); } // If data is available, append data to url for get requests if ( s.data && type === "GET" ) { s.url += (rquery.test(s.url) ? "&" : "?") + s.data; } // Watch for a new set of requests if ( s.global && jQuery.ajax.active++ === 0 ) { jQuery.event.trigger( "ajaxStart" ); } // Matches an absolute URL, and saves the domain var parts = rurl.exec( s.url ), remote = parts && (parts[1] && parts[1] !== location.protocol || parts[2] !== location.host); // If we're requesting a remote document // and trying to load JSON or Script with a GET if ( s.dataType === "script" && type === "GET" && remote ) { var head = document.getElementsByTagName("head")[0] || document.documentElement; var script = document.createElement("script"); script.src = s.url; if ( s.scriptCharset ) { script.charset = s.scriptCharset; } // Handle Script loading if ( !jsonp ) { var done = false; // Attach handlers for all browsers script.onload = script.onreadystatechange = function() { if ( !done && (!this.readyState || this.readyState === "loaded" || this.readyState === "complete") ) { done = true; jQuery.ajax.handleSuccess( s, xhr, status, data ); jQuery.ajax.handleComplete( s, xhr, status, data ); // Handle memory leak in IE script.onload = script.onreadystatechange = null; if ( head && script.parentNode ) { head.removeChild( script ); } } }; } // Use insertBefore instead of appendChild to circumvent an IE6 bug. // This arises when a base node is used (#2709 and #4378). head.insertBefore( script, head.firstChild ); // We handle everything using the script element injection return undefined; } var requestDone = false; // Create the request object var xhr = s.xhr(); if ( !xhr ) { return; } // Open the socket // Passing null username, generates a login popup on Opera (#2865) if ( s.username ) { xhr.open(type, s.url, s.async, s.username, s.password); } else { xhr.open(type, s.url, s.async); } // Need an extra try/catch for cross domain requests in Firefox 3 try { // Set the correct header, if data is being sent if ( s.data || origSettings && origSettings.contentType ) { xhr.setRequestHeader("Content-Type", s.contentType); } // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. if ( s.ifModified ) { if ( jQuery.lastModified[s.url] ) { xhr.setRequestHeader("If-Modified-Since", jQuery.lastModified[s.url]); } if ( jQuery.ajax.etag[s.url] ) { xhr.setRequestHeader("If-None-Match", jQuery.ajax.etag[s.url]); } } // Set header so the called script knows that it's an XMLHttpRequest // Only send the header if it's not a remote XHR if ( !remote ) { xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); } // Set the Accepts header for the server, depending on the dataType xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ? s.accepts[ s.dataType ] + ", */*" : s.accepts._default ); } catch( headerError ) {} // Allow custom headers/mimetypes and early abort if ( s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false ) { // Handle the global AJAX counter if ( s.global && jQuery.ajax.active-- === 1 ) { jQuery.event.trigger( "ajaxStop" ); } // close opended socket xhr.abort(); return false; } if ( s.global ) { jQuery.ajax.triggerGlobal( s, "ajaxSend", [xhr, s] ); } // Wait for a response to come back var onreadystatechange = xhr.onreadystatechange = function( isTimeout ) { // The request was aborted if ( !xhr || xhr.readyState === 0 || isTimeout === "abort" ) { // Opera doesn't call onreadystatechange before this point // so we simulate the call if ( !requestDone ) { jQuery.ajax.handleComplete( s, xhr, status, data ); } requestDone = true; if ( xhr ) { xhr.onreadystatechange = jQuery.noop; } // The transfer is complete and the data is available, or the request timed out } else if ( !requestDone && xhr && (xhr.readyState === 4 || isTimeout === "timeout") ) { requestDone = true; xhr.onreadystatechange = jQuery.noop; status = isTimeout === "timeout" ? "timeout" : !jQuery.ajax.httpSuccess( xhr ) ? "error" : s.ifModified && jQuery.ajax.httpNotModified( xhr, s.url ) ? "notmodified" : "success"; var errMsg; if ( status === "success" ) { // Watch for, and catch, XML document parse errors try { // process the data (runs the xml through httpData regardless of callback) data = jQuery.ajax.httpData( xhr, s.dataType, s ); } catch( parserError ) { status = "parsererror"; errMsg = parserError; } } // Make sure that the request was successful or notmodified if ( status === "success" || status === "notmodified" ) { // JSONP handles its own success callback if ( !jsonp ) { jQuery.ajax.handleSuccess( s, xhr, status, data ); } } else { jQuery.ajax.handleError( s, xhr, status, errMsg ); } // Fire the complete handlers if ( !jsonp ) { jQuery.ajax.handleComplete( s, xhr, status, data ); } if ( isTimeout === "timeout" ) { xhr.abort(); } // Stop memory leaks if ( s.async ) { xhr = null; } } }; // Override the abort handler, if we can (IE doesn't allow it, but that's OK) // Opera doesn't fire onreadystatechange at all on abort try { var oldAbort = xhr.abort; xhr.abort = function() { if ( xhr ) { oldAbort.call( xhr ); } onreadystatechange( "abort" ); }; } catch( abortError ) {} // Timeout checker if ( s.async && s.timeout > 0 ) { setTimeout(function() { // Check to see if the request is still happening if ( xhr && !requestDone ) { onreadystatechange( "timeout" ); } }, s.timeout); } // Send the data try { xhr.send( (type !== "GET" && s.data) || null ); } catch( sendError ) { jQuery.ajax.handleError( s, xhr, null, e ); // Fire the complete handlers jQuery.ajax.handleComplete( s, xhr, status, data ); } // firefox 1.5 doesn't fire statechange for sync requests if ( !s.async ) { onreadystatechange(); } // return XMLHttpRequest to allow aborting the request etc. return xhr; }, // Serialize an array of form elements or a set of // key/values into a query string param: function( a, traditional ) { var s = [], add = function( key, value ) { // If value is a function, invoke it and return its value value = jQuery.isFunction(value) ? value() : value; s[ s.length ] = encodeURIComponent(key) + "=" + encodeURIComponent(value); }; // Set traditional to true for jQuery <= 1.3.2 behavior. if ( traditional === undefined ) { traditional = jQuery.ajaxSettings.traditional; } // If an array was passed in, assume that it is an array of form elements. if ( jQuery.isArray(a) || a.jquery ) { // Serialize the form elements jQuery.each( a, function() { add( this.name, this.value ); }); } else { // If traditional, encode the "old" way (the way 1.3.2 or older // did it), otherwise encode params recursively. for ( var prefix in a ) { buildParams( prefix, a[prefix], traditional, add ); } } // Return the resulting serialization return s.join("&").replace(r20, "+"); } }); function buildParams( prefix, obj, traditional, add ) { if ( jQuery.isArray(obj) ) { // Serialize array item. jQuery.each( obj, function( i, v ) { if ( traditional || /\[\]$/.test( prefix ) ) { // Treat each array item as a scalar. add( prefix, v ); } else { // If array item is non-scalar (array or object), encode its // numeric index to resolve deserialization ambiguity issues. // Note that rack (as of 1.0.0) can't currently deserialize // nested arrays properly, and attempting to do so may cause // a server error. Possible fixes are to modify rack's // deserialization algorithm or to provide an option or flag // to force array serialization to be shallow. buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v, traditional, add ); } }); } else if ( !traditional && obj != null && typeof obj === "object" ) { // Serialize object item. jQuery.each( obj, function( k, v ) { buildParams( prefix + "[" + k + "]", v, traditional, add ); }); } else { // Serialize scalar item. add( prefix, obj ); } } jQuery.extend( jQuery.ajax, { // Counter for holding the number of active queries active: 0, // Last-Modified header cache for next request lastModified: {}, etag: {}, handleError: function( s, xhr, status, e ) { // If a local callback was specified, fire it if ( s.error ) { s.error.call( s.context, xhr, status, e ); } // Fire the global callback if ( s.global ) { jQuery.ajax.triggerGlobal( s, "ajaxError", [xhr, s, e] ); } }, handleSuccess: function( s, xhr, status, data ) { // If a local callback was specified, fire it and pass it the data if ( s.success ) { s.success.call( s.context, data, status, xhr ); } // Fire the global callback if ( s.global ) { jQuery.ajax.triggerGlobal( s, "ajaxSuccess", [xhr, s] ); } }, handleComplete: function( s, xhr, status ) { // Process result if ( s.complete ) { s.complete.call( s.context, xhr, status ); } // The request was completed if ( s.global ) { jQuery.ajax.triggerGlobal( s, "ajaxComplete", [xhr, s] ); } // Handle the global AJAX counter if ( s.global && jQuery.ajax.active-- === 1 ) { jQuery.event.trigger( "ajaxStop" ); } }, triggerGlobal: function( s, type, args ) { (s.context && s.context.url == null ? jQuery(s.context) : jQuery.event).trigger(type, args); }, // Determines if an XMLHttpRequest was successful or not httpSuccess: function( xhr ) { try { // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450 return !xhr.status && location.protocol === "file:" || xhr.status >= 200 && xhr.status < 300 || xhr.status === 304 || xhr.status === 1223; } catch(e) {} return false; }, // Determines if an XMLHttpRequest returns NotModified httpNotModified: function( xhr, url ) { var lastModified = xhr.getResponseHeader("Last-Modified"), etag = xhr.getResponseHeader("Etag"); if ( lastModified ) { jQuery.ajax.lastModified[url] = lastModified; } if ( etag ) { jQuery.ajax.etag[url] = etag; } return xhr.status === 304; }, httpData: function( xhr, type, s ) { var ct = xhr.getResponseHeader("content-type") || "", xml = type === "xml" || !type && ct.indexOf("xml") >= 0, data = xml ? xhr.responseXML : xhr.responseText; if ( xml && data.documentElement.nodeName === "parsererror" ) { jQuery.error( "parsererror" ); } // Allow a pre-filtering function to sanitize the response // s is checked to keep backwards compatibility if ( s && s.dataFilter ) { data = s.dataFilter( data, type ); } // The filter can actually parse the response if ( typeof data === "string" ) { // Get the JavaScript object, if JSON is used. if ( type === "json" || !type && ct.indexOf("json") >= 0 ) { data = jQuery.parseJSON( data ); // If the type is "script", eval it in global context } else if ( type === "script" || !type && ct.indexOf("javascript") >= 0 ) { jQuery.globalEval( data ); } } return data; } }); // Does this browser support XHR requests? jQuery.support.ajax = !!jQuery.ajaxSettings.xhr(); // For backwards compatibility jQuery.extend( jQuery.ajax ); })( jQuery );