var jsc = now(), rscript = //g, rselectTextarea = /select|textarea/i, rinput = /text|hidden|password|search/i, jsre = /=\?(&|$)/, rquery = /\?/, rts = /(\?|&)_=.*?(&|$)/, rurl = /^(\w+:)?\/\/([^\/?#]+)/, r20 = /%20/g; jQuery.fn.extend({ // Keep a copy of the old load _load: jQuery.fn.load, load: function( url, params, callback ) { if ( typeof url !== "string" ) { return this._load( url ); } 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 ); 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 ommited if ( jQuery.isFunction( data ) ) { 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 ) { if ( jQuery.isFunction( data ) ) { 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, */ // Create the request object; Microsoft failed to properly // implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available // This function can be overriden by calling jQuery.ajaxSetup xhr: function(){ return window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest(); }, accepts: { xml: "application/xml, text/xml", html: "text/html", script: "text/javascript, application/javascript", json: "application/json, text/javascript", text: "text/plain", _default: "*/*" } }, // Last-Modified header cache for next request lastModified: {}, etag: {}, ajax: function( s ) { // Extend the settings, but re-extend 's' so that it can be // checked again later (in the test suite, specifically) s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s)); var jsonp, status, data, type = s.type.toUpperCase(); // convert data if not already a string if ( s.data && s.processData && typeof s.data !== "string" ) { s.data = jQuery.param(s.data); } // 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 = "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 window[ jsonp ] = function(tmp){ data = tmp; success(); complete(); // Garbage collect window[ jsonp ] = undefined; try{ delete window[ jsonp ]; } catch(e){} if ( head ) { head.removeChild( script ); } }; } if ( s.dataType === "script" && s.cache === null ) { s.cache = false; } if ( s.cache === false && type === "GET" ) { var ts = 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.active++ ) { jQuery.event.trigger( "ajaxStart" ); } // Matches an absolute URL, and saves the domain var parts = rurl.exec( s.url ); // If we're requesting a remote document // and trying to load JSON or Script with a GET if ( s.dataType === "script" && type === "GET" && parts && ( parts[1] && parts[1] !== location.protocol || parts[2] !== location.host )) { var head = document.getElementsByTagName("head")[0]; var script = document.createElement("script"); script.src = s.url; if ( s.scriptCharset ) { script.charset = s.scriptCharset; } // ooktay: Error handling on firefox (DOM standard) script.onerror = function(){ jQuery.handleError(s, null, "error"); complete(); }; // 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; success(); complete(); // 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(); // 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 ) { 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.etag[s.url] ) { xhr.setRequestHeader("If-None-Match", jQuery.etag[s.url]); } } // Set header so the called script knows that it's an XMLHttpRequest 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(e){} // Allow custom headers/mimetypes and early abort if ( s.beforeSend && s.beforeSend(xhr, s) === false ) { // Handle the global AJAX counter if ( s.global && ! --jQuery.active ) { jQuery.event.trigger( "ajaxStop" ); } // close opended socket xhr.abort(); return false; } if ( s.global ) { jQuery.event.trigger("ajaxSend", [xhr, s]); } // Wait for a response to come back var onreadystatechange = function(isTimeout){ // The request was aborted, clear the interval and decrement jQuery.active if ( xhr.readyState === 0 ) { if ( ival ) { // clear poll interval clearInterval( ival ); ival = null; // Handle the global AJAX counter if ( s.global && ! --jQuery.active ) { jQuery.event.trigger( "ajaxStop" ); } } // 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; // clear poll interval if (ival) { clearInterval(ival); ival = null; } status = isTimeout === "timeout" ? "timeout" : !jQuery.httpSuccess( xhr ) ? "error" : s.ifModified && jQuery.httpNotModified( xhr, s.url ) ? "notmodified" : "success"; 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.httpData( xhr, s.dataType, s ); } catch(e) { status = "parsererror"; } } // Make sure that the request was successful or notmodified if ( status === "success" || status === "notmodified" ) { // JSONP handles its own success callback if ( !jsonp ) { success(); } } else { jQuery.handleError(s, xhr, status); } // Fire the complete handlers complete(); if ( isTimeout ) { xhr.abort(); } // Stop memory leaks if ( s.async ) { xhr = null; } } }; if ( s.async ) { // don't attach the handler to the request, just poll it instead var ival = setInterval(onreadystatechange, 13); // Timeout checker if ( 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 === "POST" || type === "PUT" ? s.data : null ); } catch(e) { jQuery.handleError(s, xhr, null, e); } // firefox 1.5 doesn't fire statechange for sync requests if ( !s.async ) { onreadystatechange(); } function success(){ // If a local callback was specified, fire it and pass it the data if ( s.success ) { s.success( data, status ); } // Fire the global callback if ( s.global ) { jQuery.event.trigger( "ajaxSuccess", [xhr, s] ); } } function complete(){ // Process result if ( s.complete ) { s.complete(xhr, status); } // The request was completed if ( s.global ) { jQuery.event.trigger( "ajaxComplete", [xhr, s] ); } // Handle the global AJAX counter if ( s.global && ! --jQuery.active ) { jQuery.event.trigger( "ajaxStop" ); } } // return XMLHttpRequest to allow aborting the request etc. return xhr; }, handleError: function( s, xhr, status, e ) { // If a local callback was specified, fire it if ( s.error ) { s.error( xhr, status, e ); } // Fire the global callback if ( s.global ) { jQuery.event.trigger( "ajaxError", [xhr, s, e] ); } }, // Counter for holding the number of active queries active: 0, // 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:" || // Opera returns 0 when status is 304 ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status === 304 || xhr.status === 1223 || xhr.status === 0; } catch(e){} return false; }, // Determines if an XMLHttpRequest returns NotModified httpNotModified: function( xhr, url ) { var last_modified = xhr.getResponseHeader("Last-Modified"), etag = xhr.getResponseHeader("Etag"); if ( last_modified ) { jQuery.lastModified[url] = last_modified; } if ( etag ) { jQuery.etag[url] = etag; } // Opera returns 0 when status is 304 return xhr.status === 304 || xhr.status === 0; }, httpData: function( xhr, type, s ) { var ct = xhr.getResponseHeader("content-type"), xml = type === "xml" || !type && ct && ct.indexOf("xml") >= 0, data = xml ? xhr.responseXML : xhr.responseText; if ( xml && data.documentElement.nodeName === "parsererror" ) { throw "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" ) { // If the type is "script", eval it in global context if ( type === "script" ) { jQuery.globalEval( data ); } // Get the JavaScript object, if JSON is used. if ( type === "json" ) { if ( typeof JSON === "object" && JSON.parse ) { data = JSON.parse( data ); } else { data = (new Function("return " + data))(); } } } return data; }, // Serialize an array of form elements or a set of // key/values into a query string param: function( a ) { var s = []; function add( key, value ){ s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value); } // 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 ); }); // Otherwise, assume that it's an object of key/value pairs } else { // Serialize the key/values for ( var j in a ) { // If the value is an array then the key names need to be repeated if ( jQuery.isArray(a[j]) ) { jQuery.each( a[j], function(){ add( j, this ); }); } else { add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] ); } } } // Return the resulting serialization return s.join("&").replace(r20, "+"); } });