
// usage: log('inside coolFunc', this, arguments);
// paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
window.log = function(){
  log.history = log.history || [];   // store logs to an array for reference
  log.history.push(arguments);
  if(this.console) {
    arguments.callee = arguments.callee.caller;
    var newarr = [].slice.call(arguments);
    (typeof console.log === 'object' ? log.apply.call(console.log, console, newarr) : console.log.apply(console, newarr));
  }
};

// make it safe to use console.log always
(function(b){function c(){}for(var d="assert,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,timeStamp,profile,profileEnd,time,timeEnd,trace,warn".split(","),a;a=d.pop();){b[a]=b[a]||c}})((function(){try
{console.log();return window.console;}catch(err){return window.console={};}})());


// place any jQuery/helper plugins in here, instead of separate, slower script files.


(function($){
	/* hoverIntent by Brian Cherne */
	$.fn.hoverIntent = function(f,g) {
		// default configuration options
		var cfg = {
			sensitivity: 7,
			interval: 100,
			timeout: 0
		};
		// override configuration options with user supplied object
		cfg = $.extend(cfg, g ? { over: f, out: g } : f );

		// instantiate variables
		// cX, cY = current X and Y position of mouse, updated by mousemove event
		// pX, pY = previous X and Y position of mouse, set by mouseover and polling interval
		var cX, cY, pX, pY;

		// A private function for getting mouse position
		var track = function(ev) {
			cX = ev.pageX;
			cY = ev.pageY;
		};

		// A private function for comparing current and previous mouse position
		var compare = function(ev,ob) {
			ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
			// compare mouse positions to see if they've crossed the threshold
			if ( ( Math.abs(pX-cX) + Math.abs(pY-cY) ) < cfg.sensitivity ) {
				$(ob).unbind("mousemove",track);
				// set hoverIntent state to true (so mouseOut can be called)
				ob.hoverIntent_s = 1;
				return cfg.over.apply(ob,[ev]);
			} else {
				// set previous coordinates for next time
				pX = cX; pY = cY;
				// use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
				ob.hoverIntent_t = setTimeout( function(){compare(ev, ob);} , cfg.interval );
			}
		};

		// A private function for delaying the mouseOut function
		var delay = function(ev,ob) {
			ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
			ob.hoverIntent_s = 0;
			return cfg.out.apply(ob,[ev]);
		};

		// A private function for handling mouse 'hovering'
		var handleHover = function(e) {
			// next three lines copied from jQuery.hover, ignore children onMouseOver/onMouseOut
			var p = (e.type == "mouseover" ? e.fromElement : e.toElement) || e.relatedTarget;
			while ( p && p != this ) { try { p = p.parentNode; } catch(e) { p = this; } }
			if ( p == this ) { return false; }

			// copy objects to be passed into t (required for event object to be passed in IE)
			var ev = jQuery.extend({},e);
			var ob = this;

			// cancel hoverIntent timer if it exists
			if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); }

			// else e.type == "onmouseover"
			if (e.type == "mouseover") {
				// set "previous" X and Y position based on initial entry point
				pX = ev.pageX; pY = ev.pageY;
				// update "current" X and Y position based on mousemove
				$(ob).bind("mousemove",track);
				// start polling interval (self-calling timeout) to compare mouse coordinates over time
				if (ob.hoverIntent_s != 1) { ob.hoverIntent_t = setTimeout( function(){compare(ev,ob);} , cfg.interval );}

			// else e.type == "onmouseout"
			} else {
				// unbind expensive mousemove event
				$(ob).unbind("mousemove",track);
				// if hoverIntent state is true, then call the mouseOut function after the specified delay
				if (ob.hoverIntent_s == 1) { ob.hoverIntent_t = setTimeout( function(){delay(ev,ob);} , cfg.timeout );}
			}
		};

		// bind the function to the two event listeners
		return this.mouseover(handleHover).mouseout(handleHover);
	};
	
})(jQuery);

/*
 * Superfish v1.4.8 - jQuery menu widget
 * Copyright (c) 2008 Joel Birch
 *
 * Dual licensed under the MIT and GPL licenses:
 * 	http://www.opensource.org/licenses/mit-license.php
 * 	http://www.gnu.org/licenses/gpl.html
 *
 * CHANGELOG: http://users.tpg.com.au/j_birch/plugins/superfish/changelog.txt
 */

;(function($){
	$.fn.superfish = function(op){

		var sf = $.fn.superfish,
			c = sf.c,
			$arrow = $(['<span class="',c.arrowClass,'"> &#187;</span>'].join('')),
			over = function(){
				var $$ = $(this), menu = getMenu($$);
				clearTimeout(menu.sfTimer);
				$$.showSuperfishUl().siblings().hideSuperfishUl();
			},
			out = function(){
				var $$ = $(this), menu = getMenu($$), o = sf.op;
				clearTimeout(menu.sfTimer);
				menu.sfTimer=setTimeout(function(){
					o.retainPath=($.inArray($$[0],o.$path)>-1);
					$$.hideSuperfishUl();
					if (o.$path.length && $$.parents(['li.',o.hoverClass].join('')).length<1){over.call(o.$path);}
				},o.delay);	
			},
			getMenu = function($menu){
				var menu = $menu.parents(['ul.',c.menuClass,':first'].join(''))[0];
				sf.op = sf.o[menu.serial];
				return menu;
			},
			addArrow = function($a){$a.addClass(c.anchorClass).append($arrow.clone());};
			
		return this.each(function() {
			var s = this.serial = sf.o.length;
			var o = $.extend({},sf.defaults,op);
			o.$path = $('li.'+o.pathClass,this).slice(0,o.pathLevels).each(function(){
				$(this).addClass([o.hoverClass,c.bcClass].join(' '))
					.filter('li:has(ul)').removeClass(o.pathClass);
			});
			sf.o[s] = sf.op = o;
			
			$('li:has(ul)',this)[($.fn.hoverIntent && !o.disableHI) ? 'hoverIntent' : 'hover'](over,out).each(function() {
				if (o.autoArrows) addArrow( $('>a:first-child',this) );
			})
			.not('.'+c.bcClass)
				.hideSuperfishUl();
			
			var $a = $('a',this);
			$a.each(function(i){
				var $li = $a.eq(i).parents('li');
				$a.eq(i).focus(function(){over.call($li);}).blur(function(){out.call($li);});
			});
			o.onInit.call(this);
			
		}).each(function() {
			var menuClasses = [c.menuClass];
			if (sf.op.dropShadows  && !($.browser.msie && $.browser.version < 7)) menuClasses.push(c.shadowClass);
			$(this).addClass(menuClasses.join(' '));
		});
	};

	var sf = $.fn.superfish;
	sf.o = [];
	sf.op = {};
	sf.IE7fix = function(){
		var o = sf.op;
		if ($.browser.msie && $.browser.version > 6 && o.dropShadows && o.animation.opacity!=undefined)
			this.toggleClass(sf.c.shadowClass+'-off');
		};
	sf.c = {
		bcClass     : 'sf-breadcrumb',
		menuClass   : 'sf-js-enabled',
		anchorClass : 'sf-with-ul',
		arrowClass  : 'sf-sub-indicator',
		shadowClass : 'sf-shadow'
	};
	sf.defaults = {
		hoverClass	: 'sfHover',
		pathClass	: 'overideThisToUse',
		pathLevels	: 1,
		delay		: 800,
		animation	: {opacity:'show'},
		speed		: 'normal',
		autoArrows	: true,
		dropShadows : true,
		disableHI	: false,		// true disables hoverIntent detection
		onInit		: function(){}, // callback functions
		onBeforeShow: function(){},
		onShow		: function(){},
		onHide		: function(){}};
	$.fn.extend({
		hideSuperfishUl : function(){
			var o = sf.op,
				not = (o.retainPath===true) ? o.$path : '';
			o.retainPath = false;
			var $ul = $(['li.',o.hoverClass].join(''),this).add(this).not(not).removeClass(o.hoverClass)
					.find('>ul').hide().css('visibility','hidden');
			o.onHide.call($ul);
			return this;
		},
		showSuperfishUl : function(){
			var o = sf.op,
				sh = sf.c.shadowClass+'-off',
				$ul = this.addClass(o.hoverClass)
					.find('>ul:hidden').css('visibility','visible');
			sf.IE7fix.call($ul);
			o.onBeforeShow.call($ul);
			$ul.animate(o.animation,o.speed,function(){ sf.IE7fix.call($ul); o.onShow.call($ul); });
			return this;
		}
	});

})(jQuery);

// /*!
//  * jQuery Form Plugin
//  * version: 2.77 (23-MAY-2011)
//  * @requires jQuery v1.3.2 or later
//  *
//  * Examples and documentation at: http://malsup.com/jquery/form/
//  * Dual licensed under the MIT and GPL licenses:
//  *   http://www.opensource.org/licenses/mit-license.php
//  *   http://www.gnu.org/licenses/gpl.html
//  */
// ;(function($) {
// 
// /*
// 	Usage Note:
// 	-----------
// 	Do not use both ajaxSubmit and ajaxForm on the same form.  These
// 	functions are intended to be exclusive.  Use ajaxSubmit if you want
// 	to bind your own submit handler to the form.  For example,
// 
// 	$(document).ready(function() {
// 		$('#myForm').bind('submit', function(e) {
// 			e.preventDefault(); // <-- important
// 			$(this).ajaxSubmit({
// 				target: '#output'
// 			});
// 		});
// 	});
// 
// 	Use ajaxForm when you want the plugin to manage all the event binding
// 	for you.  For example,
// 
// 	$(document).ready(function() {
// 		$('#myForm').ajaxForm({
// 			target: '#output'
// 		});
// 	});
// 
// 	When using ajaxForm, the ajaxSubmit function will be invoked for you
// 	at the appropriate time.
// */
// 
// /**
//  * ajaxSubmit() provides a mechanism for immediately submitting
//  * an HTML form using AJAX.
//  */
// $.fn.ajaxSubmit = function(options) {
// 	// fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
// 	if (!this.length) {
// 		log('ajaxSubmit: skipping submit process - no element selected');
// 		return this;
// 	}
// 
// 	if (typeof options == 'function') {
// 		options = { success: options };
// 	}
// 
// 	var action = this.attr('action');
// 	var url = (typeof action === 'string') ? $.trim(action) : '';
// 	url = url || window.location.href || '';
// 	if (url) {
// 		// clean url (don't include hash vaue)
// 		url = (url.match(/^([^#]+)/)||[])[1];
// 	}
// 
// 	options = $.extend(true, {
// 		url:  url,
// 		success: $.ajaxSettings.success,
// 		type: this[0].getAttribute('method') || 'GET', // IE7 massage (see issue 57)
// 		iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
// 	}, options);
// 
// 	// hook for manipulating the form data before it is extracted;
// 	// convenient for use with rich editors like tinyMCE or FCKEditor
// 	var veto = {};
// 	this.trigger('form-pre-serialize', [this, options, veto]);
// 	if (veto.veto) {
// 		log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
// 		return this;
// 	}
// 
// 	// provide opportunity to alter form data before it is serialized
// 	if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
// 		log('ajaxSubmit: submit aborted via beforeSerialize callback');
// 		return this;
// 	}
// 
// 	var n,v,a = this.formToArray(options.semantic);
// 	if (options.data) {
// 		options.extraData = options.data;
// 		for (n in options.data) {
// 			if(options.data[n] instanceof Array) {
// 				for (var k in options.data[n]) {
// 					a.push( { name: n, value: options.data[n][k] } );
// 				}
// 			}
// 			else {
// 				v = options.data[n];
// 				v = $.isFunction(v) ? v() : v; // if value is fn, invoke it
// 				a.push( { name: n, value: v } );
// 			}
// 		}
// 	}
// 
// 	// give pre-submit callback an opportunity to abort the submit
// 	if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
// 		log('ajaxSubmit: submit aborted via beforeSubmit callback');
// 		return this;
// 	}
// 
// 	// fire vetoable 'validate' event
// 	this.trigger('form-submit-validate', [a, this, options, veto]);
// 	if (veto.veto) {
// 		log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
// 		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) {
// 			var fn = options.replaceTarget ? 'replaceWith' : 'html';
// 			$(options.target)[fn](data).each(oldSuccess, arguments);
// 		});
// 	}
// 	else if (options.success) {
// 		callbacks.push(options.success);
// 	}
// 
// 	options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
// 		var context = options.context || options;   // jQuery 1.4+ supports scope context 
// 		for (var i=0, max=callbacks.length; i < max; i++) {
// 			callbacks[i].apply(context, [data, status, xhr || $form, $form]);
// 		}
// 	};
// 
// 	// are there files to upload?
// 	var fileInputs = $('input:file', this).length > 0;
// 	var mp = 'multipart/form-data';
// 	var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
// 
// 	// options.iframe allows user to force iframe mode
// 	// 06-NOV-09: now defaulting to iframe mode if file input is detected
//    if (options.iframe !== false && (fileInputs || options.iframe || multipart)) {
// 	   // hack to fix Safari hang (thanks to Tim Molendijk for this)
// 	   // see:  http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
// 	   if (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], s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle;
// 
// 		if ($(':input[name=submit],:input[id=submit]', form).length) {
// 			// if there is an input with a name or id of 'submit' then we won't be
// 			// able to invoke the submit fn on the form (at least not x-browser)
// 			alert('Error: Form elements must not have name or id of "submit".');
// 			return;
// 		}
// 		
// 		s = $.extend(true, {}, $.ajaxSettings, options);
// 		s.context = s.context || s;
// 		$io, id = 'jqFormIO' + (new Date().getTime());
// 		if (s.iframeTarget) {
// 			$io = $(s.iframeTarget);
// 			n = $io.attr('name');
// 			if (n == null)
// 			 	$io.attr('name', id);
// 			else
// 				id = n;
// 		}
// 		else {
// 			$io = $('<iframe name="' + id + '" src="'+ s.iframeSrc +'" />');
// 			$io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
// 		}
// 		io = $io[0];
// 
// 
// 		xhr = { // mock object
// 			aborted: 0,
// 			responseText: null,
// 			responseXML: null,
// 			status: 0,
// 			statusText: 'n/a',
// 			getAllResponseHeaders: function() {},
// 			getResponseHeader: function() {},
// 			setRequestHeader: function() {},
// 			abort: function(status) {
// 				var e = (status === 'timeout' ? 'timeout' : 'aborted');
// 				log('aborting upload... ' + e);
// 				this.aborted = 1;
// 				$io.attr('src', s.iframeSrc); // abort op in progress
// 				xhr.error = e;
// 				s.error && s.error.call(s.context, xhr, e, e);
// 				g && $.event.trigger("ajaxError", [xhr, s, e]);
// 				s.complete && s.complete.call(s.context, xhr, e);
// 			}
// 		};
// 
// 		g = s.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, s]);
// 		}
// 
// 		if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
// 			if (s.global) {
// 				$.active--;
// 			}
// 			return;
// 		}
// 		if (xhr.aborted) {
// 			return;
// 		}
// 
// 		// add submitting element to data if we know it
// 		sub = form.clk;
// 		if (sub) {
// 			n = sub.name;
// 			if (n && !sub.disabled) {
// 				s.extraData = s.extraData || {};
// 				s.extraData[n] = sub.value;
// 				if (sub.type == "image") {
// 					s.extraData[n+'.x'] = form.clk_x;
// 					s.extraData[n+'.y'] = form.clk_y;
// 				}
// 			}
// 		}
// 
// 		// take a breath so that pending repaints get some cpu time before the upload starts
// 		function doSubmit() {
// 			// make sure form attrs are set
// 			var t = $form.attr('target'), a = $form.attr('action');
// 
// 			// update form attrs in IE friendly way
// 			form.setAttribute('target',id);
// 			if (form.getAttribute('method') != 'POST') {
// 				form.setAttribute('method', 'POST');
// 			}
// 			if (form.getAttribute('action') != s.url) {
// 				form.setAttribute('action', s.url);
// 			}
// 
// 			// ie borks in some cases when setting encoding
// 			if (! s.skipEncodingOverride) {
// 				$form.attr({
// 					encoding: 'multipart/form-data',
// 					enctype:  'multipart/form-data'
// 				});
// 			}
// 
// 			// support timout
// 			if (s.timeout) {
// 				timeoutHandle = setTimeout(function() { timedOut = true; cb(true); }, s.timeout);
// 			}
// 
// 			// add "extra" data to form if provided in options
// 			var extraInputs = [];
// 			try {
// 				if (s.extraData) {
// 					for (var n in s.extraData) {
// 						extraInputs.push(
// 							$('<input type="hidden" name="'+n+'" value="'+s.extraData[n]+'" />')
// 								.appendTo(form)[0]);
// 					}
// 				}
// 
// 				if (!s.iframeTarget) {
// 					// 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.setAttribute('action',a);
// 				if(t) {
// 					form.setAttribute('target', t);
// 				} else {
// 					$form.removeAttr('target');
// 				}
// 				$(extraInputs).remove();
// 			}
// 		}
// 
// 		if (s.forceSync) {
// 			doSubmit();
// 		}
// 		else {
// 			setTimeout(doSubmit, 10); // this lets dom updates render
// 		}
// 
// 		var data, doc, domCheckCount = 50, callbackProcessed;
// 
// 		function cb(e) {
// 			if (xhr.aborted || callbackProcessed) {
// 				return;
// 			}
// 			if (e === true && xhr) {
// 				xhr.abort('timeout');
// 				return;
// 			}
// 
// 			var doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;
// 			if (!doc || doc.location.href == s.iframeSrc) {
// 				// response not received yet
// 				if (!timedOut)
// 					return;
// 			}
//             io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false);
// 
// 			var status = 'success', errMsg;
// 			try {
// 				if (timedOut) {
// 					throw 'timeout';
// 				}
// 
// 				var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
// 				log('isXml='+isXml);
// 				if (!isXml && window.opera && (doc.body == null || doc.body.innerHTML == '')) {
// 					if (--domCheckCount) {
// 						// in some browsers (Opera) the iframe DOM is not always traversable when
// 						// the onload callback fires, so we loop a bit to accommodate
// 						log('requeing onLoad callback, DOM not available');
// 						setTimeout(cb, 250);
// 						return;
// 					}
// 					// let this fall through because server response could be an empty document
// 					//log('Could not access iframe DOM after mutiple tries.');
// 					//throw 'DOMException: not available';
// 				}
// 
// 				//log('response detected');
//                 var docRoot = doc.body ? doc.body : doc.documentElement;
//                 xhr.responseText = docRoot ? docRoot.innerHTML : null;
// 				xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
// 				if (isXml)
// 					s.dataType = 'xml';
// 				xhr.getResponseHeader = function(header){
// 					var headers = {'content-type': s.dataType};
// 					return headers[header];
// 				};
//                 // support for XHR 'status' & 'statusText' emulation :
//                 if (docRoot) {
//                     xhr.status = Number( docRoot.getAttribute('status') ) || xhr.status;
//                     xhr.statusText = docRoot.getAttribute('statusText') || xhr.statusText;
//                 }
// 
// 				var scr = /(json|script|text)/.test(s.dataType.toLowerCase());
// 				if (scr || s.textarea) {
// 					// see if user embedded response in textarea
// 					var ta = doc.getElementsByTagName('textarea')[0];
// 					if (ta) {
// 						xhr.responseText = ta.value;
//                         // support for XHR 'status' & 'statusText' emulation :
//                         xhr.status = Number( ta.getAttribute('status') ) || xhr.status;
//                         xhr.statusText = ta.getAttribute('statusText') || xhr.statusText;
// 					}
// 					else if (scr) {
// 						// account for browsers injecting pre around json response
// 						var pre = doc.getElementsByTagName('pre')[0];
// 						var b = doc.getElementsByTagName('body')[0];
// 						if (pre) {
// 							xhr.responseText = pre.textContent ? pre.textContent : pre.innerHTML;
// 						}
// 						else if (b) {
// 							xhr.responseText = b.innerHTML;
// 						}
// 					}
// 				}
// 				else if (s.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) {
// 					xhr.responseXML = toXml(xhr.responseText);
// 				}
// 
//                 try {
//                     data = httpData(xhr, s.dataType, s);
//                 }
//                 catch (e) {
//                     status = 'parsererror';
//                     xhr.error = errMsg = (e || status);
//                 }
// 			}
// 			catch (e) {
// 				log('error caught',e);
// 				status = 'error';
//                 xhr.error = errMsg = (e || status);
// 			}
// 
// 			if (xhr.aborted) {
// 				log('upload aborted');
// 				status = null;
// 			}
// 
//             if (xhr.status) { // we've set xhr.status
//                 status = (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) ? 'success' : 'error';
//             }
// 
// 			// ordering of these callbacks/triggers is odd, but that's how $.ajax does it
// 			if (status === 'success') {
// 				s.success && s.success.call(s.context, data, 'success', xhr);
// 				g && $.event.trigger("ajaxSuccess", [xhr, s]);
// 			}
//             else if (status) {
// 				if (errMsg == undefined)
// 					errMsg = xhr.statusText;
// 				s.error && s.error.call(s.context, xhr, status, errMsg);
// 				g && $.event.trigger("ajaxError", [xhr, s, errMsg]);
//             }
// 
// 			g && $.event.trigger("ajaxComplete", [xhr, s]);
// 
// 			if (g && ! --$.active) {
// 				$.event.trigger("ajaxStop");
// 			}
// 
// 			s.complete && s.complete.call(s.context, xhr, status);
// 
// 			callbackProcessed = true;
// 			if (s.timeout)
// 				clearTimeout(timeoutHandle);
// 
// 			// clean up
// 			setTimeout(function() {
// 				if (!s.iframeTarget)
// 					$io.remove();
// 				xhr.responseXML = null;
// 			}, 100);
// 		}
// 
// 		var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+)
// 			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.nodeName != 'parsererror') ? doc : null;
// 		};
// 		var parseJSON = $.parseJSON || function(s) {
// 			return window['eval']('(' + s + ')');
// 		};
// 
// 		var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4
// 
// 			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') {
// 				$.error && $.error('parsererror');
// 			}
// 			if (s && s.dataFilter) {
// 				data = s.dataFilter(data, type);
// 			}
// 			if (typeof data === 'string') {
// 				if (type === 'json' || !type && ct.indexOf('json') >= 0) {
// 					data = parseJSON(data);
// 				} else if (type === "script" || !type && ct.indexOf("javascript") >= 0) {
// 					$.globalEval(data);
// 				}
// 			}
// 			return data;
// 		};
// 	}
// };
// 
// /**
//  * ajaxForm() provides a mechanism for fully automating form submission.
//  *
//  * The advantages of using this method instead of ajaxSubmit() are:
//  *
//  * 1: This method will include coordinates for <input type="image" /> elements (if the element
//  *	is used to submit the form).
//  * 2. This method will include the submit element's name/value data (for the element that was
//  *	used to submit the form).
//  * 3. This method binds the submit() method to the form for you.
//  *
//  * The options argument for ajaxForm works exactly as it does for ajaxSubmit.  ajaxForm merely
//  * passes the options argument along after properly binding events for submit elements and
//  * the form itself.
//  */
// $.fn.ajaxForm = function(options) {
// 	// in jQuery 1.3+ we can fix mistakes with the ready state
// 	if (this.length === 0) {
// 		var o = { s: this.selector, c: this.context };
// 		if (!$.isReady && o.s) {
// 			log('DOM not ready, queuing ajaxForm');
// 			$(function() {
// 				$(o.s,o.c).ajaxForm(options);
// 			});
// 			return this;
// 		}
// 		// is your DOM ready?  http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
// 		log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
// 		return this;
// 	}
// 
// 	return this.ajaxFormUnbind().bind('submit.form-plugin', function(e) {
// 		if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
// 			e.preventDefault();
// 			$(this).ajaxSubmit(options);
// 		}
// 	}).bind('click.form-plugin', function(e) {
// 		var target = e.target;
// 		var $el = $(target);
// 		if (!($el.is(":submit,input:image"))) {
// 			// is this a child element of the submit el?  (ex: a span within a button)
// 			var t = $el.closest(':submit');
// 			if (t.length == 0) {
// 				return;
// 			}
// 			target = t[0];
// 		}
// 		var form = this;
// 		form.clk = target;
// 		if (target.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 = $el.offset();
// 				form.clk_x = e.pageX - offset.left;
// 				form.clk_y = e.pageY - offset.top;
// 			} else {
// 				form.clk_x = e.pageX - target.offsetLeft;
// 				form.clk_y = e.pageY - target.offsetTop;
// 			}
// 		}
// 		// clear form vars
// 		setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
// 	});
// };
// 
// // ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
// $.fn.ajaxFormUnbind = function() {
// 	return this.unbind('submit.form-plugin click.form-plugin');
// };
// 
// /**
//  * formToArray() gathers form element data into an array of objects that can
//  * be passed to any of the following ajax functions: $.get, $.post, or load.
//  * Each object in the array has both a 'name' and 'value' property.  An example of
//  * an array for a simple login form might be:
//  *
//  * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
//  *
//  * It is this array that is passed to pre-submit callback functions provided to the
//  * ajaxSubmit() and ajaxForm() methods.
//  */
// $.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;
// 	}
// 
// 	var i,j,n,v,el,max,jmax;
// 	for(i=0, max=els.length; i < max; i++) {
// 		el = els[i];
// 		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, value: $(el).val()});
// 				a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
// 			}
// 			continue;
// 		}
// 
// 		v = $.fieldValue(el, true);
// 		if (v && v.constructor == Array) {
// 			for(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 it here
// 		var $input = $(form.clk), input = $input[0];
// 		n = input.name;
// 		if (n && !input.disabled && input.type == 'image') {
// 			a.push({name: n, value: $input.val()});
// 			a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
// 		}
// 	}
// 	return a;
// };
// 
// /**
//  * Serializes form data into a 'submittable' string. This method will return a string
//  * in the format: name1=value1&amp;name2=value2
//  */
// $.fn.formSerialize = function(semantic) {
// 	//hand off to jQuery.param for proper encoding
// 	return $.param(this.formToArray(semantic));
// };
// 
// /**
//  * Serializes all field elements in the jQuery object into a query string.
//  * This method will return a string in the format: name1=value1&amp;name2=value2
//  */
// $.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);
// };
// 
// /**
//  * Returns the value(s) of the element in the matched set.  For example, consider the following form:
//  *
//  *  <form><fieldset>
//  *	  <input name="A" type="text" />
//  *	  <input name="A" type="text" />
//  *	  <input name="B" type="checkbox" value="B1" />
//  *	  <input name="B" type="checkbox" value="B2"/>
//  *	  <input name="C" type="radio" value="C1" />
//  *	  <input name="C" type="radio" value="C2" />
//  *  </fieldset></form>
//  *
//  *  var v = $(':text').fieldValue();
//  *  // if no values are entered into the text inputs
//  *  v == ['','']
//  *  // if values entered into the text inputs are 'foo' and 'bar'
//  *  v == ['foo','bar']
//  *
//  *  var v = $(':checkbox').fieldValue();
//  *  // if neither checkbox is checked
//  *  v === undefined
//  *  // if both checkboxes are checked
//  *  v == ['B1', 'B2']
//  *
//  *  var v = $(':radio').fieldValue();
//  *  // if neither radio is checked
//  *  v === undefined
//  *  // if first radio is checked
//  *  v == ['C1']
//  *
//  * The successful argument controls whether or not the field element must be 'successful'
//  * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
//  * The default value of the successful argument is true.  If this value is false the value(s)
//  * for each element is returned.
//  *
//  * Note: This method *always* returns an array.  If no valid value can be determined the
//  *	   array will be empty, otherwise it will contain one or more values.
//  */
// $.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;
// };
// 
// /**
//  * Returns the value of the field element.
//  */
// $.fieldValue = function(el, successful) {
// 	var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
// 	if (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) {
// 				var v = op.value;
// 				if (!v) { // extra pain for IE...
// 					v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
// 				}
// 				if (one) {
// 					return v;
// 				}
// 				a.push(v);
// 			}
// 		}
// 		return a;
// 	}
// 	return $(el).val();
// };
// 
// /**
//  * Clears the form data.  Takes the following actions on the form's input fields:
//  *  - input text fields will have their 'value' property set to the empty string
//  *  - select elements will have their 'selectedIndex' property set to -1
//  *  - checkbox and radio inputs will have their 'checked' property set to false
//  *  - inputs of type submit, button, reset, and hidden will *not* be effected
//  *  - button elements will *not* be effected
//  */
// $.fn.clearForm = function() {
// 	return this.each(function() {
// 		$('input,select,textarea', this).clearFields();
// 	});
// };
// 
// /**
//  * Clears the selected form elements.
//  */
// $.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;
// 		}
// 	});
// };
// 
// /**
//  * Resets the form data.  Causes all form elements to be reset to their original value.
//  */
// $.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();
// 		}
// 	});
// };
// 
// /**
//  * Enables or disables any matching elements.
//  */
// $.fn.enable = function(b) {
// 	if (b === undefined) {
// 		b = true;
// 	}
// 	return this.each(function() {
// 		this.disabled = !b;
// 	});
// };
// 
// /**
//  * Checks/unchecks any matching checkboxes or radio buttons and
//  * selects/deselects and matching option elements.
//  */
// $.fn.selected = 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').selected(false);
// 			}
// 			this.selected = select;
// 		}
// 	});
// };
// 
// // helper fn for console logging
// // set $.fn.ajaxSubmit.debug to true to enable debug logging
// function log() {
// 	if ($.fn.ajaxSubmit.debug) {
// 		var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
// 		if (window.console && window.console.log) {
// 			window.console.log(msg);
// 		}
// 		else if (window.opera && window.opera.postError) {
// 			window.opera.postError(msg);
// 		}
// 	}
// };
// 
// })(jQuery);

