jQuery.extend({
    createUploadIframe: function(frameId, uri) {
		if ($.browser.msie) {
			var io = document.createElement('<iframe id="' + frameId + '" name="' + frameId + '" />');

			if (typeof uri == 'boolean') {
				io.src = 'javascript:false';
			} else if (typeof uri == 'string') {
				io.src = uri;
			}
		} else {
			var io = $("<iframe></iframe>");
			io.attr("id", frameId);
			io.attr("name", frameId);
		}

		$(io).css({
			position: "absolute",
			top: "-1000px",
			left: "-1000px"
		});

		$("body").append(io);

		return $.browser.msie ? io : io[0];
    },

	createUploadForm: function(formId, fileId, fileElementId) {
		var form = $('<form action="" method="POST" name="' + formId + '" id="' + formId + '" enctype="multipart/form-data"></form>');
		var oldElement = $('#' + fileElementId);
		var newElement = $(oldElement).clone();

		oldElement.attr('id', fileId);
		oldElement.before(newElement);
		oldElement.appendTo(form);

		form.css({
			position: "absolute",
			top: "-1200px",
			left: "-1200px"
		});

		form.appendTo("body");

		return form;
    },

	ajaxFileUpload: function(s) {
		s = jQuery.extend({}, jQuery.ajaxSettings, s);

		var id = new Date().getTime();
		var frameId = "jUploadFrame" + id;
		var formId = "jUploadForm" + id;
		var fileId = "jUploadFile" + id;
		
		var form = jQuery.createUploadForm(formId, fileId, s.fileElementId);
		var io = jQuery.createUploadIframe(frameId, s.secureuri);

		var requestDone = false;

		if (s.global && !(jQuery.active++)) {
			jQuery.event.trigger("ajaxStart");
		}

		// Create the request object
		var xml = {};

		if (s.global) {
			jQuery.event.trigger("ajaxSend", [xml, s]);
		}

		// Wait for a response to come back
		var uploadCallback = function(isTimeout) {
			try {				
				if (io.contentWindow) {
					xml.responseText = io.contentWindow.document.body ? io.contentWindow.document.body.innerHTML : null;
					xml.responseXML = io.contentWindow.document.XMLDocument ? io.contentWindow.document.XMLDocument : io.contentWindow.document;
				} else if(io.contentDocument) {
					xml.responseText = io.contentDocument.document.body ? io.contentDocument.document.body.innerHTML : null;
					xml.responseXML = io.contentDocument.document.XMLDocument ? io.contentDocument.document.XMLDocument : io.contentDocument.document;
				}
			} catch(e) {
				jQuery.handleError(s, xml, null, e);
			}

			if (xml || isTimeout == "timeout") {
				var status;
				requestDone = true;

				try {
					status = isTimeout != "timeout" ? "success" : "error";

					// Make sure that the request was successful or notmodified
					if (status != "error") {
						// process the data (runs the xml through httpData regardless of callback)
						var data = jQuery.uploadHttpData(xml, s.dataType);

						// 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", [xml, s]);
						}
                    } else {
						jQuery.handleError(s, xml, status);
					}
                } catch(e) {
					status = "error";
					jQuery.handleError(s, xml, status, e);
				}

				// The request was completed
				if (s.global) {
					jQuery.event.trigger("ajaxComplete", [xml, s]);
				}

				// Handle the global AJAX counter
				if (s.global && !(--jQuery.active)) {
					jQuery.event.trigger("ajaxStop");
				}

				// Process result
				if (s.complete) {
					s.complete(xml, status);
				}

				jQuery(io).unbind();

				setTimeout(function(){
					try {
						$(io).remove();
						form.remove();
					} catch(e) {
						jQuery.handleError(s, xml, null, e);
					}
				}, 100);

                xml = null;
			}
		};

		// Timeout checker
		if (s.timeout > 0) {
			setTimeout(function(){
				// Check to see if the request is still happening
				if (!requestDone) {
					uploadCallback("timeout");
				}
			}, s.timeout);
		}

		try {
			form.attr("action", s.url);
			form.attr("method", "POST");
			form.attr("target", frameId);

			form.submit();
		} catch(e) {
			jQuery.handleError(s, xml, null, e);
		}

		$(io).load(uploadCallback);

		return {
			abort: function() {}
		};
    },

	uploadHttpData: function(r, type) {
		var data = !type;
		data = type == "xml" || data ? r.responseXML : r.responseText;

		if (type == "json" && !data) {
			type = "xml";
			data = r.responseXML;
		}

		// 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") {
			eval( "data = " + data );
		}

		// evaluate scripts within html
		if (type == "html") {
			jQuery("<div>").html(data).evalScripts();
		}

        return data;
	}
});