(function($) {
	$.fn.jqm = function(o) {
		var _o = {
			zIndex : 3000,
			overlay : 50,
			overlayClass : 'moverlay',
			closeClass : 'jqmClose',
			trigger : '.jqModal',
			ajax : false,
			target : false,
			modal : false,
			toTop : false,
			onShow : false,
			onHide : false,
			onLoad : false
		};
		return this.each(function() {
			if (this._jqm)
				return;
			s++;
			this._jqm = s;
			H[s] = {
				c : $.extend(_o, o),
				a : false,
				w : $(this).addClass('jqmID' + s),
				s : s
			};
			if (_o.trigger)
				$(this).jqmAddTrigger(_o.trigger);
		});
	};

	$.fn.jqmAddClose = function(e) {
		hs(this, e, 'jqmHide');
		return this;
	};
	$.fn.jqmAddTrigger = function(e) {
		hs(this, e, 'jqmShow');
		return this;
	};
	$.fn.jqmShow = function(t) {
		return this.each(function() {
			if (!H[this._jqm].a)
				$.jqm.open(this._jqm, t)
		});
	};
	$.fn.jqmHide = function(t) {
		return this.each(function() {
			if (H[this._jqm].a)
				$.jqm.close(this._jqm, t)
		});
	};

	$.jqm = {
		hash : {},
		open : function(s, t) {
			var h = H[s], c = h.c, cc = '.' + c.closeClass, z = (/^\d+$/
					.test(h.w.css('z-index'))) ? h.w.css('z-index') : c.zIndex, o = $(
					'<div></div>').css({
				height : '100%',
				width : '100%',
				position : 'fixed',
				left : 0,
				top : 0,
				'z-index' : z - 1,
				opacity : c.overlay / 100
			});
			h.t = t;
			h.a = true;
			h.w.css('z-index', z);
			if (c.modal) {
				if (!A[0])
					F('bind');
				A.push(s);
				o.css('cursor', 'wait');
			} else if (c.overlay > 0)
				h.w.jqmAddClose(o);
			else
				o = false;

			h.o = (o) ? o.addClass(c.overlayClass).prependTo('body') : false;
			if (ie6) {
				$('html,body').css({
					height : '100%',
					width : '100%'
				});
				if (o) {
					o = o.css({
						position : 'absolute'
					})[0];
					for ( var y in {
						Top : 1,
						Left : 1
					})
						o.style.setExpression(y.toLowerCase(),
								"(_=(document.documentElement.scroll" + y
										+ " || document.body.scroll" + y
										+ "))+'px'");
				}
			}

			if (c.ajax) {
				var r = c.target || h.w, u = c.ajax, r = (typeof r == 'string') ? $(
						r, h.w)
						: $(r), u = (u.substr(0, 1) == '@') ? $(t).attr(
						u.substring(1)) : u;
				r.load(u, function() {
					if (c.onLoad)
						c.onLoad.call(this, h);
					if (cc)
						h.w.jqmAddClose($(cc, h.w));
					e(h);
				});
			} else if (cc)
				h.w.jqmAddClose($(cc, h.w));

			if (c.toTop && h.o)
				h.w.before('<span id="jqmP' + h.w[0]._jqm + '"></span>')
						.insertAfter(h.o);
			(c.onShow) ? c.onShow(h) : h.w.show();
			e(h);
			return false;
		},
		close : function(s) {
			var h = H[s];
			h.a = false;
			if (A[0]) {
				A.pop();
				if (!A[0])
					F('unbind');
			}
			if (h.c.toTop && h.o)
				$('#jqmP' + h.w[0]._jqm).after(h.w).remove();
			if (h.c.onHide)
				h.c.onHide(h);
			else {
				h.w.hide();
				if (h.o)
					h.o.remove();
			}
			return false;
		}
	};
	var s = 0, H = $.jqm.hash, A = [], ie6 = $.browser.msie
			&& ($.browser.version == "6.0"), i = $(
			'<iframe src="javascript:false;document.write(\'\');" class="jqm"></iframe>')
			.css({
				opacity : 0
			}), e = function(h) {
		if (ie6)
			if (h.o)
				h.o.html('<p style="width:100%;height:100%"/>').prepend(i);
			else if (!$('iframe.jqm', h.w)[0])
				h.w.prepend(i);
		f(h);
	}, f = function(h) {
		try {
			$(':input:visible', h.w)[0].focus();
		} catch (e) {
		}
	}, F = function(t) {
		$()[t]("keypress", m)[t]("keydown", m)[t]("mousedown", m);
	}, m = function(e) {
		var h = H[A[A.length - 1]], r = (!$(e.target).parents('.jqmID' + h.s)[0]);
		if (r)
			f(h);
		return !r;
	}, hs = function(w, e, y) {
		var s = [];
		w.each(function() {
			s.push(this._jqm)
		});
		$(e).each(function() {
			if (this[y])
				$.extend(this[y], s);
			else {
				this[y] = s;
				$(this).click(function() {
					for ( var i in {
						jqmShow : 1,
						jqmHide : 1
					})
						for ( var s in this[i])
							if (H[this[i][s]])
								H[this[i][s]].w[i](this);
					return false;
				});
			}
		});
	};
})(jQuery);

(function($) {
	$.fn.ajaxSubmit = function(options) {
		if (typeof options == 'function')
			options = {
				success : options
			};

		options = $.extend({
			url : this.attr('action') || window.location.toString(),
			type : this.attr('method') || 'GET'
		}, options || {});

		var veto = {};
		this.trigger('form-pre-serialize', [ this, options, veto ]);
		if (veto.veto)
			return this;

		var a = this.formToArray(options.semantic);
		if (options.data) {
			options.extraData = options.data;
			for ( var n in options.data)
				a.push({
					name : n,
					value : options.data[n]
				});
		}

		if (options.beforeSubmit
				&& options.beforeSubmit(a, this, options) === false)
			return this;

		this.trigger('form-submit-validate', [ a, this, options, veto ]);
		if (veto.veto)
			return this;

		var q = $.param(a);

		if (options.type.toUpperCase() == 'GET') {
			options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
			options.data = null; // data is null for 'get'
		} else
			options.data = q; // data is the query string for 'post'

		var $form = this, callbacks = [];
		if (options.resetForm)
			callbacks.push(function() {
				$form.resetForm();
			});
		if (options.clearForm)
			callbacks.push(function() {
				$form.clearForm();
			});

		// perform a load on the target only if dataType is not provided
		if (!options.dataType && options.target) {
			var oldSuccess = options.success || function() {
			};
			callbacks.push(function(data) {
				$(options.target).html(data).each(oldSuccess, arguments);
			});
		} else if (options.success)
			callbacks.push(options.success);

		options.success = function(data, status) {
			for ( var i = 0, max = callbacks.length; i < max; i++)
				callbacks[i](data, status, $form);
		};

		// are there files to upload?
		var files = $('input:file', this).fieldValue();
		var found = false;
		for ( var j = 0; j < files.length; j++)
			if (files[j])
				found = true;

		// options.iframe allows user to force iframe mode
		if (options.iframe || found) {
			if ($.browser.safari && options.closeKeepAlive)
				$.get(options.closeKeepAlive, fileUpload);
			else
				fileUpload();
		} else
			$.ajax(options);

		// fire 'notify' event
		this.trigger('form-submit-notify', [ this, options ]);
		return this;

		// private function for handling file uploads (hat tip to YAHOO!)
		function fileUpload() {
			var form = $form[0];
			var opts = $.extend({}, $.ajaxSettings, options);

			var id = 'jqFormIO' + (new Date().getTime());
			var $io = $('<iframe id="' + id + '" name="' + id + '" />');
			var io = $io[0];
			var op8 = $.browser.opera && window.opera.version() < 9;
			if ($.browser.msie || op8)
				io.src = 'javascript:false;document.write("");';
			$io.css({
				position : 'absolute',
				top : '-1000px',
				left : '-1000px'
			});

			var xhr = { // mock object
				responseText : null,
				responseXML : null,
				status : 0,
				statusText : 'n/a',
				getAllResponseHeaders : function() {
				},
				getResponseHeader : function() {
				},
				setRequestHeader : function() {
				}
			};

			var g = opts.global;
			// trigger ajax global events so that activity/block indicators work
			// like normal
			if (g && !$.active++)
				$.event.trigger("ajaxStart");
			if (g)
				$.event.trigger("ajaxSend", [ xhr, opts ]);

			var cbInvoked = 0;
			var timedOut = 0;

			// take a breath so that pending repaints get some cpu time before
			// the upload starts
			setTimeout(function() {
				// make sure form attrs are set
				var t = $form.attr('target'), a = $form.attr('action');
				$form.attr({
					target : id,
					encoding : 'multipart/form-data',
					enctype : 'multipart/form-data',
					method : 'POST',
					action : opts.url
				});

				// support timout
				if (opts.timeout)
					setTimeout(function() {
						timedOut = true;
						cb();
					}, opts.timeout);

				// add "extra" data to form if provided in options
				var extraInputs = [];
				try {
					if (options.extraData)
						for ( var n in options.extraData)
							extraInputs.push($(
									'<input type="hidden" name="' + n
											+ '" value="'
											+ options.extraData[n] + '" />')
									.appendTo(form)[0]);

					// add iframe to doc and submit the form
					$io.appendTo('body');
					io.attachEvent ? io.attachEvent('onload', cb) : io
							.addEventListener('load', cb, false);
					form.submit();
				} finally {
					// reset attrs and remove "extra" input elements
					$form.attr('action', a);
					t ? $form.attr('target', t) : $form.removeAttr('target');
					$(extraInputs).remove();
				}
			}, 10);

			function cb() {
				if (cbInvoked++)
					return;

				io.detachEvent ? io.detachEvent('onload', cb) : io
						.removeEventListener('load', cb, false);

				var ok = true;
				try {
					if (timedOut)
						throw 'timeout';
					// extract the server response from the iframe
					var data, doc;
					doc = io.contentWindow ? io.contentWindow.document
							: io.contentDocument ? io.contentDocument
									: io.document;
					xhr.responseText = doc.body ? doc.body.innerHTML : null;
					xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
					xhr.getResponseHeader = function(header) {
						var headers = {
							'content-type' : opts.dataType
						};
						return headers[header];
					};

					if (opts.dataType == 'json' || opts.dataType == 'script') {
						var ta = doc.getElementsByTagName('textarea')[0];
						xhr.responseText = ta ? ta.value : xhr.responseText;
					} else if (opts.dataType == 'xml' && !xhr.responseXML
							&& xhr.responseText != null) {
						xhr.responseXML = toXml(xhr.responseText);
					}
					data = $.httpData(xhr, opts.dataType);
				} catch (e) {
					ok = false;
					$.handleError(opts, xhr, 'error', e);
				}

				// ordering of these callbacks/triggers is odd, but that's how
				// $.ajax does it
				if (ok) {
					opts.success(data, 'success');
					if (g)
						$.event.trigger("ajaxSuccess", [ xhr, opts ]);
				}
				if (g)
					$.event.trigger("ajaxComplete", [ xhr, opts ]);
				if (g && !--$.active)
					$.event.trigger("ajaxStop");
				if (opts.complete)
					opts.complete(xhr, ok ? 'success' : 'error');

				// clean up
				setTimeout(function() {
					$io.remove();
					xhr.responseXML = null;
				}, 100);
			}
			;

			function toXml(s, doc) {
				if (window.ActiveXObject) {
					doc = new ActiveXObject('Microsoft.XMLDOM');
					doc.async = 'false';
					doc.loadXML(s);
				} else
					doc = (new DOMParser()).parseFromString(s, 'text/xml');
				return (doc && doc.documentElement && doc.documentElement.tagName != 'parsererror') ? doc
						: null;
			}
			;
		}
		;
	};

	$.fn.ajaxForm = function(options) {
		return this
				.ajaxFormUnbind()
				.bind('submit.form-plugin', function() {
					$(this).ajaxSubmit(options);
					return false;
				})
				.each(
						function() {
							// store options in hash
							$(":submit,input:image", this)
									.bind(
											'click.form-plugin',
											function(e) {
												var $form = this.form;
												$form.clk = this;
												if (this.type == 'image') {
													if (e.offsetX != undefined) {
														$form.clk_x = e.offsetX;
														$form.clk_y = e.offsetY;
													} else if (typeof $.fn.offset == 'function') { // try
																									// to
																									// use
																									// dimensions
																									// plugin
														var offset = $(this)
																.offset();
														$form.clk_x = e.pageX
																- offset.left;
														$form.clk_y = e.pageY
																- offset.top;
													} else {
														$form.clk_x = e.pageX
																- this.offsetLeft;
														$form.clk_y = e.pageY
																- this.offsetTop;
													}
												}
												// clear form vars
												setTimeout(
														function() {
															$form.clk = $form.clk_x = $form.clk_y = null;
														}, 10);
											});
						});
	};

	$.fn.ajaxFormUnbind = function() {
		this.unbind('submit.form-plugin');
		return this.each(function() {
			$(":submit,input:image", this).unbind('click.form-plugin');
		});

	};

	$.fn.formToArray = function(semantic) {
		var a = [];
		if (this.length == 0)
			return a;

		var form = this[0];
		var els = semantic ? form.getElementsByTagName('*') : form.elements;
		if (!els)
			return a;
		for ( var i = 0, max = els.length; i < max; i++) {
			var el = els[i];
			var n = el.name;
			if (!n)
				continue;

			if (semantic && form.clk && el.type == "image") {
				// handle image inputs on the fly when semantic == true
				if (!el.disabled && form.clk == el)
					a.push({
						name : n + '.x',
						value : form.clk_x
					}, {
						name : n + '.y',
						value : form.clk_y
					});
				continue;
			}

			var v = $.fieldValue(el, true);
			if (v && v.constructor == Array) {
				for ( var j = 0, jmax = v.length; j < jmax; j++)
					a.push({
						name : n,
						value : v[j]
					});
			} else if (v !== null && typeof v != 'undefined')
				a.push({
					name : n,
					value : v
				});
		}

		if (!semantic && form.clk) {
			// input type=='image' are not found in elements array! handle them
			// here
			var inputs = form.getElementsByTagName("input");
			for ( var i = 0, max = inputs.length; i < max; i++) {
				var input = inputs[i];
				var n = input.name;
				if (n && !input.disabled && input.type == "image"
						&& form.clk == input)
					a.push({
						name : n + '.x',
						value : form.clk_x
					}, {
						name : n + '.y',
						value : form.clk_y
					});
			}
		}
		return a;
	};

	$.fn.formSerialize = function(semantic) {
		// hand off to jQuery.param for proper encoding
		return $.param(this.formToArray(semantic));
	};

	$.fn.fieldSerialize = function(successful) {
		var a = [];
		this.each(function() {
			var n = this.name;
			if (!n)
				return;
			var v = $.fieldValue(this, successful);
			if (v && v.constructor == Array) {
				for ( var i = 0, max = v.length; i < max; i++)
					a.push({
						name : n,
						value : v[i]
					});
			} else if (v !== null && typeof v != 'undefined')
				a.push({
					name : this.name,
					value : v
				});
		});
		// hand off to jQuery.param for proper encoding
		return $.param(a);
	};

	$.fn.fieldValue = function(successful) {
		for ( var val = [], i = 0, max = this.length; i < max; i++) {
			var el = this[i];
			var v = $.fieldValue(el, successful);
			if (v === null || typeof v == 'undefined'
					|| (v.constructor == Array && !v.length))
				continue;
			v.constructor == Array ? $.merge(val, v) : val.push(v);
		}
		return val;
	};

	$.fieldValue = function(el, successful) {
		var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
		if (typeof successful == 'undefined')
			successful = true;

		if (successful
				&& (!n || el.disabled || t == 'reset' || t == 'button'
						|| (t == 'checkbox' || t == 'radio') && !el.checked
						|| (t == 'submit' || t == 'image') && el.form
						&& el.form.clk != el || tag == 'select'
						&& el.selectedIndex == -1))
			return null;

		if (tag == 'select') {
			var index = el.selectedIndex;
			if (index < 0)
				return null;
			var a = [], ops = el.options;
			var one = (t == 'select-one');
			var max = (one ? index + 1 : ops.length);
			for ( var i = (one ? index : 0); i < max; i++) {
				var op = ops[i];
				if (op.selected) {
					// extra pain for IE...
					var v = $.browser.msie
							&& !(op.attributes['value'].specified) ? op.text
							: op.value;
					if (one)
						return v;
					a.push(v);
				}
			}
			return a;
		}
		return el.value;
	};

	$.fn.clearForm = function() {
		return this.each(function() {
			$('input,select,textarea', this).clearFields();
		});
	};

	$.fn.clearFields = $.fn.clearInputs = function() {
		return this.each(function() {
			var t = this.type, tag = this.tagName.toLowerCase();
			if (t == 'text' || t == 'password' || tag == 'textarea')
				this.value = '';
			else if (t == 'checkbox' || t == 'radio')
				this.checked = false;
			else if (tag == 'select')
				this.selectedIndex = -1;
		});
	};

	$.fn.resetForm = function() {
		return this.each(function() {
			// guard against an input with the name of 'reset'
			// note that IE reports the reset function as an 'object'
			if (typeof this.reset == 'function'
					|| (typeof this.reset == 'object' && !this.reset.nodeType))
				this.reset();
		});
	};

	$.fn.enable = function(b) {
		if (b == undefined)
			b = true;
		return this.each(function() {
			this.disabled = !b
		});
	};

	$.fn.select = function(select) {
		if (select == undefined)
			select = true;
		return this.each(function() {
			var t = this.type;
			if (t == 'checkbox' || t == 'radio')
				this.checked = select;
			else if (this.tagName.toLowerCase() == 'option') {
				var $sel = $(this).parent('select');
				if (select && $sel[0] && $sel[0].type == 'select-one') {
					// deselect all other options
					$sel.find('option').select(false);
				}
				this.selected = select;
			}
		});
	};

})(jQuery);

