/*!
 * jQuery JavaScript Library v1.3.1
 * http://jquery.com/
 *
 * Copyright (c) 2009 John Resig
 * Dual licensed under the MIT and GPL licenses.
 * http://docs.jquery.com/License
 *
 * Date: 2009-01-21 20:42:16 -0500 (Wed, 21 Jan 2009)
 * Revision: 6158
 */
(function(){

var 
	// Will speed up references to window, and allows munging its name.
	window = this,
	// Will speed up references to undefined, and allows munging its name.
	undefined,
	// Map over jQuery in case of overwrite
	_jQuery = window.jQuery,
	// Map over the $ in case of overwrite
	_$ = window.$,

	jQuery = window.jQuery = window.$ = function( selector, context ) {
		// The jQuery object is actually just the init constructor 'enhanced'
		return new jQuery.fn.init( selector, context );
	},

	// A simple way to check for HTML strings or ID strings
	// (both of which we optimize for)
	quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,
	// Is it a simple selector
	isSimple = /^.[^:#\[\.,]*$/;

jQuery.fn = jQuery.prototype = {
	init: function( selector, context ) {
		// Make sure that a selection was provided
		selector = selector || document;

		// Handle $(DOMElement)
		if ( selector.nodeType ) {
			this[0] = selector;
			this.length = 1;
			this.context = selector;
			return this;
		}
		// Handle HTML strings
		if ( typeof selector === "string" ) {
			// Are we dealing with HTML string or an ID?
			var match = quickExpr.exec( selector );

			// Verify a match, and that no context was specified for #id
			if ( match && (match[1] || !context) ) {

				// HANDLE: $(html) -> $(array)
				if ( match[1] )
					selector = jQuery.clean( [ match[1] ], context );

				// HANDLE: $("#id")
				else {
					var elem = document.getElementById( match[3] );

					// Handle the case where IE and Opera return items
					// by name instead of ID
					if ( elem && elem.id != match[3] )
						return jQuery().find( selector );

					// Otherwise, we inject the element directly into the jQuery object
					var ret = jQuery( elem || [] );
					ret.context = document;
					ret.selector = selector;
					return ret;
				}

			// HANDLE: $(expr, [context])
			// (which is just equivalent to: $(content).find(expr)
			} else
				return jQuery( context ).find( selector );

		// HANDLE: $(function)
		// Shortcut for document ready
		} else if ( jQuery.isFunction( selector ) )
			return jQuery( document ).ready( selector );

		// Make sure that old selector state is passed along
		if ( selector.selector && selector.context ) {
			this.selector = selector.selector;
			this.context = selector.context;
		}

		return this.setArray(jQuery.makeArray(selector));
	},

	// Start with an empty selector
	selector: "",

	// The current version of jQuery being used
	jquery: "1.3.1",

	// The number of elements contained in the matched element set
	size: function() {
		return this.length;
	},

	// Get the Nth element in the matched element set OR
	// Get the whole matched element set as a clean array
	get: function( num ) {
		return num === undefined ?

			// Return a 'clean' array
			jQuery.makeArray( this ) :

			// Return just the object
			this[ num ];
	},

	// Take an array of elements and push it onto the stack
	// (returning the new matched element set)
	pushStack: function( elems, name, selector ) {
		// Build a new jQuery matched element set
		var ret = jQuery( elems );

		// Add the old object onto the stack (as a reference)
		ret.prevObject = this;

		ret.context = this.context;

		if ( name === "find" )
			ret.selector = this.selector + (this.selector ? " " : "") + selector;
		else if ( name )
			ret.selector = this.selector + "." + name + "(" + selector + ")";

		// Return the newly-formed element set
		return ret;
	},

	// Force the current matched set of elements to become
	// the specified array of elements (destroying the stack in the process)
	// You should use pushStack() in order to do this, but maintain the stack
	setArray: function( elems ) {
		// Resetting the length to 0, then using the native Array push
		// is a super-fast way to populate an object with array-like properties
		this.length = 0;
		Array.prototype.push.apply( this, elems );

		return this;
	},

	// Execute a callback for every element in the matched set.
	// (You can seed the arguments with an array of args, but this is
	// only used internally.)
	each: function( callback, args ) {
		return jQuery.each( this, callback, args );
	},

	// Determine the position of an element within
	// the matched set of elements
	index: function( elem ) {
		// Locate the position of the desired element
		return jQuery.inArray(
			// If it receives a jQuery object, the first element is used
			elem && elem.jquery ? elem[0] : elem
		, this );
	},

	attr: function( name, value, type ) {
		var options = name;

		// Look for the case where we're accessing a style value
		if ( typeof name === "string" )
			if ( value === undefined )
				return this[0] && jQuery[ type || "attr" ]( this[0], name );

			else {
				options = {};
				options[ name ] = value;
			}

		// Check to see if we're setting style values
		return this.each(function(i){
			// Set all the styles
			for ( name in options )
				jQuery.attr(
					type ?
						this.style :
						this,
					name, jQuery.prop( this, options[ name ], type, i, name )
				);
		});
	},

	css: function( key, value ) {
		// ignore negative width and height values
		if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
			value = undefined;
		return this.attr( key, value, "curCSS" );
	},

	text: function( text ) {
		if ( typeof text !== "object" && text != null )
			return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );

		var ret = "";

		jQuery.each( text || this, function(){
			jQuery.each( this.childNodes, function(){
				if ( this.nodeType != 8 )
					ret += this.nodeType != 1 ?
						this.nodeValue :
						jQuery.fn.text( [ this ] );
			});
		});

		return ret;
	},

	wrapAll: function( html ) {
		if ( this[0] ) {
			// The elements to wrap the target around
			var wrap = jQuery( html, this[0].ownerDocument ).clone();

			if ( this[0].parentNode )
				wrap.insertBefore( this[0] );

			wrap.map(function(){
				var elem = this;

				while ( elem.firstChild )
					elem = elem.firstChild;

				return elem;
			}).append(this);
		}

		return this;
	},

	wrapInner: function( html ) {
		return this.each(function(){
			jQuery( this ).contents().wrapAll( html );
		});
	},

	wrap: function( html ) {
		return this.each(function(){
			jQuery( this ).wrapAll( html );
		});
	},

	append: function() {
		return this.domManip(arguments, true, function(elem){
			if (this.nodeType == 1)
				this.appendChild( elem );
		});
	},

	prepend: function() {
		return this.domManip(arguments, true, function(elem){
			if (this.nodeType == 1)
				this.insertBefore( elem, this.firstChild );
		});
	},

	before: function() {
		return this.domManip(arguments, false, function(elem){
			this.parentNode.insertBefore( elem, this );
		});
	},

	after: function() {
		return this.domManip(arguments, false, function(elem){
			this.parentNode.insertBefore( elem, this.nextSibling );
		});
	},

	end: function() {
		return this.prevObject || jQuery( [] );
	},

	// For internal use only.
	// Behaves like an Array's .push method, not like a jQuery method.
	push: [].push,

	find: function( selector ) {
		if ( this.length === 1 && !/,/.test(selector) ) {
			var ret = this.pushStack( [], "find", selector );
			ret.length = 0;
			jQuery.find( selector, this[0], ret );
			return ret;
		} else {
			var elems = jQuery.map(this, function(elem){
				return jQuery.find( selector, elem );
			});

			return this.pushStack( /[^+>] [^+>]/.test( selector ) ?
				jQuery.unique( elems ) :
				elems, "find", selector );
		}
	},

	clone: function( events ) {
		// Do the clone
		var ret = this.map(function(){
			if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
				// IE copies events bound via attachEvent when
				// using cloneNode. Calling detachEvent on the
				// clone will also remove the events from the orignal
				// In order to get around this, we use innerHTML.
				// Unfortunately, this means some modifications to
				// attributes in IE that are actually only stored
				// as properties will not be copied (such as the
				// the name attribute on an input).
				var clone = this.cloneNode(true),
					container = document.createElement("div");
				container.appendChild(clone);
				return jQuery.clean([container.innerHTML])[0];
			} else
				return this.cloneNode(true);
		});

		// Need to set the expando to null on the cloned set if it exists
		// removeData doesn't work here, IE removes it from the original as well
		// this is primarily for IE but the data expando shouldn't be copied over in any browser
		var clone = ret.find("*").andSelf().each(function(){
			if ( this[ expando ] !== undefined )
				this[ expando ] = null;
		});

		// Copy the events from the original to the clone
		if ( events === true )
			this.find("*").andSelf().each(function(i){
				if (this.nodeType == 3)
					return;
				var events = jQuery.data( this, "events" );

				for ( var type in events )
					for ( var handler in events[ type ] )
						jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data );
			});

		// Return the cloned set
		return ret;
	},

	filter: function( selector ) {
		return this.pushStack(
			jQuery.isFunction( selector ) &&
			jQuery.grep(this, function(elem, i){
				return selector.call( elem, i );
			}) ||

			jQuery.multiFilter( selector, jQuery.grep(this, function(elem){
				return elem.nodeType === 1;
			}) ), "filter", selector );
	},

	closest: function( selector ) {
		var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null;

		return this.map(function(){
			var cur = this;
			while ( cur && cur.ownerDocument ) {
				if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) )
					return cur;
				cur = cur.parentNode;
			}
		});
	},

	not: function( selector ) {
		if ( typeof selector === "string" )
			// test special case where just one selector is passed in
			if ( isSimple.test( selector ) )
				return this.pushStack( jQuery.multiFilter( selector, this, true ), "not", selector );
			else
				selector = jQuery.multiFilter( selector, this );

		var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
		return this.filter(function() {
			return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
		});
	},

	add: function( selector ) {
		return this.pushStack( jQuery.unique( jQuery.merge(
			this.get(),
			typeof selector === "string" ?
				jQuery( selector ) :
				jQuery.makeArray( selector )
		)));
	},

	is: function( selector ) {
		return !!selector && jQuery.multiFilter( selector, this ).length > 0;
	},

	hasClass: function( selector ) {
		return !!selector && this.is( "." + selector );
	},

	val: function( value ) {
		if ( value === undefined ) {			
			var elem = this[0];

			if ( elem ) {
				if( jQuery.nodeName( elem, 'option' ) )
					return (elem.attributes.value || {}).specified ? elem.value : elem.text;
				
				// We need to handle select boxes special
				if ( jQuery.nodeName( elem, "select" ) ) {
					var index = elem.selectedIndex,
						values = [],
						options = elem.options,
						one = elem.type == "select-one";

					// Nothing was selected
					if ( index < 0 )
						return null;

					// Loop through all the selected options
					for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
						var option = options[ i ];

						if ( option.selected ) {
							// Get the specifc value for the option
							value = jQuery(option).val();

							// We don't need an array for one selects
							if ( one )
								return value;

							// Multi-Selects return an array
							values.push( value );
						}
					}

					return values;				
				}

				// Everything else, we just grab the value
				return (elem.value || "").replace(/\r/g, "");

			}

			return undefined;
		}

		if ( typeof value === "number" )
			value += '';

		return this.each(function(){
			if ( this.nodeType != 1 )
				return;

			if ( jQuery.isArray(value) && /radio|checkbox/.test( this.type ) )
				this.checked = (jQuery.inArray(this.value, value) >= 0 ||
					jQuery.inArray(this.name, value) >= 0);

			else if ( jQuery.nodeName( this, "select" ) ) {
				var values = jQuery.makeArray(value);

				jQuery( "option", this ).each(function(){
					this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
						jQuery.inArray( this.text, values ) >= 0);
				});

				if ( !values.length )
					this.selectedIndex = -1;

			} else
				this.value = value;
		});
	},

	html: function( value ) {
		return value === undefined ?
			(this[0] ?
				this[0].innerHTML :
				null) :
			this.empty().append( value );
	},

	replaceWith: function( value ) {
		return this.after( value ).remove();
	},

	eq: function( i ) {
		return this.slice( i, +i + 1 );
	},

	slice: function() {
		return this.pushStack( Array.prototype.slice.apply( this, arguments ),
			"slice", Array.prototype.slice.call(arguments).join(",") );
	},

	map: function( callback ) {
		return this.pushStack( jQuery.map(this, function(elem, i){
			return callback.call( elem, i, elem );
		}));
	},

	andSelf: function() {
		return this.add( this.prevObject );
	},

	domManip: function( args, table, callback ) {
		if ( this[0] ) {
			var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(),
				scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ),
				first = fragment.firstChild,
				extra = this.length > 1 ? fragment.cloneNode(true) : fragment;

			if ( first )
				for ( var i = 0, l = this.length; i < l; i++ )
					callback.call( root(this[i], first), i > 0 ? extra.cloneNode(true) : fragment );
			
			if ( scripts )
				jQuery.each( scripts, evalScript );
		}

		return this;
		
		function root( elem, cur ) {
			return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ?
				(elem.getElementsByTagName("tbody")[0] ||
				elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
				elem;
		}
	}
};

// Give the init function the jQuery prototype for later instantiation
jQuery.fn.init.prototype = jQuery.fn;

function evalScript( i, elem ) {
	if ( elem.src )
		jQuery.ajax({
			url: elem.src,
			async: false,
			dataType: "script"
		});

	else
		jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );

	if ( elem.parentNode )
		elem.parentNode.removeChild( elem );
}

function now(){
	return +new Date;
}

jQuery.extend = jQuery.fn.extend = function() {
	// copy reference to target object
	var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;

	// Handle a deep copy situation
	if ( typeof target === "boolean" ) {
		deep = target;
		target = arguments[1] || {};
		// skip the boolean and the target
		i = 2;
	}

	// Handle case when target is a string or something (possible in deep copy)
	if ( typeof target !== "object" && !jQuery.isFunction(target) )
		target = {};

	// extend jQuery itself if only one argument is passed
	if ( length == i ) {
		target = this;
		--i;
	}

	for ( ; i < length; i++ )
		// Only deal with non-null/undefined values
		if ( (options = arguments[ i ]) != null )
			// Extend the base object
			for ( var name in options ) {
				var src = target[ name ], copy = options[ name ];

				// Prevent never-ending loop
				if ( target === copy )
					continue;

				// Recurse if we're merging object values
				if ( deep && copy && typeof copy === "object" && !copy.nodeType )
					target[ name ] = jQuery.extend( deep, 
						// Never move original objects, clone them
						src || ( copy.length != null ? [ ] : { } )
					, copy );

				// Don't bring in undefined values
				else if ( copy !== undefined )
					target[ name ] = copy;

			}

	// Return the modified object
	return target;
};

// exclude the following css properties to add px
var	exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
	// cache defaultView
	defaultView = document.defaultView || {},
	toString = Object.prototype.toString;

jQuery.extend({
	noConflict: function( deep ) {
		window.$ = _$;

		if ( deep )
			window.jQuery = _jQuery;

		return jQuery;
	},

	// See test/unit/core.js for details concerning isFunction.
	// Since version 1.3, DOM methods and functions like alert
	// aren't supported. They return false on IE (#2968).
	isFunction: function( obj ) {
		return toString.call(obj) === "[object Function]";
	},

	isArray: function( obj ) {
		return toString.call(obj) === "[object Array]";
	},

	// check if an element is in a (or is an) XML document
	isXMLDoc: function( elem ) {
		return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
			!!elem.ownerDocument && jQuery.isXMLDoc( elem.ownerDocument );
	},

	// Evalulates a script in a global context
	globalEval: function( data ) {
		data = jQuery.trim( data );

		if ( data ) {
			// Inspired by code by Andrea Giammarchi
			// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
			var head = document.getElementsByTagName("head")[0] || document.documentElement,
				script = document.createElement("script");

			script.type = "text/javascript";
			if ( jQuery.support.scriptEval )
				script.appendChild( document.createTextNode( data ) );
			else
				script.text = data;

			// Use insertBefore instead of appendChild  to circumvent an IE6 bug.
			// This arises when a base node is used (#2709).
			head.insertBefore( script, head.firstChild );
			head.removeChild( script );
		}
	},

	nodeName: function( elem, name ) {
		return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
	},

	// args is for internal usage only
	each: function( object, callback, args ) {
		var name, i = 0, length = object.length;

		if ( args ) {
			if ( length === undefined ) {
				for ( name in object )
					if ( callback.apply( object[ name ], args ) === false )
						break;
			} else
				for ( ; i < length; )
					if ( callback.apply( object[ i++ ], args ) === false )
						break;

		// A special, fast, case for the most common use of each
		} else {
			if ( length === undefined ) {
				for ( name in object )
					if ( callback.call( object[ name ], name, object[ name ] ) === false )
						break;
			} else
				for ( var value = object[0];
					i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
		}

		return object;
	},

	prop: function( elem, value, type, i, name ) {
		// Handle executable functions
		if ( jQuery.isFunction( value ) )
			value = value.call( elem, i );

		// Handle passing in a number to a CSS property
		return typeof value === "number" && type == "curCSS" && !exclude.test( name ) ?
			value + "px" :
			value;
	},

	className: {
		// internal only, use addClass("class")
		add: function( elem, classNames ) {
			jQuery.each((classNames || "").split(/\s+/), function(i, className){
				if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
					elem.className += (elem.className ? " " : "") + className;
			});
		},

		// internal only, use removeClass("class")
		remove: function( elem, classNames ) {
			if (elem.nodeType == 1)
				elem.className = classNames !== undefined ?
					jQuery.grep(elem.className.split(/\s+/), function(className){
						return !jQuery.className.has( classNames, className );
					}).join(" ") :
					"";
		},

		// internal only, use hasClass("class")
		has: function( elem, className ) {
			return elem && jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
		}
	},

	// A method for quickly swapping in/out CSS properties to get correct calculations
	swap: function( elem, options, callback ) {
		var old = {};
		// Remember the old values, and insert the new ones
		for ( var name in options ) {
			old[ name ] = elem.style[ name ];
			elem.style[ name ] = options[ name ];
		}

		callback.call( elem );

		// Revert the old values
		for ( var name in options )
			elem.style[ name ] = old[ name ];
	},

	css: function( elem, name, force ) {
		if ( name == "width" || name == "height" ) {
			var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];

			function getWH() {
				val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
				var padding = 0, border = 0;
				jQuery.each( which, function() {
					padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
					border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
				});
				val -= Math.round(padding + border);
			}

			if ( jQuery(elem).is(":visible") )
				getWH();
			else
				jQuery.swap( elem, props, getWH );

			return Math.max(0, val);
		}

		return jQuery.curCSS( elem, name, force );
	},

	curCSS: function( elem, name, force ) {
		var ret, style = elem.style;

		// We need to handle opacity special in IE
		if ( name == "opacity" && !jQuery.support.opacity ) {
			ret = jQuery.attr( style, "opacity" );

			return ret == "" ?
				"1" :
				ret;
		}

		// Make sure we're using the right name for getting the float value
		if ( name.match( /float/i ) )
			name = styleFloat;

		if ( !force && style && style[ name ] )
			ret = style[ name ];

		else if ( defaultView.getComputedStyle ) {

			// Only "float" is needed here
			if ( name.match( /float/i ) )
				name = "float";

			name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();

			var computedStyle = defaultView.getComputedStyle( elem, null );

			if ( computedStyle )
				ret = computedStyle.getPropertyValue( name );

			// We should always get a number back from opacity
			if ( name == "opacity" && ret == "" )
				ret = "1";

		} else if ( elem.currentStyle ) {
			var camelCase = name.replace(/\-(\w)/g, function(all, letter){
				return letter.toUpperCase();
			});

			ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];

			// From the awesome hack by Dean Edwards
			// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291

			// If we're not dealing with a regular pixel number
			// but a number that has a weird ending, we need to convert it to pixels
			if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
				// Remember the original values
				var left = style.left, rsLeft = elem.runtimeStyle.left;

				// Put in the new values to get a computed value out
				elem.runtimeStyle.left = elem.currentStyle.left;
				style.left = ret || 0;
				ret = style.pixelLeft + "px";

				// Revert the changed values
				style.left = left;
				elem.runtimeStyle.left = rsLeft;
			}
		}

		return ret;
	},

	clean: function( elems, context, fragment ) {
		context = context || document;

		// !context.createElement fails in IE with an error but returns typeof 'object'
		if ( typeof context.createElement === "undefined" )
			context = context.ownerDocument || context[0] && context[0].ownerDocument || document;

		// If a single string is passed in and it's a single tag
		// just do a createElement and skip the rest
		if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) {
			var match = /^<(\w+)\s*\/?>$/.exec(elems[0]);
			if ( match )
				return [ context.createElement( match[1] ) ];
		}

		var ret = [], scripts = [], div = context.createElement("div");

		jQuery.each(elems, function(i, elem){
			if ( typeof elem === "number" )
				elem += '';

			if ( !elem )
				return;

			// Convert html string into DOM nodes
			if ( typeof elem === "string" ) {
				// Fix "XHTML"-style tags in all browsers
				elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
					return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
						all :
						front + "></" + tag + ">";
				});

				// Trim whitespace, otherwise indexOf won't work as expected
				var tags = jQuery.trim( elem ).toLowerCase();

				var wrap =
					// option or optgroup
					!tags.indexOf("<opt") &&
					[ 1, "<select multiple='multiple'>", "</select>" ] ||

					!tags.indexOf("<leg") &&
					[ 1, "<fieldset>", "</fieldset>" ] ||

					tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
					[ 1, "<table>", "</table>" ] ||

					!tags.indexOf("<tr") &&
					[ 2, "<table><tbody>", "</tbody></table>" ] ||

				 	// <thead> matched above
					(!tags.indexOf("<td") || !tags.indexOf("<th")) &&
					[ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||

					!tags.indexOf("<col") &&
					[ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||

					// IE can't serialize <link> and <script> tags normally
					!jQuery.support.htmlSerialize &&
					[ 1, "div<div>", "</div>" ] ||

					[ 0, "", "" ];

				// Go to html and back, then peel off extra wrappers
				div.innerHTML = wrap[1] + elem + wrap[2];

				// Move to the right depth
				while ( wrap[0]-- )
					div = div.lastChild;

				// Remove IE's autoinserted <tbody> from table fragments
				if ( !jQuery.support.tbody ) {

					// String was a <table>, *may* have spurious <tbody>
					var tbody = !tags.indexOf("<table") && tags.indexOf("<tbody") < 0 ?
						div.firstChild && div.firstChild.childNodes :

						// String was a bare <thead> or <tfoot>
						wrap[1] == "<table>" && tags.indexOf("<tbody") < 0 ?
							div.childNodes :
							[];

					for ( var j = tbody.length - 1; j >= 0 ; --j )
						if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
							tbody[ j ].parentNode.removeChild( tbody[ j ] );

					}

				// IE completely kills leading whitespace when innerHTML is used
				if ( !jQuery.support.leadingWhitespace && /^\s/.test( elem ) )
					div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
				
				elem = jQuery.makeArray( div.childNodes );
			}

			if ( elem.nodeType )
				ret.push( elem );
			else
				ret = jQuery.merge( ret, elem );

		});

		if ( fragment ) {
			for ( var i = 0; ret[i]; i++ ) {
				if ( jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
					scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
				} else {
					if ( ret[i].nodeType === 1 )
						ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
					fragment.appendChild( ret[i] );
				}
			}
			
			return scripts;
		}

		return ret;
	},

	attr: function( elem, name, value ) {
		// don't set attributes on text and comment nodes
		if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
			return undefined;

		var notxml = !jQuery.isXMLDoc( elem ),
			// Whether we are setting (or getting)
			set = value !== undefined;

		// Try to normalize/fix the name
		name = notxml && jQuery.props[ name ] || name;

		// Only do all the following if this is a node (faster for style)
		// IE elem.getAttribute passes even for style
		if ( elem.tagName ) {

			// These attributes require special treatment
			var special = /href|src|style/.test( name );

			// Safari mis-reports the default selected property of a hidden option
			// Accessing the parent's selectedIndex property fixes it
			if ( name == "selected" && elem.parentNode )
				elem.parentNode.selectedIndex;

			// If applicable, access the attribute via the DOM 0 way
			if ( name in elem && notxml && !special ) {
				if ( set ){
					// We can't allow the type property to be changed (since it causes problems in IE)
					if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
						throw "type property can't be changed";

					elem[ name ] = value;
				}

				// browsers index elements by id/name on forms, give priority to attributes.
				if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) )
					return elem.getAttributeNode( name ).nodeValue;

				// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
				// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
				if ( name == "tabIndex" ) {
					var attributeNode = elem.getAttributeNode( "tabIndex" );
					return attributeNode && attributeNode.specified
						? attributeNode.value
						: elem.nodeName.match(/(button|input|object|select|textarea)/i)
							? 0
							: elem.nodeName.match(/^(a|area)$/i) && elem.href
								? 0
								: undefined;
				}

				return elem[ name ];
			}

			if ( !jQuery.support.style && notxml &&  name == "style" )
				return jQuery.attr( elem.style, "cssText", value );

			if ( set )
				// convert the value to a string (all browsers do this but IE) see #1070
				elem.setAttribute( name, "" + value );

			var attr = !jQuery.support.hrefNormalized && notxml && special
					// Some attributes require a special call on IE
					? elem.getAttribute( name, 2 )
					: elem.getAttribute( name );

			// Non-existent attributes return null, we normalize to undefined
			return attr === null ? undefined : attr;
		}

		// elem is actually elem.style ... set the style

		// IE uses filters for opacity
		if ( !jQuery.support.opacity && name == "opacity" ) {
			if ( set ) {
				// IE has trouble with opacity if it does not have layout
				// Force it by setting the zoom level
				elem.zoom = 1;

				// Set the alpha filter to set the opacity
				elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
					(parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
			}

			return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
				(parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '':
				"";
		}

		name = name.replace(/-([a-z])/ig, function(all, letter){
			return letter.toUpperCase();
		});

		if ( set )
			elem[ name ] = value;

		return elem[ name ];
	},

	trim: function( text ) {
		return (text || "").replace( /^\s+|\s+$/g, "" );
	},

	makeArray: function( array ) {
		var ret = [];

		if( array != null ){
			var i = array.length;
			// The window, strings (and functions) also have 'length'
			if( i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval )
				ret[0] = array;
			else
				while( i )
					ret[--i] = array[i];
		}

		return ret;
	},

	inArray: function( elem, array ) {
		for ( var i = 0, length = array.length; i < length; i++ )
		// Use === because on IE, window == document
			if ( array[ i ] === elem )
				return i;

		return -1;
	},

	merge: function( first, second ) {
		// We have to loop this way because IE & Opera overwrite the length
		// expando of getElementsByTagName
		var i = 0, elem, pos = first.length;
		// Also, we need to make sure that the correct elements are being returned
		// (IE returns comment nodes in a '*' query)
		if ( !jQuery.support.getAll ) {
			while ( (elem = second[ i++ ]) != null )
				if ( elem.nodeType != 8 )
					first[ pos++ ] = elem;

		} else
			while ( (elem = second[ i++ ]) != null )
				first[ pos++ ] = elem;

		return first;
	},

	unique: function( array ) {
		var ret = [], done = {};

		try {

			for ( var i = 0, length = array.length; i < length; i++ ) {
				var id = jQuery.data( array[ i ] );

				if ( !done[ id ] ) {
					done[ id ] = true;
					ret.push( array[ i ] );
				}
			}

		} catch( e ) {
			ret = array;
		}

		return ret;
	},

	grep: function( elems, callback, inv ) {
		var ret = [];

		// Go through the array, only saving the items
		// that pass the validator function
		for ( var i = 0, length = elems.length; i < length; i++ )
			if ( !inv != !callback( elems[ i ], i ) )
				ret.push( elems[ i ] );

		return ret;
	},

	map: function( elems, callback ) {
		var ret = [];

		// Go through the array, translating each of the items to their
		// new value (or values).
		for ( var i = 0, length = elems.length; i < length; i++ ) {
			var value = callback( elems[ i ], i );

			if ( value != null )
				ret[ ret.length ] = value;
		}

		return ret.concat.apply( [], ret );
	}
});

// Use of jQuery.browser is deprecated.
// It's included for backwards compatibility and plugins,
// although they should work to migrate away.

var userAgent = navigator.userAgent.toLowerCase();

// Figure out what browser is being used
jQuery.browser = {
	version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
	safari: /webkit/.test( userAgent ),
	opera: /opera/.test( userAgent ),
	msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
	mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
};

jQuery.each({
	parent: function(elem){return elem.parentNode;},
	parents: function(elem){return jQuery.dir(elem,"parentNode");},
	next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
	prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
	nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
	prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
	siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
	children: function(elem){return jQuery.sibling(elem.firstChild);},
	contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
}, function(name, fn){
	jQuery.fn[ name ] = function( selector ) {
		var ret = jQuery.map( this, fn );

		if ( selector && typeof selector == "string" )
			ret = jQuery.multiFilter( selector, ret );

		return this.pushStack( jQuery.unique( ret ), name, selector );
	};
});

jQuery.each({
	appendTo: "append",
	prependTo: "prepend",
	insertBefore: "before",
	insertAfter: "after",
	replaceAll: "replaceWith"
}, function(name, original){
	jQuery.fn[ name ] = function() {
		var args = arguments;

		return this.each(function(){
			for ( var i = 0, length = args.length; i < length; i++ )
				jQuery( args[ i ] )[ original ]( this );
		});
	};
});

jQuery.each({
	removeAttr: function( name ) {
		jQuery.attr( this, name, "" );
		if (this.nodeType == 1)
			this.removeAttribute( name );
	},

	addClass: function( classNames ) {
		jQuery.className.add( this, classNames );
	},

	removeClass: function( classNames ) {
		jQuery.className.remove( this, classNames );
	},

	toggleClass: function( classNames, state ) {
		if( typeof state !== "boolean" )
			state = !jQuery.className.has( this, classNames );
		jQuery.className[ state ? "add" : "remove" ]( this, classNames );
	},

	remove: function( selector ) {
		if ( !selector || jQuery.filter( selector, [ this ] ).length ) {
			// Prevent memory leaks
			jQuery( "*", this ).add([this]).each(function(){
				jQuery.event.remove(this);
				jQuery.removeData(this);
			});
			if (this.parentNode)
				this.parentNode.removeChild( this );
		}
	},

	empty: function() {
		// Remove element nodes and prevent memory leaks
		jQuery( ">*", this ).remove();

		// Remove any remaining nodes
		while ( this.firstChild )
			this.removeChild( this.firstChild );
	}
}, function(name, fn){
	jQuery.fn[ name ] = function(){
		return this.each( fn, arguments );
	};
});

// Helper function used by the dimensions and offset modules
function num(elem, prop) {
	return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0;
}
var expando = "jQuery" + now(), uuid = 0, windowData = {};

jQuery.extend({
	cache: {},

	data: function( elem, name, data ) {
		elem = elem == window ?
			windowData :
			elem;

		var id = elem[ expando ];

		// Compute a unique ID for the element
		if ( !id )
			id = elem[ expando ] = ++uuid;

		// Only generate the data cache if we're
		// trying to access or manipulate it
		if ( name && !jQuery.cache[ id ] )
			jQuery.cache[ id ] = {};

		// Prevent overriding the named cache with undefined values
		if ( data !== undefined )
			jQuery.cache[ id ][ name ] = data;

		// Return the named cache data, or the ID for the element
		return name ?
			jQuery.cache[ id ][ name ] :
			id;
	},

	removeData: function( elem, name ) {
		elem = elem == window ?
			windowData :
			elem;

		var id = elem[ expando ];

		// If we want to remove a specific section of the element's data
		if ( name ) {
			if ( jQuery.cache[ id ] ) {
				// Remove the section of cache data
				delete jQuery.cache[ id ][ name ];

				// If we've removed all the data, remove the element's cache
				name = "";

				for ( name in jQuery.cache[ id ] )
					break;

				if ( !name )
					jQuery.removeData( elem );
			}

		// Otherwise, we want to remove all of the element's data
		} else {
			// Clean up the element expando
			try {
				delete elem[ expando ];
			} catch(e){
				// IE has trouble directly removing the expando
				// but it's ok with using removeAttribute
				if ( elem.removeAttribute )
					elem.removeAttribute( expando );
			}

			// Completely remove the data cache
			delete jQuery.cache[ id ];
		}
	},
	queue: function( elem, type, data ) {
		if ( elem ){
	
			type = (type || "fx") + "queue";
	
			var q = jQuery.data( elem, type );
	
			if ( !q || jQuery.isArray(data) )
				q = jQuery.data( elem, type, jQuery.makeArray(data) );
			else if( data )
				q.push( data );
	
		}
		return q;
	},

	dequeue: function( elem, type ){
		var queue = jQuery.queue( elem, type ),
			fn = queue.shift();
		
		if( !type || type === "fx" )
			fn = queue[0];
			
		if( fn !== undefined )
			fn.call(elem);
	}
});

jQuery.fn.extend({
	data: function( key, value ){
		var parts = key.split(".");
		parts[1] = parts[1] ? "." + parts[1] : "";

		if ( value === undefined ) {
			var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);

			if ( data === undefined && this.length )
				data = jQuery.data( this[0], key );

			return data === undefined && parts[1] ?
				this.data( parts[0] ) :
				data;
		} else
			return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
				jQuery.data( this, key, value );
			});
	},

	removeData: function( key ){
		return this.each(function(){
			jQuery.removeData( this, key );
		});
	},
	queue: function(type, data){
		if ( typeof type !== "string" ) {
			data = type;
			type = "fx";
		}

		if ( data === undefined )
			return jQuery.queue( this[0], type );

		return this.each(function(){
			var queue = jQuery.queue( this, type, data );
			
			 if( type == "fx" && queue.length == 1 )
				queue[0].call(this);
		});
	},
	dequeue: function(type){
		return this.each(function(){
			jQuery.dequeue( this, type );
		});
	}
});/*!
 * Sizzle CSS Selector Engine - v0.9.3
 *  Copyright 2009, The Dojo Foundation
 *  Released under the MIT, BSD, and GPL Licenses.
 *  More information: http://sizzlejs.com/
 */
(function(){

var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]+['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[]+)+|[>+~])(\s*,\s*)?/g,
	done = 0,
	toString = Object.prototype.toString;

var Sizzle = function(selector, context, results, seed) {
	results = results || [];
	context = context || document;

	if ( context.nodeType !== 1 && context.nodeType !== 9 )
		return [];
	
	if ( !selector || typeof selector !== "string" ) {
		return results;
	}

	var parts = [], m, set, checkSet, check, mode, extra, prune = true;
	
	// Reset the position of the chunker regexp (start from head)
	chunker.lastIndex = 0;
	
	while ( (m = chunker.exec(selector)) !== null ) {
		parts.push( m[1] );
		
		if ( m[2] ) {
			extra = RegExp.rightContext;
			break;
		}
	}

	if ( parts.length > 1 && origPOS.exec( selector ) ) {
		if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
			set = posProcess( parts[0] + parts[1], context );
		} else {
			set = Expr.relative[ parts[0] ] ?
				[ context ] :
				Sizzle( parts.shift(), context );

			while ( parts.length ) {
				selector = parts.shift();

				if ( Expr.relative[ selector ] )
					selector += parts.shift();

				set = posProcess( selector, set );
			}
		}
	} else {
		var ret = seed ?
			{ expr: parts.pop(), set: makeArray(seed) } :
			Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context, isXML(context) );
		set = Sizzle.filter( ret.expr, ret.set );

		if ( parts.length > 0 ) {
			checkSet = makeArray(set);
		} else {
			prune = false;
		}

		while ( parts.length ) {
			var cur = parts.pop(), pop = cur;

			if ( !Expr.relative[ cur ] ) {
				cur = "";
			} else {
				pop = parts.pop();
			}

			if ( pop == null ) {
				pop = context;
			}

			Expr.relative[ cur ]( checkSet, pop, isXML(context) );
		}
	}

	if ( !checkSet ) {
		checkSet = set;
	}

	if ( !checkSet ) {
		throw "Syntax error, unrecognized expression: " + (cur || selector);
	}

	if ( toString.call(checkSet) === "[object Array]" ) {
		if ( !prune ) {
			results.push.apply( results, checkSet );
		} else if ( context.nodeType === 1 ) {
			for ( var i = 0; checkSet[i] != null; i++ ) {
				if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
					results.push( set[i] );
				}
			}
		} else {
			for ( var i = 0; checkSet[i] != null; i++ ) {
				if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
					results.push( set[i] );
				}
			}
		}
	} else {
		makeArray( checkSet, results );
	}

	if ( extra ) {
		Sizzle( extra, context, results, seed );
	}

	return results;
};

Sizzle.matches = function(expr, set){
	return Sizzle(expr, null, null, set);
};

Sizzle.find = function(expr, context, isXML){
	var set, match;

	if ( !expr ) {
		return [];
	}

	for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
		var type = Expr.order[i], match;
		
		if ( (match = Expr.match[ type ].exec( expr )) ) {
			var left = RegExp.leftContext;

			if ( left.substr( left.length - 1 ) !== "\\" ) {
				match[1] = (match[1] || "").replace(/\\/g, "");
				set = Expr.find[ type ]( match, context, isXML );
				if ( set != null ) {
					expr = expr.replace( Expr.match[ type ], "" );
					break;
				}
			}
		}
	}

	if ( !set ) {
		set = context.getElementsByTagName("*");
	}

	return {set: set, expr: expr};
};

Sizzle.filter = function(expr, set, inplace, not){
	var old = expr, result = [], curLoop = set, match, anyFound;

	while ( expr && set.length ) {
		for ( var type in Expr.filter ) {
			if ( (match = Expr.match[ type ].exec( expr )) != null ) {
				var filter = Expr.filter[ type ], found, item;
				anyFound = false;

				if ( curLoop == result ) {
					result = [];
				}

				if ( Expr.preFilter[ type ] ) {
					match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not );

					if ( !match ) {
						anyFound = found = true;
					} else if ( match === true ) {
						continue;
					}
				}

				if ( match ) {
					for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
						if ( item ) {
							found = filter( item, match, i, curLoop );
							var pass = not ^ !!found;

							if ( inplace && found != null ) {
								if ( pass ) {
									anyFound = true;
								} else {
									curLoop[i] = false;
								}
							} else if ( pass ) {
								result.push( item );
								anyFound = true;
							}
						}
					}
				}

				if ( found !== undefined ) {
					if ( !inplace ) {
						curLoop = result;
					}

					expr = expr.replace( Expr.match[ type ], "" );

					if ( !anyFound ) {
						return [];
					}

					break;
				}
			}
		}

		expr = expr.replace(/\s*,\s*/, "");

		// Improper expression
		if ( expr == old ) {
			if ( anyFound == null ) {
				throw "Syntax error, unrecognized expression: " + expr;
			} else {
				break;
			}
		}

		old = expr;
	}

	return curLoop;
};

var Expr = Sizzle.selectors = {
	order: [ "ID", "NAME", "TAG" ],
	match: {
		ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
		CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
		NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,
		ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
		TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,
		CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
		POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
		PSEUDO: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
	},
	attrMap: {
		"class": "className",
		"for": "htmlFor"
	},
	attrHandle: {
		href: function(elem){
			return elem.getAttribute("href");
		}
	},
	relative: {
		"+": function(checkSet, part){
			for ( var i = 0, l = checkSet.length; i < l; i++ ) {
				var elem = checkSet[i];
				if ( elem ) {
					var cur = elem.previousSibling;
					while ( cur && cur.nodeType !== 1 ) {
						cur = cur.previousSibling;
					}
					checkSet[i] = typeof part === "string" ?
						cur || false :
						cur === part;
				}
			}

			if ( typeof part === "string" ) {
				Sizzle.filter( part, checkSet, true );
			}
		},
		">": function(checkSet, part, isXML){
			if ( typeof part === "string" && !/\W/.test(part) ) {
				part = isXML ? part : part.toUpperCase();

				for ( var i = 0, l = checkSet.length; i < l; i++ ) {
					var elem = checkSet[i];
					if ( elem ) {
						var parent = elem.parentNode;
						checkSet[i] = parent.nodeName === part ? parent : false;
					}
				}
			} else {
				for ( var i = 0, l = checkSet.length; i < l; i++ ) {
					var elem = checkSet[i];
					if ( elem ) {
						checkSet[i] = typeof part === "string" ?
							elem.parentNode :
							elem.parentNode === part;
					}
				}

				if ( typeof part === "string" ) {
					Sizzle.filter( part, checkSet, true );
				}
			}
		},
		"": function(checkSet, part, isXML){
			var doneName = "done" + (done++), checkFn = dirCheck;

			if ( !part.match(/\W/) ) {
				var nodeCheck = part = isXML ? part : part.toUpperCase();
				checkFn = dirNodeCheck;
			}

			checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
		},
		"~": function(checkSet, part, isXML){
			var doneName = "done" + (done++), checkFn = dirCheck;

			if ( typeof part === "string" && !part.match(/\W/) ) {
				var nodeCheck = part = isXML ? part : part.toUpperCase();
				checkFn = dirNodeCheck;
			}

			checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
		}
	},
	find: {
		ID: function(match, context, isXML){
			if ( typeof context.getElementById !== "undefined" && !isXML ) {
				var m = context.getElementById(match[1]);
				return m ? [m] : [];
			}
		},
		NAME: function(match, context, isXML){
			if ( typeof context.getElementsByName !== "undefined" && !isXML ) {
				return context.getElementsByName(match[1]);
			}
		},
		TAG: function(match, context){
			return context.getElementsByTagName(match[1]);
		}
	},
	preFilter: {
		CLASS: function(match, curLoop, inplace, result, not){
			match = " " + match[1].replace(/\\/g, "") + " ";

			var elem;
			for ( var i = 0; (elem = curLoop[i]) != null; i++ ) {
				if ( elem ) {
					if ( not ^ (" " + elem.className + " ").indexOf(match) >= 0 ) {
						if ( !inplace )
							result.push( elem );
					} else if ( inplace ) {
						curLoop[i] = false;
					}
				}
			}

			return false;
		},
		ID: function(match){
			return match[1].replace(/\\/g, "");
		},
		TAG: function(match, curLoop){
			for ( var i = 0; curLoop[i] === false; i++ ){}
			return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
		},
		CHILD: function(match){
			if ( match[1] == "nth" ) {
				// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
				var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
					match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" ||
					!/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);

				// calculate the numbers (first)n+(last) including if they are negative
				match[2] = (test[1] + (test[2] || 1)) - 0;
				match[3] = test[3] - 0;
			}

			// TODO: Move to normal caching system
			match[0] = "done" + (done++);

			return match;
		},
		ATTR: function(match){
			var name = match[1].replace(/\\/g, "");
			
			if ( Expr.attrMap[name] ) {
				match[1] = Expr.attrMap[name];
			}

			if ( match[2] === "~=" ) {
				match[4] = " " + match[4] + " ";
			}

			return match;
		},
		PSEUDO: function(match, curLoop, inplace, result, not){
			if ( match[1] === "not" ) {
				// If we're dealing with a complex expression, or a simple one
				if ( match[3].match(chunker).length > 1 ) {
					match[3] = Sizzle(match[3], null, null, curLoop);
				} else {
					var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
					if ( !inplace ) {
						result.push.apply( result, ret );
					}
					return false;
				}
			} else if ( Expr.match.POS.test( match[0] ) ) {
				return true;
			}
			
			return match;
		},
		POS: function(match){
			match.unshift( true );
			return match;
		}
	},
	filters: {
		enabled: function(elem){
			return elem.disabled === false && elem.type !== "hidden";
		},
		disabled: function(elem){
			return elem.disabled === true;
		},
		checked: function(elem){
			return elem.checked === true;
		},
		selected: function(elem){
			// Accessing this property makes selected-by-default
			// options in Safari work properly
			elem.parentNode.selectedIndex;
			return elem.selected === true;
		},
		parent: function(elem){
			return !!elem.firstChild;
		},
		empty: function(elem){
			return !elem.firstChild;
		},
		has: function(elem, i, match){
			return !!Sizzle( match[3], elem ).length;
		},
		header: function(elem){
			return /h\d/i.test( elem.nodeName );
		},
		text: function(elem){
			return "text" === elem.type;
		},
		radio: function(elem){
			return "radio" === elem.type;
		},
		checkbox: function(elem){
			return "checkbox" === elem.type;
		},
		file: function(elem){
			return "file" === elem.type;
		},
		password: function(elem){
			return "password" === elem.type;
		},
		submit: function(elem){
			return "submit" === elem.type;
		},
		image: function(elem){
			return "image" === elem.type;
		},
		reset: function(elem){
			return "reset" === elem.type;
		},
		button: function(elem){
			return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";
		},
		input: function(elem){
			return /input|select|textarea|button/i.test(elem.nodeName);
		}
	},
	setFilters: {
		first: function(elem, i){
			return i === 0;
		},
		last: function(elem, i, match, array){
			return i === array.length - 1;
		},
		even: function(elem, i){
			return i % 2 === 0;
		},
		odd: function(elem, i){
			return i % 2 === 1;
		},
		lt: function(elem, i, match){
			return i < match[3] - 0;
		},
		gt: function(elem, i, match){
			return i > match[3] - 0;
		},
		nth: function(elem, i, match){
			return match[3] - 0 == i;
		},
		eq: function(elem, i, match){
			return match[3] - 0 == i;
		}
	},
	filter: {
		CHILD: function(elem, match){
			var type = match[1], parent = elem.parentNode;

			var doneName = match[0];
			
			if ( parent && (!parent[ doneName ] || !elem.nodeIndex) ) {
				var count = 1;

				for ( var node = parent.firstChild; node; node = node.nextSibling ) {
					if ( node.nodeType == 1 ) {
						node.nodeIndex = count++;
					}
				}

				parent[ doneName ] = count - 1;
			}

			if ( type == "first" ) {
				return elem.nodeIndex == 1;
			} else if ( type == "last" ) {
				return elem.nodeIndex == parent[ doneName ];
			} else if ( type == "only" ) {
				return parent[ doneName ] == 1;
			} else if ( type == "nth" ) {
				var add = false, first = match[2], last = match[3];

				if ( first == 1 && last == 0 ) {
					return true;
				}

				if ( first == 0 ) {
					if ( elem.nodeIndex == last ) {
						add = true;
					}
				} else if ( (elem.nodeIndex - last) % first == 0 && (elem.nodeIndex - last) / first >= 0 ) {
					add = true;
				}

				return add;
			}
		},
		PSEUDO: function(elem, match, i, array){
			var name = match[1], filter = Expr.filters[ name ];

			if ( filter ) {
				return filter( elem, i, match, array );
			} else if ( name === "contains" ) {
				return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;
			} else if ( name === "not" ) {
				var not = match[3];

				for ( var i = 0, l = not.length; i < l; i++ ) {
					if ( not[i] === elem ) {
						return false;
					}
				}

				return true;
			}
		},
		ID: function(elem, match){
			return elem.nodeType === 1 && elem.getAttribute("id") === match;
		},
		TAG: function(elem, match){
			return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
		},
		CLASS: function(elem, match){
			return match.test( elem.className );
		},
		ATTR: function(elem, match){
			var result = Expr.attrHandle[ match[1] ] ? Expr.attrHandle[ match[1] ]( elem ) : elem[ match[1] ] || elem.getAttribute( match[1] ), value = result + "", type = match[2], check = match[4];
			return result == null ?
				type === "!=" :
				type === "=" ?
				value === check :
				type === "*=" ?
				value.indexOf(check) >= 0 :
				type === "~=" ?
				(" " + value + " ").indexOf(check) >= 0 :
				!match[4] ?
				result :
				type === "!=" ?
				value != check :
				type === "^=" ?
				value.indexOf(check) === 0 :
				type === "$=" ?
				value.substr(value.length - check.length) === check :
				type === "|=" ?
				value === check || value.substr(0, check.length + 1) === check + "-" :
				false;
		},
		POS: function(elem, match, i, array){
			var name = match[2], filter = Expr.setFilters[ name ];

			if ( filter ) {
				return filter( elem, i, match, array );
			}
		}
	}
};

var origPOS = Expr.match.POS;

for ( var type in Expr.match ) {
	Expr.match[ type ] = RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
}

var makeArray = function(array, results) {
	array = Array.prototype.slice.call( array );

	if ( results ) {
		results.push.apply( results, array );
		return results;
	}
	
	return array;
};

// Perform a simple check to determine if the browser is capable of
// converting a NodeList to an array using builtin methods.
try {
	Array.prototype.slice.call( document.documentElement.childNodes );

// Provide a fallback method if it does not work
} catch(e){
	makeArray = function(array, results) {
		var ret = results || [];

		if ( toString.call(array) === "[object Array]" ) {
			Array.prototype.push.apply( ret, array );
		} else {
			if ( typeof array.length === "number" ) {
				for ( var i = 0, l = array.length; i < l; i++ ) {
					ret.push( array[i] );
				}
			} else {
				for ( var i = 0; array[i]; i++ ) {
					ret.push( array[i] );
				}
			}
		}

		return ret;
	};
}

// Check to see if the browser returns elements by name when
// querying by getElementById (and provide a workaround)
(function(){
	// We're going to inject a fake input element with a specified name
	var form = document.createElement("form"),
		id = "script" + (new Date).getTime();
	form.innerHTML = "<input name='" + id + "'/>";

	// Inject it into the root element, check its status, and remove it quickly
	var root = document.documentElement;
	root.insertBefore( form, root.firstChild );

	// The workaround has to do additional checks after a getElementById
	// Which slows things down for other browsers (hence the branching)
	if ( !!document.getElementById( id ) ) {
		Expr.find.ID = function(match, context, isXML){
			if ( typeof context.getElementById !== "undefined" && !isXML ) {
				var m = context.getElementById(match[1]);
				return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
			}
		};

		Expr.filter.ID = function(elem, match){
			var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
			return elem.nodeType === 1 && node && node.nodeValue === match;
		};
	}

	root.removeChild( form );
})();

(function(){
	// Check to see if the browser returns only elements
	// when doing getElementsByTagName("*")

	// Create a fake element
	var div = document.createElement("div");
	div.appendChild( document.createComment("") );

	// Make sure no comments are found
	if ( div.getElementsByTagName("*").length > 0 ) {
		Expr.find.TAG = function(match, context){
			var results = context.getElementsByTagName(match[1]);

			// Filter out possible comments
			if ( match[1] === "*" ) {
				var tmp = [];

				for ( var i = 0; results[i]; i++ ) {
					if ( results[i].nodeType === 1 ) {
						tmp.push( results[i] );
					}
				}

				results = tmp;
			}

			return results;
		};
	}

	// Check to see if an attribute returns normalized href attributes
	div.innerHTML = "<a href='#'></a>";
	if ( div.firstChild && div.firstChild.getAttribute("href") !== "#" ) {
		Expr.attrHandle.href = function(elem){
			return elem.getAttribute("href", 2);
		};
	}
})();

if ( document.querySelectorAll ) (function(){
	var oldSizzle = Sizzle, div = document.createElement("div");
	div.innerHTML = "<p class='TEST'></p>";

	// Safari can't handle uppercase or unicode characters when
	// in quirks mode.
	if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
		return;
	}
	
	Sizzle = function(query, context, extra, seed){
		context = context || document;

		// Only use querySelectorAll on non-XML documents
		// (ID selectors don't work in non-HTML documents)
		if ( !seed && context.nodeType === 9 && !isXML(context) ) {
			try {
				return makeArray( context.querySelectorAll(query), extra );
			} catch(e){}
		}
		
		return oldSizzle(query, context, extra, seed);
	};

	Sizzle.find = oldSizzle.find;
	Sizzle.filter = oldSizzle.filter;
	Sizzle.selectors = oldSizzle.selectors;
	Sizzle.matches = oldSizzle.matches;
})();

if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) {
	Expr.order.splice(1, 0, "CLASS");
	Expr.find.CLASS = function(match, context) {
		return context.getElementsByClassName(match[1]);
	};
}

function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
		var elem = checkSet[i];
		if ( elem ) {
			elem = elem[dir];
			var match = false;

			while ( elem && elem.nodeType ) {
				var done = elem[doneName];
				if ( done ) {
					match = checkSet[ done ];
					break;
				}

				if ( elem.nodeType === 1 && !isXML )
					elem[doneName] = i;

				if ( elem.nodeName === cur ) {
					match = elem;
					break;
				}

				elem = elem[dir];
			}

			checkSet[i] = match;
		}
	}
}

function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
		var elem = checkSet[i];
		if ( elem ) {
			elem = elem[dir];
			var match = false;

			while ( elem && elem.nodeType ) {
				if ( elem[doneName] ) {
					match = checkSet[ elem[doneName] ];
					break;
				}

				if ( elem.nodeType === 1 ) {
					if ( !isXML )
						elem[doneName] = i;

					if ( typeof cur !== "string" ) {
						if ( elem === cur ) {
							match = true;
							break;
						}

					} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
						match = elem;
						break;
					}
				}

				elem = elem[dir];
			}

			checkSet[i] = match;
		}
	}
}

var contains = document.compareDocumentPosition ?  function(a, b){
	return a.compareDocumentPosition(b) & 16;
} : function(a, b){
	return a !== b && (a.contains ? a.contains(b) : true);
};

var isXML = function(elem){
	return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
		!!elem.ownerDocument && isXML( elem.ownerDocument );
};

var posProcess = function(selector, context){
	var tmpSet = [], later = "", match,
		root = context.nodeType ? [context] : context;

	// Position selectors must be done after the filter
	// And so must :not(positional) so we move all PSEUDOs to the end
	while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
		later += match[0];
		selector = selector.replace( Expr.match.PSEUDO, "" );
	}

	selector = Expr.relative[selector] ? selector + "*" : selector;

	for ( var i = 0, l = root.length; i < l; i++ ) {
		Sizzle( selector, root[i], tmpSet );
	}

	return Sizzle.filter( later, tmpSet );
};

// EXPOSE
jQuery.find = Sizzle;
jQuery.filter = Sizzle.filter;
jQuery.expr = Sizzle.selectors;
jQuery.expr[":"] = jQuery.expr.filters;

Sizzle.selectors.filters.hidden = function(elem){
	return "hidden" === elem.type ||
		jQuery.css(elem, "display") === "none" ||
		jQuery.css(elem, "visibility") === "hidden";
};

Sizzle.selectors.filters.visible = function(elem){
	return "hidden" !== elem.type &&
		jQuery.css(elem, "display") !== "none" &&
		jQuery.css(elem, "visibility") !== "hidden";
};

Sizzle.selectors.filters.animated = function(elem){
	return jQuery.grep(jQuery.timers, function(fn){
		return elem === fn.elem;
	}).length;
};

jQuery.multiFilter = function( expr, elems, not ) {
	if ( not ) {
		expr = ":not(" + expr + ")";
	}

	return Sizzle.matches(expr, elems);
};

jQuery.dir = function( elem, dir ){
	var matched = [], cur = elem[dir];
	while ( cur && cur != document ) {
		if ( cur.nodeType == 1 )
			matched.push( cur );
		cur = cur[dir];
	}
	return matched;
};

jQuery.nth = function(cur, result, dir, elem){
	result = result || 1;
	var num = 0;

	for ( ; cur; cur = cur[dir] )
		if ( cur.nodeType == 1 && ++num == result )
			break;

	return cur;
};

jQuery.sibling = function(n, elem){
	var r = [];

	for ( ; n; n = n.nextSibling ) {
		if ( n.nodeType == 1 && n != elem )
			r.push( n );
	}

	return r;
};

return;

window.Sizzle = Sizzle;

})();
/*
 * A number of helper functions used for managing events.
 * Many of the ideas behind this code originated from
 * Dean Edwards' addEvent library.
 */
jQuery.event = {

	// Bind an event to an element
	// Original by Dean Edwards
	add: function(elem, types, handler, data) {
		if ( elem.nodeType == 3 || elem.nodeType == 8 )
			return;

		// For whatever reason, IE has trouble passing the window object
		// around, causing it to be cloned in the process
		if ( elem.setInterval && elem != window )
			elem = window;

		// Make sure that the function being executed has a unique ID
		if ( !handler.guid )
			handler.guid = this.guid++;

		// if data is passed, bind to handler
		if ( data !== undefined ) {
			// Create temporary function pointer to original handler
			var fn = handler;

			// Create unique handler function, wrapped around original handler
			handler = this.proxy( fn );

			// Store data in unique handler
			handler.data = data;
		}

		// Init the element's event structure
		var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
			handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
				// Handle the second event of a trigger and when
				// an event is called after a page has unloaded
				return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
					jQuery.event.handle.apply(arguments.callee.elem, arguments) :
					undefined;
			});
		// Add elem as a property of the handle function
		// This is to prevent a memory leak with non-native
		// event in IE.
		handle.elem = elem;

		// Handle multiple events separated by a space
		// jQuery(...).bind("mouseover mouseout", fn);
		jQuery.each(types.split(/\s+/), function(index, type) {
			// Namespaced event handlers
			var namespaces = type.split(".");
			type = namespaces.shift();
			handler.type = namespaces.slice().sort().join(".");

			// Get the current list of functions bound to this event
			var handlers = events[type];
			
			if ( jQuery.event.specialAll[type] )
				jQuery.event.specialAll[type].setup.call(elem, data, namespaces);

			// Init the event handler queue
			if (!handlers) {
				handlers = events[type] = {};

				// Check for a special event handler
				// Only use addEventListener/attachEvent if the special
				// events handler returns false
				if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem, data, namespaces) === false ) {
					// Bind the global event handler to the element
					if (elem.addEventListener)
						elem.addEventListener(type, handle, false);
					else if (elem.attachEvent)
						elem.attachEvent("on" + type, handle);
				}
			}

			// Add the function to the element's handler list
			handlers[handler.guid] = handler;

			// Keep track of which events have been used, for global triggering
			jQuery.event.global[type] = true;
		});

		// Nullify elem to prevent memory leaks in IE
		elem = null;
	},

	guid: 1,
	global: {},

	// Detach an event or set of events from an element
	remove: function(elem, types, handler) {
		// don't do events on text and comment nodes
		if ( elem.nodeType == 3 || elem.nodeType == 8 )
			return;

		var events = jQuery.data(elem, "events"), ret, index;

		if ( events ) {
			// Unbind all events for the element
			if ( types === undefined || (typeof types === "string" && types.charAt(0) == ".") )
				for ( var type in events )
					this.remove( elem, type + (types || "") );
			else {
				// types is actually an event object here
				if ( types.type ) {
					handler = types.handler;
					types = types.type;
				}

				// Handle multiple events seperated by a space
				// jQuery(...).unbind("mouseover mouseout", fn);
				jQuery.each(types.split(/\s+/), function(index, type){
					// Namespaced event handlers
					var namespaces = type.split(".");
					type = namespaces.shift();
					var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");

					if ( events[type] ) {
						// remove the given handler for the given type
						if ( handler )
							delete events[type][handler.guid];

						// remove all handlers for the given type
						else
							for ( var handle in events[type] )
								// Handle the removal of namespaced events
								if ( namespace.test(events[type][handle].type) )
									delete events[type][handle];
									
						if ( jQuery.event.specialAll[type] )
							jQuery.event.specialAll[type].teardown.call(elem, namespaces);

						// remove generic event handler if no more handlers exist
						for ( ret in events[type] ) break;
						if ( !ret ) {
							if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem, namespaces) === false ) {
								if (elem.removeEventListener)
									elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
								else if (elem.detachEvent)
									elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
							}
							ret = null;
							delete events[type];
						}
					}
				});
			}

			// Remove the expando if it's no longer used
			for ( ret in events ) break;
			if ( !ret ) {
				var handle = jQuery.data( elem, "handle" );
				if ( handle ) handle.elem = null;
				jQuery.removeData( elem, "events" );
				jQuery.removeData( elem, "handle" );
			}
		}
	},

	// bubbling is internal
	trigger: function( event, data, elem, bubbling ) {
		// Event object or event type
		var type = event.type || event;

		if( !bubbling ){
			event = typeof event === "object" ?
				// jQuery.Event object
				event[expando] ? event :
				// Object literal
				jQuery.extend( jQuery.Event(type), event ) :
				// Just the event type (string)
				jQuery.Event(type);

			if ( type.indexOf("!") >= 0 ) {
				event.type = type = type.slice(0, -1);
				event.exclusive = true;
			}

			// Handle a global trigger
			if ( !elem ) {
				// Don't bubble custom events when global (to avoid too much overhead)
				event.stopPropagation();
				// Only trigger if we've ever bound an event for it
				if ( this.global[type] )
					jQuery.each( jQuery.cache, function(){
						if ( this.events && this.events[type] )
							jQuery.event.trigger( event, data, this.handle.elem );
					});
			}

			// Handle triggering a single element

			// don't do events on text and comment nodes
			if ( !elem || elem.nodeType == 3 || elem.nodeType == 8 )
				return undefined;
			
			// Clean up in case it is reused
			event.result = undefined;
			event.target = elem;
			
			// Clone the incoming data, if any
			data = jQuery.makeArray(data);
			data.unshift( event );
		}

		event.currentTarget = elem;

		// Trigger the event, it is assumed that "handle" is a function
		var handle = jQuery.data(elem, "handle");
		if ( handle )
			handle.apply( elem, data );

		// Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
		if ( (!elem[type] || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
			event.result = false;

		// Trigger the native events (except for clicks on links)
		if ( !bubbling && elem[type] && !event.isDefaultPrevented() && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
			this.triggered = true;
			try {
				elem[ type ]();
			// prevent IE from throwing an error for some hidden elements
			} catch (e) {}
		}

		this.triggered = false;

		if ( !event.isPropagationStopped() ) {
			var parent = elem.parentNode || elem.ownerDocument;
			if ( parent )
				jQuery.event.trigger(event, data, parent, true);
		}
	},

	handle: function(event) {
		// returned undefined or false
		var all, handlers;

		event = arguments[0] = jQuery.event.fix( event || window.event );

		// Namespaced event handlers
		var namespaces = event.type.split(".");
		event.type = namespaces.shift();

		// Cache this now, all = true means, any handler
		all = !namespaces.length && !event.exclusive;
		
		var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");

		handlers = ( jQuery.data(this, "events") || {} )[event.type];

		for ( var j in handlers ) {
			var handler = handlers[j];

			// Filter the functions by class
			if ( all || namespace.test(handler.type) ) {
				// Pass in a reference to the handler function itself
				// So that we can later remove it
				event.handler = handler;
				event.data = handler.data;

				var ret = handler.apply(this, arguments);

				if( ret !== undefined ){
					event.result = ret;
					if ( ret === false ) {
						event.preventDefault();
						event.stopPropagation();
					}
				}

				if( event.isImmediatePropagationStopped() )
					break;

			}
		}
	},

	props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),

	fix: function(event) {
		if ( event[expando] )
			return event;

		// store a copy of the original event object
		// and "clone" to set read-only properties
		var originalEvent = event;
		event = jQuery.Event( originalEvent );

		for ( var i = this.props.length, prop; i; ){
			prop = this.props[ --i ];
			event[ prop ] = originalEvent[ prop ];
		}

		// Fix target property, if necessary
		if ( !event.target )
			event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either

		// check if target is a textnode (safari)
		if ( event.target.nodeType == 3 )
			event.target = event.target.parentNode;

		// Add relatedTarget, if necessary
		if ( !event.relatedTarget && event.fromElement )
			event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;

		// Calculate pageX/Y if missing and clientX/Y available
		if ( event.pageX == null && event.clientX != null ) {
			var doc = document.documentElement, body = document.body;
			event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
			event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
		}

		// Add which for key events
		if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
			event.which = event.charCode || event.keyCode;

		// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
		if ( !event.metaKey && event.ctrlKey )
			event.metaKey = event.ctrlKey;

		// Add which for click: 1 == left; 2 == middle; 3 == right
		// Note: button is not normalized, so don't use it
		if ( !event.which && event.button )
			event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));

		return event;
	},

	proxy: function( fn, proxy ){
		proxy = proxy || function(){ return fn.apply(this, arguments); };
		// Set the guid of unique handler to the same of original handler, so it can be removed
		proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
		// So proxy can be declared as an argument
		return proxy;
	},

	special: {
		ready: {
			// Make sure the ready event is setup
			setup: bindReady,
			teardown: function() {}
		}
	},
	
	specialAll: {
		live: {
			setup: function( selector, namespaces ){
				jQuery.event.add( this, namespaces[0], liveHandler );
			},
			teardown:  function( namespaces ){
				if ( namespaces.length ) {
					var remove = 0, name = RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
					
					jQuery.each( (jQuery.data(this, "events").live || {}), function(){
						if ( name.test(this.type) )
							remove++;
					});
					
					if ( remove < 1 )
						jQuery.event.remove( this, namespaces[0], liveHandler );
				}
			}
		}
	}
};

jQuery.Event = function( src ){
	// Allow instantiation without the 'new' keyword
	if( !this.preventDefault )
		return new jQuery.Event(src);
	
	// Event object
	if( src && src.type ){
		this.originalEvent = src;
		this.type = src.type;
	// Event type
	}else
		this.type = src;

	// timeStamp is buggy for some events on Firefox(#3843)
	// So we won't rely on the native value
	this.timeStamp = now();
	
	// Mark it as fixed
	this[expando] = true;
};

function returnFalse(){
	return false;
}
function returnTrue(){
	return true;
}

// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
jQuery.Event.prototype = {
	preventDefault: function() {
		this.isDefaultPrevented = returnTrue;

		var e = this.originalEvent;
		if( !e )
			return;
		// if preventDefault exists run it on the original event
		if (e.preventDefault)
			e.preventDefault();
		// otherwise set the returnValue property of the original event to false (IE)
		e.returnValue = false;
	},
	stopPropagation: function() {
		this.isPropagationStopped = returnTrue;

		var e = this.originalEvent;
		if( !e )
			return;
		// if stopPropagation exists run it on the original event
		if (e.stopPropagation)
			e.stopPropagation();
		// otherwise set the cancelBubble property of the original event to true (IE)
		e.cancelBubble = true;
	},
	stopImmediatePropagation:function(){
		this.isImmediatePropagationStopped = returnTrue;
		this.stopPropagation();
	},
	isDefaultPrevented: returnFalse,
	isPropagationStopped: returnFalse,
	isImmediatePropagationStopped: returnFalse
};
// Checks if an event happened on an element within another element
// Used in jQuery.event.special.mouseenter and mouseleave handlers
var withinElement = function(event) {
	// Check if mouse(over|out) are still within the same parent element
	var parent = event.relatedTarget;
	// Traverse up the tree
	while ( parent && parent != this )
		try { parent = parent.parentNode; }
		catch(e) { parent = this; }
	
	if( parent != this ){
		// set the correct event type
		event.type = event.data;
		// handle event if we actually just moused on to a non sub-element
		jQuery.event.handle.apply( this, arguments );
	}
};
	
jQuery.each({ 
	mouseover: 'mouseenter', 
	mouseout: 'mouseleave'
}, function( orig, fix ){
	jQuery.event.special[ fix ] = {
		setup: function(){
			jQuery.event.add( this, orig, withinElement, fix );
		},
		teardown: function(){
			jQuery.event.remove( this, orig, withinElement );
		}
	};			   
});

jQuery.fn.extend({
	bind: function( type, data, fn ) {
		return type == "unload" ? this.one(type, data, fn) : this.each(function(){
			jQuery.event.add( this, type, fn || data, fn && data );
		});
	},

	one: function( type, data, fn ) {
		var one = jQuery.event.proxy( fn || data, function(event) {
			jQuery(this).unbind(event, one);
			return (fn || data).apply( this, arguments );
		});
		return this.each(function(){
			jQuery.event.add( this, type, one, fn && data);
		});
	},

	unbind: function( type, fn ) {
		return this.each(function(){
			jQuery.event.remove( this, type, fn );
		});
	},

	trigger: function( type, data ) {
		return this.each(function(){
			jQuery.event.trigger( type, data, this );
		});
	},

	triggerHandler: function( type, data ) {
		if( this[0] ){
			var event = jQuery.Event(type);
			event.preventDefault();
			event.stopPropagation();
			jQuery.event.trigger( event, data, this[0] );
			return event.result;
		}		
	},

	toggle: function( fn ) {
		// Save reference to arguments for access in closure
		var args = arguments, i = 1;

		// link all the functions, so any of them can unbind this click handler
		while( i < args.length )
			jQuery.event.proxy( fn, args[i++] );

		return this.click( jQuery.event.proxy( fn, function(event) {
			// Figure out which function to execute
			this.lastToggle = ( this.lastToggle || 0 ) % i;

			// Make sure that clicks stop
			event.preventDefault();

			// and execute the function
			return args[ this.lastToggle++ ].apply( this, arguments ) || false;
		}));
	},

	hover: function(fnOver, fnOut) {
		return this.mouseenter(fnOver).mouseleave(fnOut);
	},

	ready: function(fn) {
		// Attach the listeners
		bindReady();

		// If the DOM is already ready
		if ( jQuery.isReady )
			// Execute the function immediately
			fn.call( document, jQuery );

		// Otherwise, remember the function for later
		else
			// Add the function to the wait list
			jQuery.readyList.push( fn );

		return this;
	},
	
	live: function( type, fn ){
		var proxy = jQuery.event.proxy( fn );
		proxy.guid += this.selector + type;

		jQuery(document).bind( liveConvert(type, this.selector), this.selector, proxy );

		return this;
	},
	
	die: function( type, fn ){
		jQuery(document).unbind( liveConvert(type, this.selector), fn ? { guid: fn.guid + this.selector + type } : null );
		return this;
	}
});

function liveHandler( event ){
	var check = RegExp("(^|\\.)" + event.type + "(\\.|$)"),
		stop = true,
		elems = [];

	jQuery.each(jQuery.data(this, "events").live || [], function(i, fn){
		if ( check.test(fn.type) ) {
			var elem = jQuery(event.target).closest(fn.data)[0];
			if ( elem )
				elems.push({ elem: elem, fn: fn });
		}
	});

	jQuery.each(elems, function(){
		if ( this.fn.call(this.elem, event, this.fn.data) === false )
			stop = false;
	});

	return stop;
}

function liveConvert(type, selector){
	return ["live", type, selector.replace(/\./g, "`").replace(/ /g, "|")].join(".");
}

jQuery.extend({
	isReady: false,
	readyList: [],
	// Handle when the DOM is ready
	ready: function() {
		// Make sure that the DOM is not already loaded
		if ( !jQuery.isReady ) {
			// Remember that the DOM is ready
			jQuery.isReady = true;

			// If there are functions bound, to execute
			if ( jQuery.readyList ) {
				// Execute all of them
				jQuery.each( jQuery.readyList, function(){
					this.call( document, jQuery );
				});

				// Reset the list of functions
				jQuery.readyList = null;
			}

			// Trigger any bound ready events
			jQuery(document).triggerHandler("ready");
		}
	}
});

var readyBound = false;

function bindReady(){
	if ( readyBound ) return;
	readyBound = true;

	// Mozilla, Opera and webkit nightlies currently support this event
	if ( document.addEventListener ) {
		// Use the handy event callback
		document.addEventListener( "DOMContentLoaded", function(){
			document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
			jQuery.ready();
		}, false );

	// If IE event model is used
	} else if ( document.attachEvent ) {
		// ensure firing before onload,
		// maybe late but safe also for iframes
		document.attachEvent("onreadystatechange", function(){
			if ( document.readyState === "complete" ) {
				document.detachEvent( "onreadystatechange", arguments.callee );
				jQuery.ready();
			}
		});

		// If IE and not an iframe
		// continually check to see if the document is ready
		if ( document.documentElement.doScroll && typeof window.frameElement === "undefined" ) (function(){
			if ( jQuery.isReady ) return;

			try {
				// If IE is used, use the trick by Diego Perini
				// http://javascript.nwbox.com/IEContentLoaded/
				document.documentElement.doScroll("left");
			} catch( error ) {
				setTimeout( arguments.callee, 0 );
				return;
			}

			// and execute any waiting functions
			jQuery.ready();
		})();
	}

	// A fallback to window.onload, that will always work
	jQuery.event.add( window, "load", jQuery.ready );
}

jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
	"mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave," +
	"change,select,submit,keydown,keypress,keyup,error").split(","), function(i, name){

	// Handle event binding
	jQuery.fn[name] = function(fn){
		return fn ? this.bind(name, fn) : this.trigger(name);
	};
});

// Prevent memory leaks in IE
// And prevent errors on refresh with events like mouseover in other browsers
// Window isn't included so as not to unbind existing unload events
jQuery( window ).bind( 'unload', function(){ 
	for ( var id in jQuery.cache )
		// Skip the window
		if ( id != 1 && jQuery.cache[ id ].handle )
			jQuery.event.remove( jQuery.cache[ id ].handle.elem );
}); 
(function(){

	jQuery.support = {};

	var root = document.documentElement,
		script = document.createElement("script"),
		div = document.createElement("div"),
		id = "script" + (new Date).getTime();

	div.style.display = "none";
	div.innerHTML = '   <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';

	var all = div.getElementsByTagName("*"),
		a = div.getElementsByTagName("a")[0];

	// Can't get basic test support
	if ( !all || !all.length || !a ) {
		return;
	}

	jQuery.support = {
		// IE strips leading whitespace when .innerHTML is used
		leadingWhitespace: div.firstChild.nodeType == 3,
		
		// Make sure that tbody elements aren't automatically inserted
		// IE will insert them into empty tables
		tbody: !div.getElementsByTagName("tbody").length,
		
		// Make sure that you can get all elements in an <object> element
		// IE 7 always returns no results
		objectAll: !!div.getElementsByTagName("object")[0]
			.getElementsByTagName("*").length,
		
		// Make sure that link elements get serialized correctly by innerHTML
		// This requires a wrapper element in IE
		htmlSerialize: !!div.getElementsByTagName("link").length,
		
		// Get the style information from getAttribute
		// (IE uses .cssText insted)
		style: /red/.test( a.getAttribute("style") ),
		
		// Make sure that URLs aren't manipulated
		// (IE normalizes it by default)
		hrefNormalized: a.getAttribute("href") === "/a",
		
		// Make sure that element opacity exists
		// (IE uses filter instead)
		opacity: a.style.opacity === "0.5",
		
		// Verify style float existence
		// (IE uses styleFloat instead of cssFloat)
		cssFloat: !!a.style.cssFloat,

		// Will be defined later
		scriptEval: false,
		noCloneEvent: true,
		boxModel: null
	};
	
	script.type = "text/javascript";
	try {
		script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
	} catch(e){}

	root.insertBefore( script, root.firstChild );
	
	// Make sure that the execution of code works by injecting a script
	// tag with appendChild/createTextNode
	// (IE doesn't support this, fails, and uses .text instead)
	if ( window[ id ] ) {
		jQuery.support.scriptEval = true;
		delete window[ id ];
	}

	root.removeChild( script );

	if ( div.attachEvent && div.fireEvent ) {
		div.attachEvent("onclick", function(){
			// Cloning a node shouldn't copy over any
			// bound event handlers (IE does this)
			jQuery.support.noCloneEvent = false;
			div.detachEvent("onclick", arguments.callee);
		});
		div.cloneNode(true).fireEvent("onclick");
	}

	// Figure out if the W3C box model works as expected
	// document.body must exist before we can do this
	jQuery(function(){
		var div = document.createElement("div");
		div.style.width = "1px";
		div.style.paddingLeft = "1px";

		document.body.appendChild( div );
		jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
		document.body.removeChild( div );
	});
})();

var styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat";

jQuery.props = {
	"for": "htmlFor",
	"class": "className",
	"float": styleFloat,
	cssFloat: styleFloat,
	styleFloat: styleFloat,
	readonly: "readOnly",
	maxlength: "maxLength",
	cellspacing: "cellSpacing",
	rowspan: "rowSpan",
	tabindex: "tabIndex"
};
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("<div/>")
							// inject the contents of the document in, removing the scripts
							// to avoid any 'Permission Denied' errors in IE
							.append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))

							// 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 || /select|textarea/i.test(this.nodeName) ||
					/text|hidden|password/i.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);
	};
});

var jsc = now();

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: {},

	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, jsre = /=\?(&|$)/g, 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 ( !s.url.match(jsre) )
					s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
			} else if ( !s.data || !s.data.match(jsre) )
				s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
			s.dataType = "json";
		}

		// Build temporary JSONP function
		if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
			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(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
			// if nothing was replaced, add timestamp to the end
			s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
		}

		// If data is available, append data to url for get requests
		if ( s.data && type == "GET" ) {
			s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;

			// IE likes to send both get and post data, prevent this
			s.data = null;
		}

		// 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 = /^(\w+:)?\/\/([^\/?#]+)/.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;

			// 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();
						head.removeChild( script );
					}
				};
			}

			head.appendChild(script);

			// 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 header, if ifModified mode.
			if ( s.ifModified )
				xhr.setRequestHeader("If-Modified-Since",
					jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );

			// 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" ) {
					// Cache Last-Modified header, if ifModified mode.
					var modRes;
					try {
						modRes = xhr.getResponseHeader("Last-Modified");
					} catch(e) {} // swallow exception thrown by FF if header is not available

					if ( s.ifModified && modRes )
						jQuery.lastModified[s.url] = modRes;

					// 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(s.data);
		} 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:" ||
				( 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 ) {
		try {
			var xhrRes = xhr.getResponseHeader("Last-Modified");

			// Firefox always returns 200. check Last-Modified date
			return xhr.status == 304 || xhrRes == jQuery.lastModified[url];
		} catch(e){}
		return false;
	},

	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.tagName == "parsererror" )
			throw "parsererror";
			
		// Allow a pre-filtering function to sanitize the response
		// s != null 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" )
				data = window["eval"]("(" + 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(/%20/g, "+");
	}

});
var elemdisplay = {},
	timerId,
	fxAttrs = [
		// height animations
		[ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
		// width animations
		[ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
		// opacity animations
		[ "opacity" ]
	];

function genFx( type, num ){
	var obj = {};
	jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function(){
		obj[ this ] = type;
	});
	return obj;
}

jQuery.fn.extend({
	show: function(speed,callback){
		if ( speed ) {
			return this.animate( genFx("show", 3), speed, callback);
		} else {
			for ( var i = 0, l = this.length; i < l; i++ ){
				var old = jQuery.data(this[i], "olddisplay");
				
				this[i].style.display = old || "";
				
				if ( jQuery.css(this[i], "display") === "none" ) {
					var tagName = this[i].tagName, display;
					
					if ( elemdisplay[ tagName ] ) {
						display = elemdisplay[ tagName ];
					} else {
						var elem = jQuery("<" + tagName + " />").appendTo("body");
						
						display = elem.css("display");
						if ( display === "none" )
							display = "block";
						
						elem.remove();
						
						elemdisplay[ tagName ] = display;
					}
					
					this[i].style.display = jQuery.data(this[i], "olddisplay", display);
				}
			}
			
			return this;
		}
	},

	hide: function(speed,callback){
		if ( speed ) {
			return this.animate( genFx("hide", 3), speed, callback);
		} else {
			for ( var i = 0, l = this.length; i < l; i++ ){
				var old = jQuery.data(this[i], "olddisplay");
				if ( !old && old !== "none" )
					jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
				this[i].style.display = "none";
			}
			return this;
		}
	},

	// Save the old toggle function
	_toggle: jQuery.fn.toggle,

	toggle: function( fn, fn2 ){
		var bool = typeof fn === "boolean";

		return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
			this._toggle.apply( this, arguments ) :
			fn == null || bool ?
				this.each(function(){
					var state = bool ? fn : jQuery(this).is(":hidden");
					jQuery(this)[ state ? "show" : "hide" ]();
				}) :
				this.animate(genFx("toggle", 3), fn, fn2);
	},

	fadeTo: function(speed,to,callback){
		return this.animate({opacity: to}, speed, callback);
	},

	animate: function( prop, speed, easing, callback ) {
		var optall = jQuery.speed(speed, easing, callback);

		return this[ optall.queue === false ? "each" : "queue" ](function(){
		
			var opt = jQuery.extend({}, optall), p,
				hidden = this.nodeType == 1 && jQuery(this).is(":hidden"),
				self = this;
	
			for ( p in prop ) {
				if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
					return opt.complete.call(this);

				if ( ( p == "height" || p == "width" ) && this.style ) {
					// Store display property
					opt.display = jQuery.css(this, "display");

					// Make sure that nothing sneaks out
					opt.overflow = this.style.overflow;
				}
			}

			if ( opt.overflow != null )
				this.style.overflow = "hidden";

			opt.curAnim = jQuery.extend({}, prop);

			jQuery.each( prop, function(name, val){
				var e = new jQuery.fx( self, opt, name );

				if ( /toggle|show|hide/.test(val) )
					e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
				else {
					var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
						start = e.cur(true) || 0;

					if ( parts ) {
						var end = parseFloat(parts[2]),
							unit = parts[3] || "px";

						// We need to compute starting value
						if ( unit != "px" ) {
							self.style[ name ] = (end || 1) + unit;
							start = ((end || 1) / e.cur(true)) * start;
							self.style[ name ] = start + unit;
						}

						// If a +=/-= token was provided, we're doing a relative animation
						if ( parts[1] )
							end = ((parts[1] == "-=" ? -1 : 1) * end) + start;

						e.custom( start, end, unit );
					} else
						e.custom( start, val, "" );
				}
			});

			// For JS strict compliance
			return true;
		});
	},

	stop: function(clearQueue, gotoEnd){
		var timers = jQuery.timers;

		if (clearQueue)
			this.queue([]);

		this.each(function(){
			// go in reverse order so anything added to the queue during the loop is ignored
			for ( var i = timers.length - 1; i >= 0; i-- )
				if ( timers[i].elem == this ) {
					if (gotoEnd)
						// force the next step to be the last
						timers[i](true);
					timers.splice(i, 1);
				}
		});

		// start the next in the queue if the last step wasn't forced
		if (!gotoEnd)
			this.dequeue();

		return this;
	}

});

// Generate shortcuts for custom animations
jQuery.each({
	slideDown: genFx("show", 1),
	slideUp: genFx("hide", 1),
	slideToggle: genFx("toggle", 1),
	fadeIn: { opacity: "show" },
	fadeOut: { opacity: "hide" }
}, function( name, props ){
	jQuery.fn[ name ] = function( speed, callback ){
		return this.animate( props, speed, callback );
	};
});

jQuery.extend({

	speed: function(speed, easing, fn) {
		var opt = typeof speed === "object" ? speed : {
			complete: fn || !fn && easing ||
				jQuery.isFunction( speed ) && speed,
			duration: speed,
			easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
		};

		opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
			jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;

		// Queueing
		opt.old = opt.complete;
		opt.complete = function(){
			if ( opt.queue !== false )
				jQuery(this).dequeue();
			if ( jQuery.isFunction( opt.old ) )
				opt.old.call( this );
		};

		return opt;
	},

	easing: {
		linear: function( p, n, firstNum, diff ) {
			return firstNum + diff * p;
		},
		swing: function( p, n, firstNum, diff ) {
			return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
		}
	},

	timers: [],

	fx: function( elem, options, prop ){
		this.options = options;
		this.elem = elem;
		this.prop = prop;

		if ( !options.orig )
			options.orig = {};
	}

});

jQuery.fx.prototype = {

	// Simple function for setting a style value
	update: function(){
		if ( this.options.step )
			this.options.step.call( this.elem, this.now, this );

		(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );

		// Set display property to block for height/width animations
		if ( ( this.prop == "height" || this.prop == "width" ) && this.elem.style )
			this.elem.style.display = "block";
	},

	// Get the current size
	cur: function(force){
		if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) )
			return this.elem[ this.prop ];

		var r = parseFloat(jQuery.css(this.elem, this.prop, force));
		return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
	},

	// Start an animation from one number to another
	custom: function(from, to, unit){
		this.startTime = now();
		this.start = from;
		this.end = to;
		this.unit = unit || this.unit || "px";
		this.now = this.start;
		this.pos = this.state = 0;

		var self = this;
		function t(gotoEnd){
			return self.step(gotoEnd);
		}

		t.elem = this.elem;

		if ( t() && jQuery.timers.push(t) == 1 ) {
			timerId = setInterval(function(){
				var timers = jQuery.timers;

				for ( var i = 0; i < timers.length; i++ )
					if ( !timers[i]() )
						timers.splice(i--, 1);

				if ( !timers.length ) {
					clearInterval( timerId );
				}
			}, 13);
		}
	},

	// Simple 'show' function
	show: function(){
		// Remember where we started, so that we can go back to it later
		this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
		this.options.show = true;

		// Begin the animation
		// Make sure that we start at a small width/height to avoid any
		// flash of content
		this.custom(this.prop == "width" || this.prop == "height" ? 1 : 0, this.cur());

		// Start by showing the element
		jQuery(this.elem).show();
	},

	// Simple 'hide' function
	hide: function(){
		// Remember where we started, so that we can go back to it later
		this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
		this.options.hide = true;

		// Begin the animation
		this.custom(this.cur(), 0);
	},

	// Each step of an animation
	step: function(gotoEnd){
		var t = now();

		if ( gotoEnd || t >= this.options.duration + this.startTime ) {
			this.now = this.end;
			this.pos = this.state = 1;
			this.update();

			this.options.curAnim[ this.prop ] = true;

			var done = true;
			for ( var i in this.options.curAnim )
				if ( this.options.curAnim[i] !== true )
					done = false;

			if ( done ) {
				if ( this.options.display != null ) {
					// Reset the overflow
					this.elem.style.overflow = this.options.overflow;

					// Reset the display
					this.elem.style.display = this.options.display;
					if ( jQuery.css(this.elem, "display") == "none" )
						this.elem.style.display = "block";
				}

				// Hide the element if the "hide" operation was done
				if ( this.options.hide )
					jQuery(this.elem).hide();

				// Reset the properties, if the item has been hidden or shown
				if ( this.options.hide || this.options.show )
					for ( var p in this.options.curAnim )
						jQuery.attr(this.elem.style, p, this.options.orig[p]);
					
				// Execute the complete function
				this.options.complete.call( this.elem );
			}

			return false;
		} else {
			var n = t - this.startTime;
			this.state = n / this.options.duration;

			// Perform the easing function, defaults to swing
			this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
			this.now = this.start + ((this.end - this.start) * this.pos);

			// Perform the next step of the animation
			this.update();
		}

		return true;
	}

};

jQuery.extend( jQuery.fx, {
	speeds:{
		slow: 600,
 		fast: 200,
 		// Default speed
 		_default: 400
	},
	step: {

		opacity: function(fx){
			jQuery.attr(fx.elem.style, "opacity", fx.now);
		},

		_default: function(fx){
			if ( fx.elem.style && fx.elem.style[ fx.prop ] != null )
				fx.elem.style[ fx.prop ] = fx.now + fx.unit;
			else
				fx.elem[ fx.prop ] = fx.now;
		}
	}
});
if ( document.documentElement["getBoundingClientRect"] )
	jQuery.fn.offset = function() {
		if ( !this[0] ) return { top: 0, left: 0 };
		if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
		var box  = this[0].getBoundingClientRect(), doc = this[0].ownerDocument, body = doc.body, docElem = doc.documentElement,
			clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
			top  = box.top  + (self.pageYOffset || jQuery.boxModel && docElem.scrollTop  || body.scrollTop ) - clientTop,
			left = box.left + (self.pageXOffset || jQuery.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft;
		return { top: top, left: left };
	};
else 
	jQuery.fn.offset = function() {
		if ( !this[0] ) return { top: 0, left: 0 };
		if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
		jQuery.offset.initialized || jQuery.offset.initialize();

		var elem = this[0], offsetParent = elem.offsetParent, prevOffsetParent = elem,
			doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement,
			body = doc.body, defaultView = doc.defaultView,
			prevComputedStyle = defaultView.getComputedStyle(elem, null),
			top = elem.offsetTop, left = elem.offsetLeft;

		while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
			computedStyle = defaultView.getComputedStyle(elem, null);
			top -= elem.scrollTop, left -= elem.scrollLeft;
			if ( elem === offsetParent ) {
				top += elem.offsetTop, left += elem.offsetLeft;
				if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.tagName)) )
					top  += parseInt( computedStyle.borderTopWidth,  10) || 0,
					left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
				prevOffsetParent = offsetParent, offsetParent = elem.offsetParent;
			}
			if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" )
				top  += parseInt( computedStyle.borderTopWidth,  10) || 0,
				left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
			prevComputedStyle = computedStyle;
		}

		if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" )
			top  += body.offsetTop,
			left += body.offsetLeft;

		if ( prevComputedStyle.position === "fixed" )
			top  += Math.max(docElem.scrollTop, body.scrollTop),
			left += Math.max(docElem.scrollLeft, body.scrollLeft);

		return { top: top, left: left };
	};

jQuery.offset = {
	initialize: function() {
		if ( this.initialized ) return;
		var body = document.body, container = document.createElement('div'), innerDiv, checkDiv, table, td, rules, prop, bodyMarginTop = body.style.marginTop,
			html = '<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';

		rules = { position: 'absolute', top: 0, left: 0, margin: 0, border: 0, width: '1px', height: '1px', visibility: 'hidden' };
		for ( prop in rules ) container.style[prop] = rules[prop];

		container.innerHTML = html;
		body.insertBefore(container, body.firstChild);
		innerDiv = container.firstChild, checkDiv = innerDiv.firstChild, td = innerDiv.nextSibling.firstChild.firstChild;

		this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
		this.doesAddBorderForTableAndCells = (td.offsetTop === 5);

		innerDiv.style.overflow = 'hidden', innerDiv.style.position = 'relative';
		this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);

		body.style.marginTop = '1px';
		this.doesNotIncludeMarginInBodyOffset = (body.offsetTop === 0);
		body.style.marginTop = bodyMarginTop;

		body.removeChild(container);
		this.initialized = true;
	},

	bodyOffset: function(body) {
		jQuery.offset.initialized || jQuery.offset.initialize();
		var top = body.offsetTop, left = body.offsetLeft;
		if ( jQuery.offset.doesNotIncludeMarginInBodyOffset )
			top  += parseInt( jQuery.curCSS(body, 'marginTop',  true), 10 ) || 0,
			left += parseInt( jQuery.curCSS(body, 'marginLeft', true), 10 ) || 0;
		return { top: top, left: left };
	}
};


jQuery.fn.extend({
	position: function() {
		var left = 0, top = 0, results;

		if ( this[0] ) {
			// Get *real* offsetParent
			var offsetParent = this.offsetParent(),

			// Get correct offsets
			offset       = this.offset(),
			parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { top: 0, left: 0 } : offsetParent.offset();

			// Subtract element margins
			// note: when an element has margin: auto the offsetLeft and marginLeft 
			// are the same in Safari causing offset.left to incorrectly be 0
			offset.top  -= num( this, 'marginTop'  );
			offset.left -= num( this, 'marginLeft' );

			// Add offsetParent borders
			parentOffset.top  += num( offsetParent, 'borderTopWidth'  );
			parentOffset.left += num( offsetParent, 'borderLeftWidth' );

			// Subtract the two offsets
			results = {
				top:  offset.top  - parentOffset.top,
				left: offset.left - parentOffset.left
			};
		}

		return results;
	},

	offsetParent: function() {
		var offsetParent = this[0].offsetParent || document.body;
		while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && jQuery.css(offsetParent, 'position') == 'static') )
			offsetParent = offsetParent.offsetParent;
		return jQuery(offsetParent);
	}
});


// Create scrollLeft and scrollTop methods
jQuery.each( ['Left', 'Top'], function(i, name) {
	var method = 'scroll' + name;
	
	jQuery.fn[ method ] = function(val) {
		if (!this[0]) return null;

		return val !== undefined ?

			// Set the scroll offset
			this.each(function() {
				this == window || this == document ?
					window.scrollTo(
						!i ? val : jQuery(window).scrollLeft(),
						 i ? val : jQuery(window).scrollTop()
					) :
					this[ method ] = val;
			}) :

			// Return the scroll offset
			this[0] == window || this[0] == document ?
				self[ i ? 'pageYOffset' : 'pageXOffset' ] ||
					jQuery.boxModel && document.documentElement[ method ] ||
					document.body[ method ] :
				this[0][ method ];
	};
});
// Create innerHeight, innerWidth, outerHeight and outerWidth methods
jQuery.each([ "Height", "Width" ], function(i, name){

	var tl = i ? "Left"  : "Top",  // top or left
		br = i ? "Right" : "Bottom"; // bottom or right

	// innerHeight and innerWidth
	jQuery.fn["inner" + name] = function(){
		return this[ name.toLowerCase() ]() +
			num(this, "padding" + tl) +
			num(this, "padding" + br);
	};

	// outerHeight and outerWidth
	jQuery.fn["outer" + name] = function(margin) {
		return this["inner" + name]() +
			num(this, "border" + tl + "Width") +
			num(this, "border" + br + "Width") +
			(margin ?
				num(this, "margin" + tl) + num(this, "margin" + br) : 0);
	};
	
	var type = name.toLowerCase();

	jQuery.fn[ type ] = function( size ) {
		// Get window width or height
		return this[0] == window ?
			// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
			document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] ||
			document.body[ "client" + name ] :

			// Get document width or height
			this[0] == document ?
				// Either scroll[Width/Height] or offset[Width/Height], whichever is greater
				Math.max(
					document.documentElement["client" + name],
					document.body["scroll" + name], document.documentElement["scroll" + name],
					document.body["offset" + name], document.documentElement["offset" + name]
				) :

				// Get or set width or height on the element
				size === undefined ?
					// Get width or height on the element
					(this.length ? jQuery.css( this[0], type ) : null) :

					// Set the width or height on the element (default to pixels if value is unitless)
					this.css( type, typeof size === "string" ? size : size + "px" );
	};

});})();
/*
Written by Steve Tucker, 2006, http://www.stevetucker.co.uk
Full documentation can be found at http://www.stevetucker.co.uk/page-innerxhtml.php
Released under the Creative Commons Attribution-Share Alike 3.0  License, http://creativecommons.org/licenses/by-sa/3.0/

Change Log
----------
15/10/2006	v0.3	innerXHTML official release.
21/03/2007	v0.4	1. Third argument $appendage added (Steve Tucker & Stef Dawson, www.stefdawson.com)
			2. $source argument accepts string ID (Stef Dawson)
			3. IE6 'on' functions work (Stef Dawson & Steve Tucker)
*/
var innerXHTML;
(function() {
innerXHTML = function($source,$string,$appendage) {
	// (v0.4) Written 2006 by Steve Tucker, http://www.stevetucker.co.uk
	if (typeof($source) == 'string') $source = document.getElementById($source);
	if (!($source.nodeType == 1)) return false;
	var $children = $source.childNodes;
	var $xhtml;
	if (!$string) {
		$xhtml = [];
function innerXHTMLWalker($children) {
		for (var $i=0; $i<$children.length; $i++) {
			var $child = $children[$i];
			if ($child.nodeType == 3) {
				var $text_content = $child.nodeValue;
				$text_content = $text_content.replace(/</g,'&lt;');
				$text_content = $text_content.replace(/>/g,'&gt;');
				$xhtml.push($text_content);
			}
			else if ($child.nodeType == 8) {
				$xhtml.push('<!--', $child.nodeValue, '-->');
			}
			else {
				var $nodeName = $child.nodeName.toLowerCase();
				$xhtml.push('<', $nodeName);
				var $attributes = $child.attributes;
 				for (var $j=0; $j<$attributes.length; $j++) {
					var $attribute = $attributes[$j];
					var $attName = $attribute.nodeName.toLowerCase();
					var $attValue = $attribute.nodeValue;
					if ($attName == 'style' && $child.style.cssText) {
						$xhtml.push(' style="', $child.style.cssText.toLowerCase(), '"');
					}
					else if ($attValue && $attName != 'contenteditable') {
						// FIXME: quote $attrValue
						$xhtml.push(' ', $attName, '="', $attValue, '"');
					}
				}
				if ($child.childNodes.length == 0) {
					$xhtml.push(' />');
				} else {
					$xhtml.push('>');
					innerXHTMLWalker($child.childNodes);
					$xhtml.push('</', $nodeName, '>');
				}
			}
		}
}
		innerXHTMLWalker($children);
		$xhtml = $xhtml.join('');
	}
	else {
		if (!$appendage) {
			while ($children.length>0) {
				$source.removeChild($children[0]);
			}
			$appendage = false;
		}
		$xhtml = $string;
		while ($string) {
			var $returned = translateXHTML($string);
			var $elements = $returned[0];
			$string = $returned[1];
			if ($elements) {
				if (typeof($appendage) == 'string') $appendage = document.getElementById($appendage);
				if (!($appendage.nodeType == 1)) $source.appendChild($elements);
				else $source.insertBefore($elements,$appendage);
			}
		}
	}
	return $xhtml;
}
function translateXHTML($string) {
	var $match = /^<\/[a-z0-9]{1,}>/i.test($string);
	if ($match) {
		var $return = Array;
		$return[0] = false;
		$return[1] = $string.replace(/^<\/[a-z0-9]{1,}>/i,'');
		return $return;
	}
	$match = /^<[a-z]{1,}/i.test($string);
	if ($match) {
		$string = $string.replace(/^</,'');
		var $element = $string.match(/[a-z0-9]{1,}/i);
		if ($element) {
			var $new_element = document.createElement($element[0]);
			$string = $string.replace(/[a-z0-9]{1,}/i,'');
			var $attribute = true;
			while ($attribute) {
				$string = $string.replace(/^\s{1,}/,'');
				$attribute = $string.match(/^[a-z1-9_-]{1,}="[^"]{0,}"/i);
				if ($attribute) {
					$attribute = $attribute[0];
					$string = $string.replace(/^[a-z1-9_-]{1,}="[^"]{0,}"/i,'');
					var $attName = $attribute.match(/^[a-z1-9_-]{1,}/i);
					$attribute = $attribute.replace(/^[a-z1-9_-]{1,}="/i,'');
					$attribute = $attribute.replace(/;{0,1}"$/,'');
					if ($attribute) {
						var $attValue = $attribute;
						if ($attName == 'value') $new_element.value = $attValue;
						else if ($attName == 'class') $new_element.className = $attValue;
						else if ($attName == 'style') {
							var $style = $attValue.split(';');
							for (var $i=0; $i<$style.length; $i++) {
								var $this_style = $style[$i].split(':');
								$this_style[0] = $this_style[0].toLowerCase().replace(/(^\s{0,})|(\s{0,1}$)/,'');
								$this_style[1] = $this_style[1].toLowerCase().replace(/(^\s{0,})|(\s{0,1}$)/,'');
								if (/-{1,}/g.test($this_style[0])) {
									var $this_style_words = $this_style[0].split(/-/g);
									$this_style[0] = '';
									for (var $j=0; $j<$this_style_words.length; $j++) {
										if ($j==0) {
											$this_style[0] = $this_style_words[0];
											continue;
										}
										var $first_letter = $this_style_words[$j].toUpperCase().match(/^[a-z]{1,1}/i);
										$this_style[0] += $first_letter+$this_style_words[$j].replace(/^[a-z]{1,1}/,'');
									}
								}
								$new_element.style[$this_style[0]] = $this_style[1];
							}
						}
						else if (/^on/.test($attName)) $new_element[$attName] = function() { eval($attValue) };
						else $new_element.setAttribute($attName,$attValue);
					}
					else $attribute = true;
				}
			}
			$match = /^>/.test($string);
			if ($match) {
				$string = $string.replace(/^>/,'');
				var $child = true;
				while ($child) {
					var $returned = translateXHTML($string,false);
					$child = $returned[0];
					if ($child) $new_element.appendChild($child);
					$string = $returned[1];
				}
			}
			$string = $string.replace(/^\/>/,'');
		}
	}
	$match = /^[^<>]{1,}/i.test($string);
	if ($match && !$new_element) {
		var $text_content = $string.match(/^[^<>]{1,}/i)[0];
		$text_content = $text_content.replace(/&lt;/g,'<');
		$text_content = $text_content.replace(/&gt;/g,'>');
		$text_content = $text_content.replace(/&quot;/g,'"');
		var $new_element = document.createTextNode($text_content);
		$string = $string.replace(/^[^<>]{1,}/i,'');
	}
	$match = /^<!--[^<>]{1,}-->/i.test($string);
	if ($match && !$new_element) {
		if (document.createComment) {
			$string = $string.replace(/^<!--/i,'');
			var $text_content = $string.match(/^[^<>]{0,}-->{1,}/i);
			$text_content = $text_content[0].replace(/-->{1,1}$/,'');			
			var $new_element = document.createComment($text_content);
			$string = $string.replace(/^[^<>]{1,}-->/i,'');
		}
		else $string = $string.replace(/^<!--[^<>]{1,}-->/i,'');
	}
	var $return = Array;
	$return[0] = $new_element;
	$return[1] = $string;
	return $return;
}
})();
/*******************************************************************************
 * OpenAjax.js
 *
 * Reference implementation of the OpenAjax Hub, as specified by OpenAjax Alliance.
 * Specification is under development at: 
 *
 *   http://www.openajax.org/member/wiki/OpenAjax_Hub_Specification
 *
 * Copyright 2006-2007 OpenAjax Alliance
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 
 * use this file except in compliance with the License. You may obtain a copy 
 * of the License at http://www.apache.org/licenses/LICENSE-2.0 . Unless 
 * required by applicable law or agreed to in writing, software distributed 
 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
 * CONDITIONS OF ANY KIND, either express or implied. See the License for the 
 * specific language governing permissions and limitations under the License.
 *
 ******************************************************************************/

// prevent re-definition of the OpenAjax object
if(!window["OpenAjax"]){
	OpenAjax = new function(){
		var t = true;
		var f = false;
		var g = window;
		var libs;
		var ooh = "org.openajax.hub.";

		var h = {};
		this.hub = h;
		h.implementer = "http://openajax.org";
		h.implVersion = "0.6";
		h.specVersion = "0.6";
		h.implExtraData = {};
		var libs = {};
		h.libraries = libs;

		h.registerLibrary = function(prefix, nsURL, version, extra){
			libs[prefix] = {
				prefix: prefix,
				namespaceURI: nsURL,
				version: version,
				extraData: extra 
			};
			this.publish(ooh+"registerLibrary", libs[prefix]);
		}
		h.unregisterLibrary = function(prefix){
			this.publish(ooh+"unregisterLibrary", libs[prefix]);
			delete libs[prefix];
		}

		h._subscriptions = { c:{}, s:[] };
		h._cleanup = [];
		h._subIndex = 0;
		h._pubDepth = 0;

		h.subscribe = function(name, callback, scope, subscriberData, filter)			
		{
			if(!scope){
				scope = window;
			}
			var handle = name + "." + this._subIndex;
			var sub = { scope: scope, cb: callback, fcb: filter, data: subscriberData, sid: this._subIndex++, hdl: handle };
			var path = name.split(".");
	 		this._subscribe(this._subscriptions, path, 0, sub);
			return handle;
		}

		h.publish = function(name, message)		
		{
			var path = name.split(".");
			this._pubDepth++;
			this._publish(this._subscriptions, path, 0, name, message);
			this._pubDepth--;
			if((this._cleanup.length > 0) && (this._pubDepth == 0)) {
				for(var i = 0; i < this._cleanup.length; i++) 
					this.unsubscribe(this._cleanup[i].hdl);
				delete(this._cleanup);
				this._cleanup = [];
			}
		}

		h.unsubscribe = function(sub) 
		{
			var path = sub.split(".");
			var sid = path.pop();
			this._unsubscribe(this._subscriptions, path, 0, sid);
		}
		
		h._subscribe = function(tree, path, index, sub) 
		{
			var token = path[index];
			if(index == path.length) 	
				tree.s.push(sub);
			else { 
				if(typeof tree.c == "undefined")
					 tree.c = {};
				if(typeof tree.c[token] == "undefined") {
					tree.c[token] = { c: {}, s: [] }; 
					this._subscribe(tree.c[token], path, index + 1, sub);
				}
				else 
					this._subscribe( tree.c[token], path, index + 1, sub);
			}
		}

		h._publish = function(tree, path, index, name, msg) {
			if(typeof tree != "undefined") {
				var node;
				if(index == path.length) {
					node = tree;
				} else {
					this._publish(tree.c[path[index]], path, index + 1, name, msg);
					this._publish(tree.c["*"], path, index + 1, name, msg);			
					node = tree.c["**"];
				}
				if(typeof node != "undefined") {
					var callbacks = node.s;
					var max = callbacks.length;
					for(var i = 0; i < max; i++) {
						if(callbacks[i].cb) {
							var sc = callbacks[i].scope;
							var cb = callbacks[i].cb;
							var fcb = callbacks[i].fcb;
							var d = callbacks[i].data;
							if(typeof cb == "string"){
								// get a function object
								cb = sc[cb];
							}
							if(typeof fcb == "string"){
								// get a function object
								fcb = sc[fcb];
							}
							if((!fcb) || 
							   (fcb.call(sc, name, msg, d))) {
								cb.call(sc, name, msg, d);
							}
						}
					}
				}
			}
		}
			
		h._unsubscribe = function(tree, path, index, sid) {
			if(typeof tree != "undefined") {
				if(index < path.length) {
					var childNode = tree.c[path[index]];
					this._unsubscribe(childNode, path, index + 1, sid);
					if(childNode.s.length == 0) {
						for(var x in childNode.c) 
					 		return;		
						delete tree.c[path[index]];	
					}
					return;
				}
				else {
					var callbacks = tree.s;
					var max = callbacks.length;
					for(var i = 0; i < max; i++) 
						if(sid == callbacks[i].sid) {
							if(this._pubDepth > 0) {
								callbacks[i].cb = null;	
								this._cleanup.push(callbacks[i]);						
							}
							else
								callbacks.splice(i, 1);
							return; 	
						}
				}
			}
		}
		// The following function is provided for automatic testing purposes.
		// It is not expected to be deployed in run-time OpenAjax Hub implementations.
		h.reinit = function()
		{
			for (var lib in OpenAjax.hub.libraries) {
				delete OpenAjax.hub.libraries[lib];
			}
			OpenAjax.hub.registerLibrary("OpenAjax", "http://openajax.org/hub", "0.6", {});

			delete OpenAjax._subscriptions;
			OpenAjax._subscriptions = {c:{},s:[]};
			delete OpenAjax._cleanup;
			OpenAjax._cleanup = [];
			OpenAjax._subIndex = 0;
			OpenAjax._pubDepth = 0;
		}
	};
	// Register the OpenAjax Hub itself as a library.
	OpenAjax.hub.registerLibrary("OpenAjax", "http://openajax.org/hub", "0.6", {});

}

(function($){$.extend({tablesorter:new function(){var parsers=[],widgets=[];this.defaults={cssHeader:"header",cssAsc:"headerSortUp",cssDesc:"headerSortDown",sortInitialOrder:"asc",sortMultiSortKey:"shiftKey",sortForce:null,sortAppend:null,textExtraction:"simple",parsers:{},widgets:[],widgetZebra:{css:["even","odd"]},headers:{},widthFixed:false,cancelSelection:true,sortList:[],headerList:[],dateFormat:"us",decimal:'.',debug:false};function benchmark(s,d){log(s+","+(new Date().getTime()-d.getTime())+"ms");}this.benchmark=benchmark;function log(s){if(typeof console!="undefined"&&typeof console.debug!="undefined"){console.log(s);}else{alert(s);}}function buildParserCache(table,$headers){if(table.config.debug){var parsersDebug="";}var rows=table.tBodies[0].rows;if(table.tBodies[0].rows[0]){var list=[],cells=rows[0].cells,l=cells.length;for(var i=0;i<l;i++){var p=false;if($.metadata&&($($headers[i]).metadata()&&$($headers[i]).metadata().sorter)){p=getParserById($($headers[i]).metadata().sorter);}else if((table.config.headers[i]&&table.config.headers[i].sorter)){p=getParserById(table.config.headers[i].sorter);}if(!p){p=detectParserForColumn(table,cells[i]);}if(table.config.debug){parsersDebug+="column:"+i+" parser:"+p.id+"\n";}list.push(p);}}if(table.config.debug){log(parsersDebug);}return list;};function detectParserForColumn(table,node){var l=parsers.length;for(var i=1;i<l;i++){if(parsers[i].is($.trim(getElementText(table.config,node)),table,node)){return parsers[i];}}return parsers[0];}function getParserById(name){var l=parsers.length;for(var i=0;i<l;i++){if(parsers[i].id.toLowerCase()==name.toLowerCase()){return parsers[i];}}return false;}function buildCache(table){if(table.config.debug){var cacheTime=new Date();}var totalRows=(table.tBodies[0]&&table.tBodies[0].rows.length)||0,totalCells=(table.tBodies[0].rows[0]&&table.tBodies[0].rows[0].cells.length)||0,parsers=table.config.parsers,cache={row:[],normalized:[]};for(var i=0;i<totalRows;++i){var c=table.tBodies[0].rows[i],cols=[];cache.row.push($(c));for(var j=0;j<totalCells;++j){cols.push(parsers[j].format(getElementText(table.config,c.cells[j]),table,c.cells[j]));}cols.push(i);cache.normalized.push(cols);cols=null;};if(table.config.debug){benchmark("Building cache for "+totalRows+" rows:",cacheTime);}return cache;};function getElementText(config,node){if(!node)return"";var t="";if(config.textExtraction=="simple"){if(node.childNodes[0]&&node.childNodes[0].hasChildNodes()){t=node.childNodes[0].innerHTML;}else{t=node.innerHTML;}}else{if(typeof(config.textExtraction)=="function"){t=config.textExtraction(node);}else{t=$(node).text();}}return t;}function appendToTable(table,cache){if(table.config.debug){var appendTime=new Date()}var c=cache,r=c.row,n=c.normalized,totalRows=n.length,checkCell=(n[0].length-1),tableBody=$(table.tBodies[0]),rows=[];for(var i=0;i<totalRows;i++){rows.push(r[n[i][checkCell]]);if(!table.config.appender){var o=r[n[i][checkCell]];var l=o.length;for(var j=0;j<l;j++){tableBody[0].appendChild(o[j]);}}}if(table.config.appender){table.config.appender(table,rows);}rows=null;if(table.config.debug){benchmark("Rebuilt table:",appendTime);}applyWidget(table);setTimeout(function(){$(table).trigger("sortEnd");},0);};function buildHeaders(table){if(table.config.debug){var time=new Date();}var meta=($.metadata)?true:false,tableHeadersRows=[];for(var i=0;i<table.tHead.rows.length;i++){tableHeadersRows[i]=0;};$tableHeaders=$("thead th",table);$tableHeaders.each(function(index){this.count=0;this.column=index;this.order=formatSortingOrder(table.config.sortInitialOrder);if(checkHeaderMetadata(this)||checkHeaderOptions(table,index))this.sortDisabled=true;if(!this.sortDisabled){$(this).addClass(table.config.cssHeader);}table.config.headerList[index]=this;});if(table.config.debug){benchmark("Built headers:",time);log($tableHeaders);}return $tableHeaders;};function checkCellColSpan(table,rows,row){var arr=[],r=table.tHead.rows,c=r[row].cells;for(var i=0;i<c.length;i++){var cell=c[i];if(cell.colSpan>1){arr=arr.concat(checkCellColSpan(table,headerArr,row++));}else{if(table.tHead.length==1||(cell.rowSpan>1||!r[row+1])){arr.push(cell);}}}return arr;};function checkHeaderMetadata(cell){if(($.metadata)&&($(cell).metadata().sorter===false)){return true;};return false;}function checkHeaderOptions(table,i){if((table.config.headers[i])&&(table.config.headers[i].sorter===false)){return true;};return false;}function applyWidget(table){var c=table.config.widgets;var l=c.length;for(var i=0;i<l;i++){getWidgetById(c[i]).format(table);}}function getWidgetById(name){var l=widgets.length;for(var i=0;i<l;i++){if(widgets[i].id.toLowerCase()==name.toLowerCase()){return widgets[i];}}};function formatSortingOrder(v){if(typeof(v)!="Number"){i=(v.toLowerCase()=="desc")?1:0;}else{i=(v==(0||1))?v:0;}return i;}function isValueInArray(v,a){var l=a.length;for(var i=0;i<l;i++){if(a[i][0]==v){return true;}}return false;}function setHeadersCss(table,$headers,list,css){$headers.removeClass(css[0]).removeClass(css[1]);var h=[];$headers.each(function(offset){if(!this.sortDisabled){h[this.column]=$(this);}});var l=list.length;for(var i=0;i<l;i++){h[list[i][0]].addClass(css[list[i][1]]);}}function fixColumnWidth(table,$headers){var c=table.config;if(c.widthFixed){var colgroup=$('<colgroup>');$("tr:first td",table.tBodies[0]).each(function(){colgroup.append($('<col>').css('width',$(this).width()));});$(table).prepend(colgroup);};}function updateHeaderSortCount(table,sortList){var c=table.config,l=sortList.length;for(var i=0;i<l;i++){var s=sortList[i],o=c.headerList[s[0]];o.count=s[1];o.count++;}}function multisort(table,sortList,cache){if(table.config.debug){var sortTime=new Date();}var dynamicExp="var sortWrapper = function(a,b) {",l=sortList.length;for(var i=0;i<l;i++){var c=sortList[i][0];var order=sortList[i][1];var s=(getCachedSortType(table.config.parsers,c)=="text")?((order==0)?"sortText":"sortTextDesc"):((order==0)?"sortNumeric":"sortNumericDesc");var e="e"+i;dynamicExp+="var "+e+" = "+s+"(a["+c+"],b["+c+"]); ";dynamicExp+="if("+e+") { return "+e+"; } ";dynamicExp+="else { ";}var orgOrderCol=cache.normalized[0].length-1;dynamicExp+="return a["+orgOrderCol+"]-b["+orgOrderCol+"];";for(var i=0;i<l;i++){dynamicExp+="}; ";}dynamicExp+="return 0; ";dynamicExp+="}; ";eval(dynamicExp);cache.normalized.sort(sortWrapper);if(table.config.debug){benchmark("Sorting on "+sortList.toString()+" and dir "+order+" time:",sortTime);}return cache;};function sortText(a,b){return((a<b)?-1:((a>b)?1:0));};function sortTextDesc(a,b){return((b<a)?-1:((b>a)?1:0));};function sortNumeric(a,b){return a-b;};function sortNumericDesc(a,b){return b-a;};function getCachedSortType(parsers,i){return parsers[i].type;};this.construct=function(settings){return this.each(function(){if(!this.tHead||!this.tBodies)return;var $this,$document,$headers,cache,config,shiftDown=0,sortOrder;this.config={};config=$.extend(this.config,$.tablesorter.defaults,settings);$this=$(this);$headers=buildHeaders(this);this.config.parsers=buildParserCache(this,$headers);cache=buildCache(this);var sortCSS=[config.cssDesc,config.cssAsc];fixColumnWidth(this);$headers.click(function(e){$this.trigger("sortStart");var totalRows=($this[0].tBodies[0]&&$this[0].tBodies[0].rows.length)||0;if(!this.sortDisabled&&totalRows>0){var $cell=$(this);var i=this.column;this.order=this.count++%2;if(!e[config.sortMultiSortKey]){config.sortList=[];if(config.sortForce!=null){var a=config.sortForce;for(var j=0;j<a.length;j++){if(a[j][0]!=i){config.sortList.push(a[j]);}}}config.sortList.push([i,this.order]);}else{if(isValueInArray(i,config.sortList)){for(var j=0;j<config.sortList.length;j++){var s=config.sortList[j],o=config.headerList[s[0]];if(s[0]==i){o.count=s[1];o.count++;s[1]=o.count%2;}}}else{config.sortList.push([i,this.order]);}};setTimeout(function(){setHeadersCss($this[0],$headers,config.sortList,sortCSS);appendToTable($this[0],multisort($this[0],config.sortList,cache));},1);return false;}}).mousedown(function(){if(config.cancelSelection){this.onselectstart=function(){return false};return false;}});$this.bind("update",function(){this.config.parsers=buildParserCache(this,$headers);cache=buildCache(this);}).bind("sorton",function(e,list){$(this).trigger("sortStart");config.sortList=list;var sortList=config.sortList;updateHeaderSortCount(this,sortList);setHeadersCss(this,$headers,sortList,sortCSS);appendToTable(this,multisort(this,sortList,cache));}).bind("appendCache",function(){appendToTable(this,cache);}).bind("applyWidgetId",function(e,id){getWidgetById(id).format(this);}).bind("applyWidgets",function(){applyWidget(this);});if($.metadata&&($(this).metadata()&&$(this).metadata().sortlist)){config.sortList=$(this).metadata().sortlist;}if(config.sortList.length>0){$this.trigger("sorton",[config.sortList]);}applyWidget(this);});};this.addParser=function(parser){var l=parsers.length,a=true;for(var i=0;i<l;i++){if(parsers[i].id.toLowerCase()==parser.id.toLowerCase()){a=false;}}if(a){parsers.push(parser);};};this.addWidget=function(widget){widgets.push(widget);};this.formatFloat=function(s){var i=parseFloat(s);return(isNaN(i))?0:i;};this.formatInt=function(s){var i=parseInt(s);return(isNaN(i))?0:i;};this.isDigit=function(s,config){var DECIMAL='\\'+config.decimal;var exp='/(^[+]?0('+DECIMAL+'0+)?$)|(^([-+]?[1-9][0-9]*)$)|(^([-+]?((0?|[1-9][0-9]*)'+DECIMAL+'(0*[1-9][0-9]*)))$)|(^[-+]?[1-9]+[0-9]*'+DECIMAL+'0+$)/';return RegExp(exp).test($.trim(s));};this.clearTableBody=function(table){if($.browser.msie){function empty(){while(this.firstChild)this.removeChild(this.firstChild);}empty.apply(table.tBodies[0]);}else{table.tBodies[0].innerHTML="";}};}});$.fn.extend({tablesorter:$.tablesorter.construct});var ts=$.tablesorter;ts.addParser({id:"text",is:function(s){return true;},format:function(s){return $.trim(s.toLowerCase());},type:"text"});ts.addParser({id:"digit",is:function(s,table){var c=table.config;return $.tablesorter.isDigit(s,c);},format:function(s){return $.tablesorter.formatFloat(s);},type:"numeric"});ts.addParser({id:"currency",is:function(s){return/^[£$€?.]/.test(s);},format:function(s){return $.tablesorter.formatFloat(s.replace(new RegExp(/[^0-9.]/g),""));},type:"numeric"});ts.addParser({id:"ipAddress",is:function(s){return/^\d{2,3}[\.]\d{2,3}[\.]\d{2,3}[\.]\d{2,3}$/.test(s);},format:function(s){var a=s.split("."),r="",l=a.length;for(var i=0;i<l;i++){var item=a[i];if(item.length==2){r+="0"+item;}else{r+=item;}}return $.tablesorter.formatFloat(r);},type:"numeric"});ts.addParser({id:"url",is:function(s){return/^(https?|ftp|file):\/\/$/.test(s);},format:function(s){return jQuery.trim(s.replace(new RegExp(/(https?|ftp|file):\/\//),''));},type:"text"});ts.addParser({id:"isoDate",is:function(s){return/^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(s);},format:function(s){return $.tablesorter.formatFloat((s!="")?new Date(s.replace(new RegExp(/-/g),"/")).getTime():"0");},type:"numeric"});ts.addParser({id:"percent",is:function(s){return/\%$/.test($.trim(s));},format:function(s){return $.tablesorter.formatFloat(s.replace(new RegExp(/%/g),""));},type:"numeric"});ts.addParser({id:"usLongDate",is:function(s){return s.match(new RegExp(/^[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/));},format:function(s){return $.tablesorter.formatFloat(new Date(s).getTime());},type:"numeric"});ts.addParser({id:"shortDate",is:function(s){return/\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2,4}/.test(s);},format:function(s,table){var c=table.config;s=s.replace(/\-/g,"/");if(c.dateFormat=="us"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,"$3/$1/$2");}else if(c.dateFormat=="uk"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/,"$3/$2/$1");}else if(c.dateFormat=="dd/mm/yy"||c.dateFormat=="dd-mm-yy"){s=s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{2})/,"$1/$2/$3");}return $.tablesorter.formatFloat(new Date(s).getTime());},type:"numeric"});ts.addParser({id:"time",is:function(s){return/^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/.test(s);},format:function(s){return $.tablesorter.formatFloat(new Date("2000/01/01 "+s).getTime());},type:"numeric"});ts.addParser({id:"metadata",is:function(s){return false;},format:function(s,table,cell){var c=table.config,p=(!c.parserMetadataName)?'sortValue':c.parserMetadataName;return $(cell).metadata()[p];},type:"numeric"});ts.addWidget({id:"zebra",format:function(table){if(table.config.debug){var time=new Date();}$("tr:visible",table.tBodies[0]).filter(':even').removeClass(table.config.widgetZebra.css[1]).addClass(table.config.widgetZebra.css[0]).end().filter(':odd').removeClass(table.config.widgetZebra.css[0]).addClass(table.config.widgetZebra.css[1]);if(table.config.debug){$.tablesorter.benchmark("Applying Zebra widget",time);}}});})(jQuery);/*
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * $LastChangedDate: 2007-03-04 20:15:11 -0600 (Sun, 04 Mar 2007) $
 * $Rev: 1485 $
 */

jQuery.fn._height = jQuery.fn.height;
jQuery.fn._width  = jQuery.fn.width;

/**
 * If used on document, returns the document's height (innerHeight)
 * If used on window, returns the viewport's (window) height
 * See core docs on height() to see what happens when used on an element.
 *
 * @example $("#testdiv").height()
 * @result 200
 *
 * @example $(document).height()
 * @result 800
 *
 * @example $(window).height()
 * @result 400
 *
 * @name height
 * @type Object
 * @cat Plugins/Dimensions
 */
jQuery.fn.height = function() {
	if ( this[0] == window )
		return self.innerHeight ||
			jQuery.boxModel && document.documentElement.clientHeight ||
			document.body.clientHeight;

	if ( this[0] == document )
		return Math.max( document.body.scrollHeight, document.body.offsetHeight );

	return this._height(arguments[0]);
};

/**
 * If used on document, returns the document's width (innerWidth)
 * If used on window, returns the viewport's (window) width
 * See core docs on height() to see what happens when used on an element.
 *
 * @example $("#testdiv").width()
 * @result 200
 *
 * @example $(document).width()
 * @result 800
 *
 * @example $(window).width()
 * @result 400
 *
 * @name width
 * @type Object
 * @cat Plugins/Dimensions
 */
jQuery.fn.width = function() {
	if ( this[0] == window )
		return self.innerWidth ||
			jQuery.boxModel && document.documentElement.clientWidth ||
			document.body.clientWidth;

	if ( this[0] == document )
		return Math.max( document.body.scrollWidth, document.body.offsetWidth );

	return this._width(arguments[0]);
};

/**
 * Returns the inner height value (without border) for the first matched element.
 * If used on document, returns the document's height (innerHeight)
 * If used on window, returns the viewport's (window) height
 *
 * @example $("#testdiv").innerHeight()
 * @result 800
 *
 * @name innerHeight
 * @type Number
 * @cat Plugins/Dimensions
 */
jQuery.fn.innerHeight = function() {
	return this[0] == window || this[0] == document ?
		this.height() :
		this.css('display') != 'none' ?
		 	this[0].offsetHeight - (parseInt(this.css("borderTopWidth")) || 0) - (parseInt(this.css("borderBottomWidth")) || 0) :
			this.height() + (parseInt(this.css("paddingTop")) || 0) + (parseInt(this.css("paddingBottom")) || 0);
};

/**
 * Returns the inner width value (without border) for the first matched element.
 * If used on document, returns the document's Width (innerWidth)
 * If used on window, returns the viewport's (window) width
 *
 * @example $("#testdiv").innerWidth()
 * @result 1000
 *
 * @name innerWidth
 * @type Number
 * @cat Plugins/Dimensions
 */
jQuery.fn.innerWidth = function() {
	return this[0] == window || this[0] == document ?
		this.width() :
		this.css('display') != 'none' ?
			this[0].offsetWidth - (parseInt(this.css("borderLeftWidth")) || 0) - (parseInt(this.css("borderRightWidth")) || 0) :
			this.height() + (parseInt(this.css("paddingLeft")) || 0) + (parseInt(this.css("paddingRight")) || 0);
};

/**
 * Returns the outer height value (including border) for the first matched element.
 * Cannot be used on document or window.
 *
 * @example $("#testdiv").outerHeight()
 * @result 1000
 *
 * @name outerHeight
 * @type Number
 * @cat Plugins/Dimensions
 */
jQuery.fn.outerHeight = function() {
	return this[0] == window || this[0] == document ?
		this.height() :
		this.css('display') != 'none' ?
			this[0].offsetHeight :
			this.height() + (parseInt(this.css("borderTopWidth")) || 0) + (parseInt(this.css("borderBottomWidth")) || 0)
				+ (parseInt(this.css("paddingTop")) || 0) + (parseInt(this.css("paddingBottom")) || 0);
};

/**
 * Returns the outer width value (including border) for the first matched element.
 * Cannot be used on document or window.
 *
 * @example $("#testdiv").outerWidth()
 * @result 1000
 *
 * @name outerWidth
 * @type Number
 * @cat Plugins/Dimensions
 */
jQuery.fn.outerWidth = function() {
	return this[0] == window || this[0] == document ?
		this.width() :
		this.css('display') != 'none' ?
			this[0].offsetWidth :
			this.height() + (parseInt(this.css("borderLeftWidth")) || 0) + (parseInt(this.css("borderRightWidth")) || 0)
				+ (parseInt(this.css("paddingLeft")) || 0) + (parseInt(this.css("paddingRight")) || 0);
};

/**
 * Returns how many pixels the user has scrolled to the right (scrollLeft).
 * Works on containers with overflow: auto and window/document.
 *
 * @example $("#testdiv").scrollLeft()
 * @result 100
 *
 * @name scrollLeft
 * @type Number
 * @cat Plugins/Dimensions
 */
jQuery.fn.scrollLeft = function() {
	if ( this[0] == window || this[0] == document )
		return self.pageXOffset ||
			jQuery.boxModel && document.documentElement.scrollLeft ||
			document.body.scrollLeft;

	return this[0].scrollLeft;
};

/**
 * Returns how many pixels the user has scrolled to the bottom (scrollTop).
 * Works on containers with overflow: auto and window/document.
 *
 * @example $("#testdiv").scrollTop()
 * @result 100
 *
 * @name scrollTop
 * @type Number
 * @cat Plugins/Dimensions
 */
jQuery.fn.scrollTop = function() {
	if ( this[0] == window || this[0] == document )
		return self.pageYOffset ||
			jQuery.boxModel && document.documentElement.scrollTop ||
			document.body.scrollTop;

	return this[0].scrollTop;
};

/**
 * Returns the location of the element in pixels from the top left corner of the viewport.
 *
 * For accurate readings make sure to use pixel values for margins, borders and padding.
 *
 * @example $("#testdiv").offset()
 * @result { top: 100, left: 100, scrollTop: 10, scrollLeft: 10 }
 *
 * @example $("#testdiv").offset({ scroll: false })
 * @result { top: 90, left: 90 }
 *
 * @example var offset = {}
 * $("#testdiv").offset({ scroll: false }, offset)
 * @result offset = { top: 90, left: 90 }
 *
 * @name offset
 * @param Object options A hash of options describing what should be included in the final calculations of the offset.
 *                       The options include:
 *                           margin: Should the margin of the element be included in the calculations? True by default.
 *                                   If set to false the margin of the element is subtracted from the total offset.
 *                           border: Should the border of the element be included in the calculations? True by default.
 *                                   If set to false the border of the element is subtracted from the total offset.
 *                           padding: Should the padding of the element be included in the calculations? False by default.
 *                                    If set to true the padding of the element is added to the total offset.
 *                           scroll: Should the scroll offsets of the parent elements be included in the calculations?
 *                                   True by default. When true, it adds the total scroll offsets of all parents to the
 *                                   total offset and also adds two properties to the returned object, scrollTop and
 *                                   scrollLeft. If set to false the scroll offsets of parent elements are ignored.
 *                                   If scroll offsets are not needed, set to false to get a performance boost.
 * @param Object returnObject An object to store the return value in, so as not to break the chain. If passed in the
 *                            chain will not be broken and the result will be assigned to this object.
 * @type Object
 * @cat Plugins/Dimensions
 * @author Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
 */
jQuery.fn.offset = function(options, returnObject) {
	var x = 0, y = 0, elem = this[0], parent = this[0], op, sl = 0, st = 0, options = jQuery.extend({ margin: true, border: true, padding: false, scroll: true }, options || {});
	do {
		x += parent.offsetLeft || 0;
		y += parent.offsetTop  || 0;

		// Mozilla and IE do not add the border
		if (jQuery.browser.mozilla || jQuery.browser.msie) {
			// get borders
			var bt = parseInt(jQuery.css(parent, 'borderTopWidth')) || 0;
			var bl = parseInt(jQuery.css(parent, 'borderLeftWidth')) || 0;

			// add borders to offset
			x += bl;
			y += bt;

			// Mozilla removes the border if the parent has overflow property other than visible
			if (jQuery.browser.mozilla && parent != elem && jQuery.css(parent, 'overflow') != 'visible') {
				x += bl;
				y += bt;
			}
		}

		if (options.scroll) {
			// Need to get scroll offsets in-between offsetParents
			op = parent.offsetParent;
			do {
				sl += parent.scrollLeft || 0;
				st += parent.scrollTop  || 0;

				parent = parent.parentNode;

				// Mozilla removes the border if the parent has overflow property other than visible
				if (jQuery.browser.mozilla && parent != elem && parent != op && jQuery.css(parent, 'overflow') != 'visible') {
					y += parseInt(jQuery.css(parent, 'borderTopWidth')) || 0;
					x += parseInt(jQuery.css(parent, 'borderLeftWidth')) || 0;
				}
			} while (parent != op);
		} else
			parent = parent.offsetParent;

		if (parent && (parent.tagName.toLowerCase() == 'body' || parent.tagName.toLowerCase() == 'html')) {
			// Safari and IE Standards Mode doesn't add the body margin for elments positioned with static or relative
			if ((jQuery.browser.safari || (jQuery.browser.msie && jQuery.boxModel)) && jQuery.css(parent, 'position') != 'absolute') {
				x += parseInt(jQuery.css(op, 'marginLeft')) || 0;
				y += parseInt(jQuery.css(op, 'marginTop'))  || 0;
			}
			break; // Exit the loop
		}
	} while (parent);

	if ( !options.margin) {
		x -= parseInt(jQuery.css(elem, 'marginLeft')) || 0;
		y -= parseInt(jQuery.css(elem, 'marginTop'))  || 0;
	}

	// Safari and Opera do not add the border for the element
	if ( options.border && (jQuery.browser.safari || jQuery.browser.opera) ) {
		x += parseInt(jQuery.css(elem, 'borderLeftWidth')) || 0;
		y += parseInt(jQuery.css(elem, 'borderTopWidth'))  || 0;
	} else if ( !options.border && !(jQuery.browser.safari || jQuery.browser.opera) ) {
		x -= parseInt(jQuery.css(elem, 'borderLeftWidth')) || 0;
		y -= parseInt(jQuery.css(elem, 'borderTopWidth'))  || 0;
	}

	if ( options.padding ) {
		x += parseInt(jQuery.css(elem, 'paddingLeft')) || 0;
		y += parseInt(jQuery.css(elem, 'paddingTop'))  || 0;
	}

	// Opera thinks offset is scroll offset for display: inline elements
	if (options.scroll && jQuery.browser.opera && jQuery.css(elem, 'display') == 'inline') {
		sl -= elem.scrollLeft || 0;
		st -= elem.scrollTop  || 0;
	}

	var returnValue = options.scroll ? { top: y - st, left: x - sl, scrollTop:  st, scrollLeft: sl }
	                                 : { top: y, left: x };

	if (returnObject) { jQuery.extend(returnObject, returnValue); return this; }
	else              { return returnValue; }
};/** The JSON class is copyright 2005 JSON.org. */
Array.prototype.______array = '______array';

var JSON = {
    org: 'http://www.JSON.org',
    copyright: '(c)2005 JSON.org',
    license: 'http://www.crockford.com/JSON/license.html',

    stringify: function (arg) {
        var c, i, l, s = '', v;

        switch (typeof arg) {
        case 'object':
            if (arg) {
                if (arg.______array == '______array') {
                    for (i = 0; i < arg.length; ++i) {
                        v = this.stringify(arg[i]);
                        if (s) {
                            s += ',';
                        }
                        s += v;
                    }
                    return '[' + s + ']';
                } else if (typeof arg.toString != 'undefined') {
                    for (i in arg) {
                        v = arg[i];
                        if (typeof v != 'undefined' && typeof v != 'function') {
                            v = this.stringify(v);
                            if (s) {
                                s += ',';
                            }
                            s += this.stringify(i) + ':' + v;
                        }
                    }
                    return '{' + s + '}';
                }
            }
            return 'null';
        case 'number':
            return isFinite(arg) ? String(arg) : 'null';
        case 'string':
            l = arg.length;
            s = '"';
            for (i = 0; i < l; i += 1) {
                c = arg.charAt(i);
                if (c >= ' ') {
                    if (c == '\\' || c == '"') {
                        s += '\\';
                    }
                    s += c;
                } else {
                    switch (c) {
                        case '\b':
                            s += '\\b';
                            break;
                        case '\f':
                            s += '\\f';
                            break;
                        case '\n':
                            s += '\\n';
                            break;
                        case '\r':
                            s += '\\r';
                            break;
                        case '\t':
                            s += '\\t';
                            break;
                        default:
                            c = c.charCodeAt();
                            s += '\\u00' + Math.floor(c / 16).toString(16) +
                                (c % 16).toString(16);
                    }
                }
            }
            return s + '"';
        case 'boolean':
            return String(arg);
        default:
            return 'null';
        }
    },
    parse: function (text) {
        var at = 0;
        var ch = ' ';

        function error(m) {
            throw {
                name: 'JSONError',
                message: m,
                at: at - 1,
                text: text
            };
        }

        function next() {
            ch = text.charAt(at);
            at += 1;
            return ch;
        }

        function white() {
            while (ch != '' && ch <= ' ') {
                next();
            }
        }

        function str() {
            var i, s = '', t, u;

            if (ch == '"') {
outer:          while (next()) {
                    if (ch == '"') {
                        next();
                        return s;
                    } else if (ch == '\\') {
                        switch (next()) {
                        case 'b':
                            s += '\b';
                            break;
                        case 'f':
                            s += '\f';
                            break;
                        case 'n':
                            s += '\n';
                            break;
                        case 'r':
                            s += '\r';
                            break;
                        case 't':
                            s += '\t';
                            break;
                        case 'u':
                            u = 0;
                            for (i = 0; i < 4; i += 1) {
                                t = parseInt(next(), 16);
                                if (!isFinite(t)) {
                                    break outer;
                                }
                                u = u * 16 + t;
                            }
                            s += String.fromCharCode(u);
                            break;
                        default:
                            s += ch;
                        }
                    } else {
                        s += ch;
                    }
                }
            }
            error("Bad string");
        }

        function arr() {
            var a = [];

            if (ch == '[') {
                next();
                white();
                if (ch == ']') {
                    next();
                    return a;
                }
                while (ch) {
                    a.push(val());
                    white();
                    if (ch == ']') {
                        next();
                        return a;
                    } else if (ch != ',') {
                        break;
                    }
                    next();
                    white();
                }
            }
            error("Bad array");
        }

        function obj() {
            var k, o = {};

            if (ch == '{') {
                next();
                white();
                if (ch == '}') {
                    next();
                    return o;
                }
                while (ch) {
                    k = str();
                    white();
                    if (ch != ':') {
                        break;
                    }
                    next();
                    o[k] = val();
                    white();
                    if (ch == '}') {
                        next();
                        return o;
                    } else if (ch != ',') {
                        break;
                    }
                    next();
                    white();
                }
            }
            error("Bad object");
        }

        function num() {
            var n = '', v;
            if (ch == '-') {
                n = '-';
                next();
            }
            while (ch >= '0' && ch <= '9') {
                n += ch;
                next();
            }
            if (ch == '.') {
                n += '.';
                while (next() && ch >= '0' && ch <= '9') {
                    n += ch;
                }
            }
            if (ch == 'e' || ch == 'E') {
                n += 'e';
                next();
                if (ch == '-' || ch == '+') {
                    n += ch;
                    next();
                }
                while (ch >= '0' && ch <= '9') {
                    n += ch;
                    next();
                }
            }
            v = +n;
            if (!isFinite(v)) {
                error("Bad number");
            } else {
                return v;
            }
        }

        function word() {
            switch (ch) {
                case 't':
                    if (next() == 'r' && next() == 'u' && next() == 'e') {
                        next();
                        return true;
                    }
                    break;
                case 'f':
                    if (next() == 'a' && next() == 'l' && next() == 's' &&
                            next() == 'e') {
                        next();
                        return false;
                    }
                    break;
                case 'n':
                    if (next() == 'u' && next() == 'l' && next() == 'l') {
                        next();
                        return null;
                    }
                    break;
            }
            error("Syntax error");
        }

        function val() {
            white();
            switch (ch) {
                case '{':
                    return obj();
                case '[':
                    return arr();
                case '"':
                    return str();
                case '-':
                    return num();
                default:
                    return ch >= '0' && ch <= '9' ? num() : word();
            }
        }

        return val();
    }
};
/*
Copyright (c) 2007 Brian Dillard and Brad Neuberg:
Brian Dillard | Project Lead | bdillard@pathf.com | http://blogs.pathf.com/agileajax/
Brad Neuberg | Original Project Creator | http://codinginparadise.org
   
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

/*
	dhtmlHistory: An object that provides history, history data, and bookmarking for DHTML and Ajax applications.
	
	dependencies:
		* the historyStorage object included in this file.

*/
window.dhtmlHistory = {
	
	/*Public: User-agent booleans*/
	isIE: false,
	isOpera: false,
	isSafari: false,
	isKonquerer: false,
	isGecko: false,
	isSupported: false,
	
	/*Public: Create the DHTML history infrastructure*/
	create: function(options) {
		
		/*
			options - object to store initialization parameters
			options.debugMode - boolean that causes hidden form fields to be shown for development purposes.
			options.toJSON - function to override default JSON stringifier
			options.fromJSON - function to override default JSON parser
		*/

		var that = this;

		/*set user-agent flags*/
		var UA = navigator.userAgent.toLowerCase();
		var platform = navigator.platform.toLowerCase();
		var vendor = navigator.vendor || "";
		if (vendor === "KDE") {
			this.isKonqueror = true;
			this.isSupported = false;
		} else if (typeof window.opera !== "undefined") {
			this.isOpera = true;
			this.isSupported = true;
		} else if (typeof document.all !== "undefined") {
			this.isIE = true;
			this.isSupported = true;
		} else if (vendor.indexOf("Apple Computer, Inc.") > -1) {
			this.isSafari = true;
			this.isSupported = (platform.indexOf("mac") > -1);
		} else if (UA.indexOf("gecko") != -1) {
			this.isGecko = true;
			this.isSupported = true;
		}

		/*Set up the historyStorage object; pass in init parameters*/
		window.historyStorage.setup(options);

		/*Execute browser-specific setup methods*/
		if (this.isSafari) {
			this.createSafari();
		} else if (this.isOpera) {
			this.createOpera();
		}
		
		/*Get our initial location*/
		var initialHash = this.getCurrentLocation();

		/*Save it as our current location*/
		this.currentLocation = initialHash;

		/*Now that we have a hash, create IE-specific code*/
		if (this.isIE) {
			this.createIE(initialHash);
		}

		/*Add an unload listener for the page; this is needed for FF 1.5+ because this browser caches all dynamic updates to the
		page, which can break some of our logic related to testing whether this is the first instance a page has loaded or whether
		it is being pulled from the cache*/

		var unloadHandler = function() {
			that.firstLoad = null;
		};
		
		this.addEventListener(window,'unload',unloadHandler);		

		/*Determine if this is our first page load; for IE, we do this in this.iframeLoaded(), which is fired on pageload. We do it
		there because we have no historyStorage at this point, which only exists after the page is finished loading in IE*/
		if (this.isIE) {
			/*The iframe will get loaded on page load, and we want to ignore this fact*/
			this.ignoreLocationChange = true;
		} else {
			if (!historyStorage.hasKey(this.PAGELOADEDSTRING)) {
				/*This is our first page load, so ignore the location change and add our special history entry*/
				this.ignoreLocationChange = true;
				this.firstLoad = true;
				historyStorage.put(this.PAGELOADEDSTRING, true);
			} else {
				/*This isn't our first page load, so indicate that we want to pay attention to this location change*/
				this.ignoreLocationChange = false;
				/*For browsers other than IE, fire a history change event; on IE, the event will be thrown automatically when its
				hidden iframe reloads on page load. Unfortunately, we don't have any listeners yet; indicate that we want to fire
				an event when a listener is added.*/
				this.fireOnNewListener = true;
			}
		}

		/*Other browsers can use a location handler that checks at regular intervals as their primary mechanism; we use it for IE as
		well to handle an important edge case; see checkLocation() for details*/
		var locationHandler = function() {
			that.checkLocation();
		};
		setInterval(locationHandler, 100);
	},	
	
	/*Public: Initialize our DHTML history. You must call this after the page is finished loading.*/
	initialize: function() {
		/*IE needs to be explicitly initialized. IE doesn't autofill form data until the page is finished loading, so we have to wait*/
		if (this.isIE) {
			/*If this is the first time this page has loaded*/
			if (!historyStorage.hasKey(this.PAGELOADEDSTRING)) {
				/*For IE, we do this in initialize(); for other browsers, we do it in create()*/
				this.fireOnNewListener = false;
				this.firstLoad = true;
				historyStorage.put(this.PAGELOADEDSTRING, true);
			}
			/*Else if this is a fake onload event*/
			else {
				this.fireOnNewListener = true;
				this.firstLoad = false;   
			}
		}
	},

	/*Public: Adds a history change listener. Note that only one listener is supported at this time.*/
	addListener: function(listener) {
		this.listener = listener;
		/*If the page was just loaded and we should not ignore it, fire an event to our new listener now*/
		if (this.fireOnNewListener) {
			this.fireHistoryEvent(this.currentLocation);
			this.fireOnNewListener = false;
		}
	},
	
	/*Public: Generic utility function for attaching events*/
	addEventListener: function(o,e,l) {
		if (o.addEventListener) {
			o.addEventListener(e,l,false);
		} else if (o.attachEvent) {
			o.attachEvent('on'+e,function() {
				l(window.event);
			});
		}
	},
	
	/*Public: Add a history point.*/
	add: function(newLocation, historyData) {
		
		if (this.isSafari) {
			
			/*Remove any leading hash symbols on newLocation*/
			newLocation = this.removeHash(newLocation);

			/*Store the history data into history storage*/
			historyStorage.put(newLocation, historyData);

			/*Save this as our current location*/
			this.currentLocation = newLocation;
	
			/*Change the browser location*/
			window.location.hash = newLocation;
		
			/*Save this to the Safari form field*/
			this.putSafariState(newLocation);

		} else {
			
			/*Most browsers require that we wait a certain amount of time before changing the location, such
			as 200 MS; rather than forcing external callers to use window.setTimeout to account for this,
			we internally handle it by putting requests in a queue.*/
			var that = this;
			var addImpl = function() {

				/*Indicate that the current wait time is now less*/
				if (that.currentWaitTime > 0) {
					that.currentWaitTime = that.currentWaitTime - that.waitTime;
				}
			
				/*Remove any leading hash symbols on newLocation*/
				newLocation = that.removeHash(newLocation);

				/*IE has a strange bug; if the newLocation is the same as _any_ preexisting id in the
				document, then the history action gets recorded twice; throw a programmer exception if
				there is an element with this ID*/
				if (document.getElementById(newLocation) && that.debugMode) {
					var e = "Exception: History locations can not have the same value as _any_ IDs that might be in the document,"
					+ " due to a bug in IE; please ask the developer to choose a history location that does not match any HTML"
					+ " IDs in this document. The following ID is already taken and cannot be a location: " + newLocation;
					throw new Error(e); 
				}

				/*Store the history data into history storage*/
				historyStorage.put(newLocation, historyData);

				/*Indicate to the browser to ignore this upcomming location change since we're making it programmatically*/
				that.ignoreLocationChange = true;

				/*Indicate to IE that this is an atomic location change block*/
				that.ieAtomicLocationChange = true;
		
				/*Save this as our current location*/
				that.currentLocation = newLocation;

				/*Change the browser location*/
				window.location.hash = newLocation;

				/*Change the hidden iframe's location if on IE*/
				if (that.isIE) {
					that.iframe.src = "/blank.html?" + newLocation;
				}

				/*End of atomic location change block for IE*/
				that.ieAtomicLocationChange = false;
			};

			/*Now queue up this add request*/
			window.setTimeout(addImpl, this.currentWaitTime);

			/*Indicate that the next request will have to wait for awhile*/
			this.currentWaitTime = this.currentWaitTime + this.waitTime;
		}
	},

	/*Public*/
	isFirstLoad: function() {
		return this.firstLoad;
	},

	/*Public*/
	getVersion: function() {
		return "0.6";
	},

	/*Get browser's current hash location; for Safari, read value from a hidden form field*/

	/*Public*/
	getCurrentLocation: function() {
		var r = (this.isSafari
			? this.getSafariState()
			: this.getCurrentHash()
		);
		return r;
	},
	
	/*Public: Manually parse the current url for a hash; tip of the hat to YUI*/
    getCurrentHash: function() {
		var r = window.location.href;
		var i = r.indexOf("#");
		return (i >= 0
			? r.substr(i+1)
			: ""
		);
    },
	
	/*- - - - - - - - - - - -*/
	
	/*Private: Constant for our own internal history event called when the page is loaded*/
	PAGELOADEDSTRING: "DhtmlHistory_pageLoaded",
	
	/*Private: Our history change listener.*/
	listener: null,

	/*Private: MS to wait between add requests - will be reset for certain browsers*/
	waitTime: 200,
	
	/*Private: MS before an add request can execute*/
	currentWaitTime: 0,

	/*Private: Our current hash location, without the "#" symbol.*/
	currentLocation: null,

	/*Private: Hidden iframe used to IE to detect history changes*/
	iframe: null,

	/*Private: Flags and DOM references used only by Safari*/
	safariHistoryStartPoint: null,
	safariStack: null,
	safariLength: null,

	/*Private: Flag used to keep checkLocation() from doing anything when it discovers location changes we've made ourselves
	programmatically with the add() method. Basically, add() sets this to true. When checkLocation() discovers it's true,
	it refrains from firing our listener, then resets the flag to false for next cycle. That way, our listener only gets fired on
	history change events triggered by the user via back/forward buttons and manual hash changes. This flag also helps us set up
	IE's special iframe-based method of handling history changes.*/
	ignoreLocationChange: null,

	/*Private: A flag that indicates that we should fire a history change event when we are ready, i.e. after we are initialized and
	we have a history change listener. This is needed due to an edge case in browsers other than IE; if you leave a page entirely
	then return, we must fire this as a history change event. Unfortunately, we have lost all references to listeners from earlier,
	because JavaScript clears out.*/
	fireOnNewListener: null,

	/*Private: A variable that indicates whether this is the first time this page has been loaded. If you go to a web page, leave it
	for another one, and then return, the page's onload listener fires again. We need a way to differentiate between the first page
	load and subsequent ones. This variable works hand in hand with the pageLoaded variable we store into historyStorage.*/
	firstLoad: null,

	/*Private: A variable to handle an important edge case in IE. In IE, if a user manually types an address into their browser's
	location bar, we must intercept this by calling checkLocation() at regular intervals. However, if we are programmatically
	changing the location bar ourselves using the add() method, we need to ignore these changes in checkLocation(). Unfortunately,
	these changes take several lines of code to complete, so for the duration of those lines of code, we set this variable to true.
	That signals to checkLocation() to ignore the change-in-progress. Once we're done with our chunk of location-change code in
	add(), we set this back to false. We'll do the same thing when capturing user-entered address changes in checkLocation itself.*/
	ieAtomicLocationChange: null,
	
	/*Private: Create IE-specific DOM nodes and overrides*/
	createIE: function(initialHash) {
		/*write out a hidden iframe for IE and set the amount of time to wait between add() requests*/
		this.waitTime = 400;/*IE needs longer between history updates*/
		var styles = (historyStorage.debugMode
			? 'width: 800px;height:80px;border:1px solid black;'
			: historyStorage.hideStyles
		);
		var iframeID = "rshHistoryFrame";
		var iframeHTML = '<iframe frameborder="0" id="' + iframeID + '" style="' + styles + '" src="/blank.html?' + initialHash + '"></iframe>';
		jQuery('body').append(iframeHTML);
		this.iframe = document.getElementById(iframeID);
	},
	
	/*Private: Create Opera-specific DOM nodes and overrides*/
	createOpera: function() {
		this.waitTime = 400;/*Opera needs longer between history updates*/
		var imgHTML = '<img src="javascript:location.href=\'javascript:dhtmlHistory.checkLocation();\';" style="' + historyStorage.hideStyles + '" />';
		jQuery('body').append(imgHTML);
	},
	
	/*Private: Create Safari-specific DOM nodes and overrides*/
	createSafari: function() {
		var formID = "rshSafariForm";
		var stackID = "rshSafariStack";
		var lengthID = "rshSafariLength";
		var formStyles = historyStorage.debugMode ? historyStorage.showStyles : historyStorage.hideStyles;
		var inputStyles = (historyStorage.debugMode
			? 'width:800px;height:20px;border:1px solid black;margin:0;padding:0;'
			: historyStorage.hideStyles
		);
		var safariHTML = '<form id="' + formID + '" style="' + formStyles + '">'
			+ '<input type="text" style="' + inputStyles + '" id="' + stackID + '" value="[]"/>'
			+ '<input type="text" style="' + inputStyles + '" id="' + lengthID + '" value=""/>'
		+ '</form>';
		jQuery('body').append(safariHTML);
		this.safariStack = document.getElementById(stackID);
		this.safariLength = document.getElementById(lengthID);
		if (!historyStorage.hasKey(this.PAGELOADEDSTRING)) {
			this.safariHistoryStartPoint = history.length;
			this.safariLength.value = this.safariHistoryStartPoint;
		} else {
			this.safariHistoryStartPoint = this.safariLength.value;
		}
	},
	
	/*Private: Safari method to read the history stack from a hidden form field*/
	getSafariStack: function() {
		var r = this.safariStack.value;
		return historyStorage.fromJSON(r);
	},

	/*Private: Safari method to read from the history stack*/
	getSafariState: function() {
		var stack = this.getSafariStack();
		var state = stack[history.length - this.safariHistoryStartPoint - 1];
		return state;
	},			
	/*Private: Safari method to write the history stack to a hidden form field*/
	putSafariState: function(newLocation) {
	    var stack = this.getSafariStack();
	    stack[history.length - this.safariHistoryStartPoint] = newLocation;
	    this.safariStack.value = historyStorage.toJSON(stack);
	},

	/*Private: Notify the listener of new history changes.*/
	fireHistoryEvent: function(newHash) {
		/*extract the value from our history storage for this hash*/
		var historyData = historyStorage.get(newHash);
		/*call our listener*/
		this.listener.call(null, newHash, historyData);
	},
	
	/*Private: See if the browser has changed location. This is the primary history mechanism for Firefox. For IE, we use this to
	handle an important edge case: if a user manually types in a new hash value into their IE location bar and press enter, we want to
	to intercept this and notify any history listener.*/
	checkLocation: function() {
		
		/*Ignore any location changes that we made ourselves for browsers other than IE*/
		if (!this.isIE && this.ignoreLocationChange) {
			this.ignoreLocationChange = false;
			return;
		}

		/*If we are dealing with IE and we are in the middle of making a location change from an iframe, ignore it*/
		if (!this.isIE && this.ieAtomicLocationChange) {
			return;
		}
		
		/*Get hash location*/
		var hash = this.getCurrentLocation();

		/*Do nothing if there's been no change*/
		if (hash == this.currentLocation) {
			return;
		}

		/*In IE, users manually entering locations into the browser; we do this by comparing the browser's location against the
		iframe's location; if they differ, we are dealing with a manual event and need to place it inside our history, otherwise
		we can return*/
		this.ieAtomicLocationChange = true;

		if (this.isIE && this.getIframeHash() != hash) {
			this.iframe.src = "/blank.html?" + hash;
		}
		else if (this.isIE) {
			/*the iframe is unchanged*/
			return;
		}

		/*Save this new location*/
		this.currentLocation = hash;

		this.ieAtomicLocationChange = false;

		/*Notify listeners of the change*/
		this.fireHistoryEvent(hash);
	},

	/*Private: Get the current location of IE's hidden iframe.*/
	getIframeHash: function() {
		var doc = this.iframe.contentWindow.document;
		var hash = String(doc.location.search);
		if (hash.length == 1 && hash.charAt(0) == "?") {
			hash = "";
		}
		else if (hash.length >= 2 && hash.charAt(0) == "?") {
			hash = hash.substring(1);
		}
		return hash;
	},

	/*Private: Remove any leading hash that might be on a location.*/
	removeHash: function(hashValue) {
		var r;
		if (hashValue === null || hashValue === undefined) {
			r = null;
		}
		else if (hashValue === "") {
			r = "";
		}
		else if (hashValue.length == 1 && hashValue.charAt(0) == "#") {
			r = "";
		}
		else if (hashValue.length > 1 && hashValue.charAt(0) == "#") {
			r = hashValue.substring(1);
		}
		else {
			r = hashValue;
		}
		return r;
	},

	/*Private: For IE, tell when the hidden iframe has finished loading.*/
	iframeLoaded: function(newLocation) {
		/*ignore any location changes that we made ourselves*/
		if (this.ignoreLocationChange) {
			this.ignoreLocationChange = false;
			return;
		}

		/*Get the new location*/
		var hash = String(newLocation.search);
		if (hash.length == 1 && hash.charAt(0) == "?") {
			hash = "";
		}
		else if (hash.length >= 2 && hash.charAt(0) == "?") {
			hash = hash.substring(1);
		}
		/*Keep the browser location bar in sync with the iframe hash*/
		window.location.hash = hash;

		/*Notify listeners of the change*/
		this.fireHistoryEvent(hash);
	}

};

/*
	historyStorage: An object that uses a hidden form to store history state across page loads. The mechanism for doing so relies on
	the fact that browsers save the text in form data for the life of the browser session, which means the text is still there when
	the user navigates back to the page. This object can be used independently of the dhtmlHistory object for caching of Ajax
	session information.
	
	dependencies: 
		* json2007.js (included in a separate file) or alternate JSON methods passed in through an options bundle.
*/
window.historyStorage = {
	
	/*Public: Set up our historyStorage object for use by dhtmlHistory or other objects*/
	setup: function(options) {
		
		/*
			options - object to store initialization parameters - passed in from dhtmlHistory or directly into historyStorage
			options.debugMode - boolean that causes hidden form fields to be shown for development purposes.
			options.toJSON - function to override default JSON stringifier
			options.fromJSON - function to override default JSON parser
		*/
		
		/*process init parameters*/
		if (typeof options !== "undefined") {
			if (options.debugMode) {
				this.debugMode = options.debugMode;
			}
			if (options.toJSON) {
				this.toJSON = options.toJSON;
			}
			if (options.fromJSON) {
				this.fromJSON = options.fromJSON;
			}
		}		
		
		/*write a hidden form and textarea into the page; we'll stow our history stack here*/
		var formID = "rshStorageForm";
		var textareaID = "rshStorageField";
		var formStyles = this.debugMode ? historyStorage.showStyles : historyStorage.hideStyles;
		var textareaStyles = (historyStorage.debugMode
			? 'width: 800px;height:80px;border:1px solid black;'
			: historyStorage.hideStyles
		);
		var textareaHTML = '<form id="' + formID + '" style="' + formStyles + '">'
			+ '<textarea id="' + textareaID + '" style="' + textareaStyles + '"></textarea>'
		+ '</form>';
		jQuery('body').append(textareaHTML);
		this.storageField = document.getElementById(textareaID);
		if (typeof window.opera !== "undefined") {
			this.storageField.focus();/*Opera needs to focus this element before persisting values in it*/
		}
	},
	
	/*Public*/
	put: function(key, value) {
		this.assertValidKey(key);
		/*if we already have a value for this, remove the value before adding the new one*/
		if (this.hasKey(key)) {
			this.remove(key);
		}
		/*store this new key*/
		this.storageHash[key] = value;
		/*save and serialize the hashtable into the form*/
		this.saveHashTable();
	},

	/*Public*/
	get: function(key) {
		this.assertValidKey(key);
		/*make sure the hash table has been loaded from the form*/
		this.loadHashTable();
		var value = this.storageHash[key];
		if (value === undefined) {
			value = null;
		}
		return value;
	},

	/*Public*/
	remove: function(key) {
		this.assertValidKey(key);
		/*make sure the hash table has been loaded from the form*/
		this.loadHashTable();
		/*delete the value*/
		delete this.storageHash[key];
		/*serialize and save the hash table into the form*/
		this.saveHashTable();
	},

	/*Public: Clears out all saved data.*/
	reset: function() {
		this.storageField.value = "";
		this.storageHash = {};
	},

	/*Public*/
	hasKey: function(key) {
		this.assertValidKey(key);
		/*make sure the hash table has been loaded from the form*/
		this.loadHashTable();
		return (typeof this.storageHash[key] !== "undefined");
	},

	/*Public*/
	isValidKey: function(key) {
		return (typeof key === "string");
	},
	
	/*Public - CSS strings utilized by both objects to hide or show behind-the-scenes DOM elements*/
	showStyles: 'border:0;margin:0;padding:0;',
	hideStyles: 'left:-1000px;top:-1000px;width:1px;height:1px;border:0;position:absolute;',
	
	/*Public - debug mode flag*/
	debugMode: false,
	
	/*- - - - - - - - - - - -*/

	/*Private: Our hash of key name/values.*/
	storageHash: {},

	/*Private: If true, we have loaded our hash table out of the storage form.*/
	hashLoaded: false, 

	/*Private: DOM reference to our history field*/
	storageField: null,

	/*Private: Assert that a key is valid; throw an exception if it not.*/
	assertValidKey: function(key) {
		var isValid = this.isValidKey(key);
		if (!isValid && this.debugMode) {
			throw new Error("Please provide a valid key for window.historyStorage. Invalid key = " + key + ".");
		}
	},

	/*Private: Load the hash table up from the form.*/
	loadHashTable: function() {
		if (!this.hashLoaded) {	
			var serializedHashTable = this.storageField.value;
			if (serializedHashTable !== "" && serializedHashTable !== null) {
				this.storageHash = this.fromJSON(serializedHashTable);
				this.hashLoaded = true;
			}
		}
	},
	/*Private: Save the hash table into the form.*/
	saveHashTable: function() {
		this.loadHashTable();
		var serializedHashTable = this.toJSON(this.storageHash);
		this.storageField.value = serializedHashTable;
	},
	/*Private: Bridges for our JSON implementations - both rely on 2007 JSON.org library - can be overridden by options bundle*/
	toJSON: function(o) {
		return o.toJSONString();
	},
	fromJSON: function(s) {
		return s.parseJSON();
	}
};
/*extern jQuery */
/*jslint browser: true, passfail: false, undef: false */
var webslinger;
if (jQuery) (function($) {
	(function() {
		var mutators = [];
		if (!$.mutations) $.mutations = {};
		$.extend($.mutations, {
			applier:	function(ctx) {
				if (!ctx) ctx = document;
				for (var i = 0; i < mutators.length; i++) {
					try {
						mutators[i](ctx);
					} catch (e) {
						alert(i + '->' + e);
					}
				}
			},
			delayedAdder:	function(f) {
				mutators[mutators.length] = f;
			},
			immediateAdder:	function(f) {
				mutators[mutators.length] = f;
				f(document);
			},
			init:	function() {
				$.mutations.applier();
				$.addMutator = $.mutations.immediateAdder;
			}
		});
		$.extend({
			addMutator: $.mutations.delayedAdder
		});
		$.fn.applyMutators = function() {
			webslinger.timer.log('applying mutators');
			webslinger.createTimer();
			this.each(function() {
				$.mutations.applier(this);
			});
			webslinger.timer.pop('applied mutators');
			return this;
		};
		$(function() { $.mutations.init(); });
	})();

	(function() {
		$.extend({
			runWhenAttached: function(element, callback) {
				var ptr = element;
				while (ptr != null) {
					if (ptr == document.body) break;
					ptr = ptr.parentNode;
				}
				if (ptr == null) {
					setTimeout(function() {
						$.runIfAttached(element, callback);
					}, 50);
					return;
				}
				setTimeout(function() {
					callback.call(element);
				}, 0);
				return;
			}
		});
		$.fn.extend({
			runWhenAttached:	function(callback) {
				return this.each(function() {
					$.runWhenAttached(this, callback);
				});
			}
		});
	})();
	(function() {
	 	var resetter;
		$(function() {
			$('body').click(function() {
				if (resetter) resetter();
			});
		});
		$.fn.transientClick = function(checker, opener) {
			this.each(function() {
				$(this).click(function() {
					if (resetter) {
						resetter();
						return false;
					}
					var args = $.makeArray(arguments);
					if (checker.apply(this, args)) {
						var closer = opener.apply(this, args);
						resetter = function() {
							resetter = null;
							closer();
						};
					}
					return false;
				});

			});
		};
	})();

	if (false) if (jQuery.browser.msie || true) {
		jQuery.addMutator(function(ctx) {
			var jBody = jQuery("body");
			jQuery("form", ctx).each(function() {
				var jForm = jQuery(this);
				jForm.prepend("<input type='hidden' />");
				var hidden = jForm.get(0).firstChild;
				jForm.find("button").each(function() {
					var name = this.getAttribute("name");
					this.removeAttribute("name");
					var value = this.getAttribute("value");
					this.removeAttribute("value");
					jQuery(this).click(function() {
						hidden.setAttribute("name", name);
						hidden.setAttrbute("value", value);
						return true;
					});
				});
			});
		});
	}
/*
	Object.prototype.super = function(name) {
		var args = [];
		for (var i = 1; i < arguments.length; i++) args.push(arguments[i]);
	};
*/
	webslinger = function(path) {
		if (window == this) return new webslinger(path);
		if (path && path[path.length - 1] != '/') path += '/';
		this._path = path;
	};

	webslinger.cleanupFunction = function() {
		var args = $.makeArray(arguments);
		var main = args.shift();
		return function() {
			try {
				return main.apply(this, $.makeArray(arguments));
			} finally {
				for (var i = 0; i < args.length; i++) {
					try {
						args[i]();
					} catch(e) {
						// ignore
					}
				}
			}
		};
	};

	// http://www.howtocreate.co.uk/tutorials/javascript/eventinfo
	webslinger.fixMouseEvent = function(e) {
		if( !e ) {
			if( window.event ) {
				//Internet Explorer
				e = window.event;
			} else {
				//total failure, we have no way of referencing the event
				return;
			}
		}
		if( typeof( e.pageX ) == 'number' ) {
			//most browsers
			var xcoord = e.pageX;
			var ycoord = e.pageY;
		} else if( typeof( e.clientX ) == 'number' ) {
			//Internet Explorer and older browsers
			//other browsers provide this, but follow the pageX/Y branch
			var xcoord = e.clientX;
			var ycoord = e.clientY;
			var badOldBrowser = ( window.navigator.userAgent.indexOf( 'Opera' ) + 1 ) ||
			( window.ScriptEngine && ScriptEngine().indexOf( 'InScript' ) + 1 ) ||
			( navigator.vendor == 'KDE' );
			if( !badOldBrowser ) {
				if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
					//IE 4, 5 & 6 (in non-standards compliant mode)
					xcoord += document.body.scrollLeft;
					ycoord += document.body.scrollTop;
				} else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
					//IE 6 (in standards compliant mode)
					xcoord += document.documentElement.scrollLeft;
					ycoord += document.documentElement.scrollTop;
				}
			}
		} else {
			//total failure, we have no way of obtaining the mouse coordinates
			return;
		}
		return [xcoord, ycoord];
	};

	function indentingString(doSpace, doNewline) {
		var parts = []
		if (doSpace == null) doSpace = true;
		if (doNewline == null) doNewline = true;
		var lastWasNewline = false;
		var indent = '';
	
		this.newline = function() {
			lastWasNewline = true;
			if (doNewline) parts.push('\n');
			return this;
		};

		checkAfterNewline = function() {
			if (!lastWasNewline) return;
			if (doSpace) {
				parts.push(doNewline ? indent : ' ');
			}
			lastWasNewline = false;
		};

		this.push = function() {
			indent += ' ';
			return this;
		};

		this.pop = function() {
			indent = indent.substring(0, indent.length - 1);
			return this;
		};

		this.space = function() {
			checkAfterNewline();
			if (doSpace) parts.push(' ');
			return this;
		};

		this.write = function(s) {
			var i;
			var offset;
			checkAfterNewline();
			for (i = 0, offset = 0; i < s.length; i++) {
				var c = s.charAt(i);
				parts.push(c);
				if (s.charCodeAt(i) == '\n') {
					checkAfterNewline();
					lastWasNewline = true;
				}
			}
			return this;
		};

		this.toString = function() {
			return parts.join('');
		};
	};


	var writeString = function(o, s) {
		s.write('"');
		for (var i = 0; i < o.length; i++) {
			var c = o.substring(i, i + 1);
			switch (c) {
				case "\\": s.write("\\\\"); continue;
				case "/": s.write("\\/"); continue;
				case "\"": s.write("\\\""); continue;
				case "\b": s.write("\\b"); continue;
				case "\f": s.write("\\f"); continue;
				case "\n": s.write("\\n"); continue;
				case "\r": s.write("\\r"); continue;
				case "\t": s.write("\\t"); continue;
			}
			var code = o.charCodeAt(i);
			if (32 <= code && code >= 256) {
				s.write("\\u");
				var n = code.toString(16);
				for (var j = 4 - n.length; j > 0; j--) s.write("0");
				s.write(n);
			} else {
				s.write(c);
			}
  		}
		s.write('"');
	};

	var writeArray = function(o, s) {
		s.write('[').push();
		if (o.length) s.newline();
		for (var i = 0; i < o.length; i++) {
			writeObject(o[i], s);
			if (i != o.length - 1) s.write(',');
			s.newline();
		}
		s.pop().write(']');
	};

	var writeMap = function(o, s) {
		s.write('{').push();
		var i = 0;
		for (var n in o) {
			if (i == 0) {
				s.newline();
			} else {
				s.write(',').newline();
			}
			writeObject(n, s);
			s.write(':').space();
			writeObject(o[n], s);
			i++;
		}
		if (i != 0) s.write(',').newline();
		s.pop().write('}');
	};

	var writeObject = function(o, s) {
		if (o == null) {
			s.write("null");
		} else if (typeof o == 'string') {
			writeString(o, s);
		} else if (o.constructor == Array) {
			writeArray(o, s);
		} else if (typeof o == 'object') {
			writeMap(o, s);
		} else {
			s.write("" + o);
		}
	};

	webslinger.toJSON = function(o, doSpace, doNewline) {
		var s = new indentingString(doSpace, doNewline);
		writeObject(o, s);
		return s.toString();
	};

	webslinger.defaultErrorHandler = null;

	webslinger.ajax = function(path, payload, context, callback, errorHandler) {
		var args = [];
		for (var i = 0; i < arguments.length; i++) args.push(arguments[i]);
		path = args.shift();
		callback = args.pop();
		if (args[args.length - 1] instanceof Function) {
			errorHandler = callback;
			callback = args.pop();
		} else {
			if (webslinger.defaultErrorHandler) {
				errorHandler = webslinger.defaultErrorHandler;
			} else {
				errorHandler = function(type, data) {
					switch (type) {
						case "request":
							alert("error(" + data.path + ")[" + data.type + "][" + data.exc + "]");
							callback(null, {type: "request", ajax: data});
							break;
						case "client":
							alert("client error(" + data + ")");
							callback(null, {type: "client", exc: data});
							break;
						case "server":
							alert("server error");
							callback(null, {type: "server", error: data});
							break;
					}
				};
			}
		}
		if (args.length == 2) {
			if (args[0] instanceof String) {
				payload = args.shift();
				context = args.shift();
			} else if (args[0] instanceof Object) {
				context = args.shift();
				payload = args.shift();
			} else {
				payload = null;
				context = null;
			}
		} else if (args.length == 1) {
			if (args[0] instanceof String) {
				payload = args.shift();
				context = null;
			} else if (args[0] instanceof Object) {
				context = args.shift();
				payload = null;
			} else {
				payload = null;
				context = null;
			}
		} else {
			payload = null;
			context = null;
		}
		if (path.substring(0, 1) != '/') {
			path = (this._path ? this._path + (this._path[this._path.length - 1] == '/' ? '' : '/')  : '/') + path;
		}
		if (!context) context = {};
		var data = {
			payload: payload,
			context: context
		};
		var encodedData = webslinger.toJSON(data);
		return {
			async:		true,
			contentType:	"text/x-json; charset=UTF-8",
			data:		encodedData,
			dataType:	"json",
			error:		function(req, type, exc) {
				alert('error{' + req + ', ' + type + ', ' + exc + '}');
				errorHandler("request", {path: path, req: req, type: type, exc: exc});
				throw exc;
			},
			processData:	false,
			success:	function(data) {
				//alert("event data=" + webslinger.toJSON(data));
				if (data.hub) {
					for (var i = 0; i < data.hub.length; i++) {
						var item = data.hub[i];
						OpenAjax.hub.publish(item.topic, item.data);
					}
				}
				if (data.result != null) {
					try {
						callback(data.result);
					} catch (e) {
						errorHandler("client", e);
					}
				} else {
					errorHandler("server", data.error);
				}
			},
			type:		"post",
			url:		path
		};
	};
	webslinger.event = function() {
		var args = [];
		for (var i = 0; i < arguments.length; i++) args.push(arguments[i]);
		jQuery.ajax(webslinger.ajax.apply(webslinger, args));
		return this;
	};

	webslinger.prototype.event = webslinger.event;

	(function() {
		function sendWidgetMessage(jThis, msg, widgetName, context) {
			if (!(widgetName instanceof String) && !context) {
				context = widgetName;
				widgetName = null;
			}
			return jThis.each(function() {
				var possibleName = widgetName;
				if (!possibleName) possibleName = this.getAttribute("wsWidgetName");
				if (!possibleName) return;
				OpenAjax.hub.publish("widget." + possibleName + "." + msg, context);
			});
		}
		jQuery.fn.WidgetClear = function(widgetName) { return sendWidgetMessage(this, "clear", widgetName); };
		jQuery.fn.WidgetFill = function(widgetName) { return sendWidgetMessage(this, "fill", widgetName); };
		jQuery.fn.WidgetRefresh = function(widgetName, context) { return sendWidgetMessage(this, "refresh", widgetName, context); };
		jQuery.fn.WidgetSetName = function(widgetName) {
			return this.attr("wsWidgetName", widgetName);
		};
		function onResize(ptr) {
			var widget;
			while (ptr != null) {
				if (!ptr.getAttribute) break;
				var name = ptr.getAttribute("wsWidgetName");
				if (name != null) {
					OpenAjax.hub.publish("widget." + name + ".resize");
					break;
				}
				ptr = ptr.parentNode;
			}
		}
		jQuery.fn.WidgetSendResizeEvent = function() {
			this.each(function() { onResize(this.parentNode); });
		}
		jQuery.addMutator(function(ctx) {
			jQuery("img", ctx).load(function() { onResize(this.parentNode); });
		});
	})();

	jQuery.fn.CommunicationPane = function() {
		return this.each(function() {
			var jThis = jQuery(this);
			var widgetName = jThis.attr("wsWidgetName");
			var urlBase = jThis.attr("communicationsBase");
			var listUrl = jThis.attr("communicationsList");
			var messageUrl = jThis.attr("communicationsMessage");
			var editUrl = jThis.attr("communicationsEdit");
			var messagePane = jThis.find(".Communications-Message").WidgetSetName(widgetName + ":Message");
			var listContainer = jThis.find(".Communications-List").WidgetSetName(widgetName + ":List");
			var processor = new webslinger(urlBase);
			var messagePaneHide = function(callback) {
				callback();
			};
			OpenAjax.hub.subscribe(
				"widget." + widgetName + ":List.refresh",
				function(name, context) {
					processor.event(
						listUrl,
						context,
						function(result) {
							var scrollTop = listContainer.scrollTop();
							listContainer.WidgetClear().empty().append(result).scrollTop(scrollTop).WidgetFill();
						}
					);
				}
			);
			OpenAjax.hub.subscribe("widget." + widgetName + ":List.clear", function() {
				if (messageUrl && messagePane.length) {
					messagePaneHide(function() {
						messagePane.WidgetClear().empty();
					});
				}
			});
			OpenAjax.hub.subscribe("widget." + widgetName + ":List.fill", function() {
				listContainer.find("[@listSort]").css("cursor", "pointer").click(function() {
					listContainer.WidgetRefresh({sort: this.getAttribute("listSort"), sortOrder: this.getAttribute("listSortOrder")});
				});
				var lastCommChosen;
				var listRows = listContainer.find("[@listCommId][@listCommType]");
				if (messageUrl && messagePane.length) {
					listRows.css("cursor", "pointer").click(function() {
						if (lastCommChosen) lastCommChosen.removeClass("CommListMessageSelected");
						lastCommChosen = jQuery("[@listCommId='" + this.getAttribute("listCommId") + "']", this.parentNode).addClass("CommListMessageSelected");
						var commId = this.getAttribute("listCommId");
						var messageResult;
						//alert("row clicked: " + alertId);
						var latch = webslinger.Latch(
							2,
							function() {
								//alert("trigger called: loadResult=" + loadResult);
								messagePane.empty();
								messagePane.append(messageResult);
								/*
								messagePane.find("*[@lprCommId][@lprActionType]").click(function() {
									var commId = this.getAttribute("lprCommId");
									var type = this.getAttribute("lprActionType");

								});
								*/
								messagePane.show(500);
								messagePane.WidgetFill();
								messagePaneHide = function(callback) {
									if (messagePane.is(":visible")) {
										messagePane.hide(500, callback);
									} else {
										callback();
									}
								};
							}
						);
						messagePaneHide(latch);
						processor.event(
							messageUrl,
							{
								commId: commId
							},
							function(result) {
								messageResult = result;
								latch();
							}
						);
					});
					messagePane.empty();
				}
				if (editUrl) {
					listRows.css("cursor", "pointer").dblclick(function() {
						if (lastCommChosen) lastCommChosen.removeClass("CommListMessageSelected");
						lastCommChosen = jQuery("[@listCommId='" + this.getAttribute("listCommId") + "']", this.parentNode).addClass("CommListMessageSelected");
						var commId = this.getAttribute("listCommId");
						jQuery(this).openDialog(urlBase + "/" + editUrl + "/" + commId, "EditShowing", "Edit"); 
					});
				}
			});
			listContainer.WidgetFill();
			jThis.WidgetFill();
		});
	};

	webslinger.remotePane = function(id, path) {
		OpenAjax.hub.subscribe(
			"widget." + id + ".refresh",
			function(name, context) {
				webslinger.event(
					path,
					context,
					function(result) {
						var container = jQuery("#" + id);
						OpenAjax.hub.publish("widget." + id + ".clear", container);
						container.empty().append(result);
						try {
							container.applyMutators();
						} catch (e) {
							alert("e=" + e);
						}
						OpenAjax.hub.publish("widget." + id + ".fill", container);
					}
				);
			}
		);
		jQuery(
			function() {
				OpenAjax.hub.publish("widget." + id + ".fill", jQuery("#" + id));
			}
		);
		var f = function(name, context) {
			OpenAjax.hub.publish("widget." + id + ".refresh", context);
		}
		for (var i = 2; i < arguments.length; i++) {
			OpenAjax.hub.subscribe(arguments[i], f);
		}
		var refreshTimer;
		var thiz = {
			refreshPeriod:	function(timeout) {
				if (refreshTimer) clearTimeout(refreshTimer);
				var timerFunction = function() {
					OpenAjax.hub.publish("widget." + id + ".refresh");
					setTimeout(timerFunction, timeout);
				};
				refreshTimer = setTimeout(timerFunction, timeout);
				return thiz;
			}
		};
		return thiz;
	};

	webslinger.Latch = function(count, trigger) {
		var f = function() {
			f.count--;
			if (f.count == 0) trigger();
		};
		f.incr = function() {
			f.count++;
		};
		f.count = count;
		if (f.count == 0) trigger();
		return f;
	};

	webslinger.chainFunctions = function() {
		var funcs = $.makeArray(arguments);
		return function() {
			for (var i = 0; i < funcs.length; i++) {
				if (typeof funcs[i] == 'function') {
					funcs[i]();
				}
			}
		};
	};

	webslinger.createTimer = function() {
		var oldTimer = webslinger.timer;
		var startTime = new Date().getTime();
		var times = [];
		return webslinger.timer = {
			log:	function(msg) {
				times[times.length] = [msg, new Date().getTime()];
			},
			msg:	function() {
				var m = [];
				var lastTime = startTime;
				for (var i = 0; i < times.length; i++) {
					var line = times[i];
					m.push(', ', line[0], ': ', (line[1] - lastTime));
					lastTime = line[1];
				}
				m.shift();
				webslinger.timer = oldTimer;
				m.push(', total: ', (new Date().getTime() - startTime));
				return m.join('');
			},
			pop:	function(msg) {
				var m = webslinger.timer.msg();
				webslinger.timer.log(msg + '(' + m + ')');
			}
		};
	};
	webslinger.timer = {
		log:	function(msg) { },
		msg:	function() { },
		pop:	function(msg) { }
	};

	(function() {
		// $1 = path
		// $2 = search
		// $3 = hash
		var pathRegex = /^([^?#]*)(?:\?([^#]*))?(?:#(.*))?$/;
		// $1 = protocol
		// $2 = host
		// $3 = port
		// $4 = path
		var urlRegex = /^([^:\/]+:)(?:\/\/([^:\/]+)(?:(:[0-9]+))?)?(.*)$/;
		var defaultPorts = {
			'ftp:':		21,
			'gopher:':	70,
			'http:':	80,
			'https:':	443
		};

		webslinger.url = function() {
			var base, pathname
			if (arguments.length == 0) throw 'Not enough arguments to  url constructor';
			if (arguments.length == 1) {
				pathname = arguments[0];
				base = webslinger.getLocation();
			} else {
				if (typeof arguments[0] == 'string') {
					pathname = arguments[0];
					base = arguments[1];
				} else {
					base = arguments[0];
					pathname = arguments[1];
				}
			}
			var baseParts = urlRegex.exec(pathname);
			this.protocol = null;
			this.host = null;
			this.port = null;
			var pathname;
			if (!baseParts || baseParts.length == 0) {
				// only pathname
				if (base) {
					this.protocol = base.protocol;
					this.host = base.host;
					this.port = base.port;
				} else {
					this.protocol = null;
					this.host = null;
					this.port = null;
				}
			} else {
				this.protocol = baseParts[1];
				this.host = baseParts[2] != null ? baseParts[2] : null;
				this.port = baseParts[3] != null ? parseInt(baseParts[3]) : null;
				pathname = baseParts[4];
				if (!pathname) pathname = '/';
			}
			var pathParts = pathRegex.exec(pathname);
			this.pathname = pathParts[1];
			this.search = pathParts[2];
			this.hash = pathParts[3];
			if (this.search && this.search.length == 0) this.search = null;
			if (this.hash && this.hash.length == 0) this.hash = null;
			if (base) {
				if (!this.pathname) {
					this.pathname = base.pathname;
				} else if (this.pathname.charAt(0) != '/') {
					this.pathname = base.pathname.replace(/[^\/]*$/, '') + this.pathname;
				}
			}
			if (!this.port) this.port = defaultPorts[this.protocol];

			var s = this.protocol;
			if (this.host != null) s += '//' + this.host;
			if (this.port != null && defaultPorts[this.protocol] != this.port) s += ':' + this.port;
			s += this.pathname;
			if (this.search) s += '?' + this.search;
			if (this.hash) s += '#' + this.hash;
			this.href = s;
		};

		webslinger.url.prototype.toString = function() {
			return this.href;
		};

		webslinger.url.prototype.isSameHost = function(o) {
			return this.protocol == o.protocol && this.host == o.host && this.port == o.port;
		};

		webslinger.url.prototype.resolve = function(path) {
			return new webslinger.url(this, path);
		};

		webslinger.url.removeProtocol = function(href) {
			var parts = urlRegex.exec(href);
			return parts ? parts[4] : href;
		};

		webslinger.url.extractBase = function(href) {
			href = webslinger.url.removeProtocol(href);
			if (href.charAt(href.length - 1) == "/") return href;
			//alert("stripping");
			var slash = href.lastIndexOf('/');
			return href.substring(0, slash + 1);
		};

		webslinger.url.fix = function(href) {
			var base = webslinger.getLocation();
			var fixed = new webslinger.url(base, href);
			if (base.isSameHost(fixed)) return urlRegex.exec(fixed.href)[4];
			return fixed.href;
		};
	})();

	(function() {
		var location;
		webslinger.getLocation = function() {
			return location;
		};
		webslinger.setPath = function(path) {
			location = new webslinger.url(location, path);
		};
		webslinger.getPath = function() {
			return location.pathname;
		};
		webslinger.pageReload = function() {
			window.location.href = location.href;
		};
		location = new webslinger.url(window.location.href);
	})();

	OpenAjax.hub.subscribe(
		"mailto",
		function(name, data) {
			alert("mailto[" + webslinger.toJSON(data) + "]");
		}
	);
	OpenAjax.hub.subscribe(
		"page.refresh",
		function(name, data) {
			webslinger.pageReload();
		}
	);
	OpenAjax.hub.subscribe(
		"page.redirect",
		function(name, data) {
			window.location = data.location;
		}
	);

	(function() {
		var loadedScripts = {};
		$.extend({
			getScripts: function() {
				var args = $.makeArray(arguments);
				var callback = args.pop();
				var latch = webslinger.Latch(args.length, callback);
				for (var i = 0; i < args.length; i++) {
					var script = args[i];
					var f = loadedScripts[script];
					if (!f) {
						var queue = [];
						f = loadedScripts[script] = function(callback) {
							queue.push(callback);
						};
						var doneCallback = function() {
							var script = arguments.callee.script;
							//alert('script(' +  script + ') loaded');
							loadedScripts[script] = function(callback) {
								callback();
							};
							for (var i = 0; i < queue.length; i++) queue[i]();
						};
						doneCallback.script = script;
						$.getScript(script, doneCallback);
					} 
					f(latch);
				}
			}
		});
	})();

	(function() {
		var busyHandlers = [];
		var depth = 0;
		function sendBusySignal() {
			for (var i = 0; i < busyHandlers.length; i++) {
				busyHandlers[i]('start');
			}
		}
		function clearBusySignal() {
			for (var i = 0; i < busyHandlers.length; i++) {
				busyHandlers[i]('end');
			}
		}
		webslinger.addBusyHandler = function(handler) {
			busyHandlers[busyHandlers.length] = handler;
		};
		webslinger.removeBusyHandler = function(handler) {
			for (var i = 0; i < busyHandlers.length; i++) {
				if (busyHandlers[i] == handler) {
					busyHandlers.splice(i, 1);
					break;
				}
			}
		};
		webslinger.isBusy = function() {
			return depth > 0;
		};
		webslinger.incrementBusy = function() {
			if (depth == 0) sendBusySignal();
			depth++;
		};
		webslinger.decrementBusy = function() {
			depth--;
			if (depth == 0) clearBusySignal();
		};
		webslinger.createBusyLatch = function() {
			var delegate;
			delegate = function() {
				webslinger.decrementBusy();
				delegate = function() { };
			};
			webslinger.incrementBusy();
			return function() {
				delegate();
			};
		};
		jQuery(function() {
			jQuery('body')
				.ajaxStart(function() { webslinger.incrementBusy(); })
				.ajaxStop(function() { webslinger.decrementBusy(); });
		});
	})();
})(jQuery);
if (jQuery) (function($) {
	function InstallTree(o, state, tree, item) {
		//alert('(' + item[0] + ')li.length=' + li.length);
		item.children('li').each(function() {
			if ($.data(this, 'jquery.wstree:installed')) return;
			$.data(this, 'jquery.wstree:installed', true);
			var node = $(this);
			//alert('li(' + node.attr('href') + ')' + toggle.length + ',' + name.length);
			function setImage(attr) {
				node.children('[closeImg][openImg]').each(function() {
					this.setAttribute('src', this.getAttribute(attr));
				});
			}
			function closeNode() {
				setImage('closeImg');
				node.children(o.actionToggle).removeClass(o.classActionOpened).addClass(o.classActionClosed);
				node.removeClass(o.classOpened).addClass(o.classClosed);
				o.setStatus(state, tree, node, false);
				o.hide(tree, o.getTree(tree, node), function(item) {
					o.removeTree(tree, item);
				});
			}
			function openNode() {
				setImage('openImg');
				node.children(o.actionToggle).removeClass(o.classActionClosed).addClass(o.classActionOpened);
				node.removeClass(o.classClosed).addClass(o.classOpened);
				o.rpc(tree, node, function(item) {
					o.show(tree, o.addTree(tree, node, item), function(item) {
						InstallTree(o, state, tree, item);
					});
				});
				o.setStatus(state, tree, node, true);
			}
			function toggleNode() {
				if (o.getStatus(state, tree, node)) {
					closeNode();
				} else {
					openNode();
				}
			}
			node.bind(o.eventNodeOpen, function() {
				//alert('eventNodeOpen');
				//if (o.getStatus(state, tree, node)) return;
				tree.trigger(o.eventNodeOpen, [node]);
				openNode();
				return false;
			});
			node.bind(o.eventNodeToggle, function() {
				//alert('eventNodeToggle');
				tree.trigger(o.eventNodeToggle, [node]);
				toggleNode();
				return false;
			});
			node.bind(o.eventNodeClose, function() {
				//alert('eventNodeClose');
				tree.trigger(o.eventNodeClose, [node]);
				closeNode();
				return false;
			});
			node.bind(o.eventNodeSelect, function() {
				//alert('eventNodeSelect');
				if (!o.getStatus(state, tree, node)) openNode();
				tree.trigger(o.eventNodeSelect, [node]);
				return false;
			});
			node.children(o.actionSelect).click(function() { node.trigger(o.eventNodeSelect); return false; });
			node.children(o.actionOpen).click(function() { node.trigger(o.eventNodeOpen); return false; });
			node.children(o.actionToggle).click(function() { node.trigger(o.eventNodeToggle); return false; });
			if (o.getStatus(state, tree, node)) {
				node.trigger(o.eventNodeOpen);
			} else {
				node.trigger(o.eventNodeClose);
			}
		});
	}
	$.fn.extend({
		wstree: function(o) {
			o = $.extend({
				eventNodeOpen:		'Tree:Node:Open',
				eventNodeToggle:	'Tree:Node:Toggle',
				eventNodeClose:		'Tree:Node:Close',
				eventNodeSelect:	'Tree:Node:Select',

				classOpened:		'TreeNodeOpened',
				classClosed:		'TreeNodeClosed',

				actionToggle:		'.TreeActionToggle',
				actionSelect:		'.TreeActionSelect',
				actionOpen:		'.TreeActionOpen',
				classIcon:		'.TreeNodeIcon',

				classActionOpened:	'TreeActionOpened',
				classActionClosed:	'TreeActionClosed',

				show:			function(tree, node, callback) {
					if (false && !node.is(":hidden")) {
						callback(node);
						return;
					}
					node.slideDown();//, function() {
					//	callback(node);
					//});
					callback(node);
				},
				hide:			function(tree, node, callback) {
					if (node.is(":hidden")) {
						callback(node);
						return;
					}
					node.slideUp(function() {
						callback(node);
					});
				},

				addTree:		function(tree, node, item) {
					var ptr = node.children('ul');
					if (item != null) {
						ptr.remove();
						ptr = node.append(item).children('ul').hide();
					}
					return ptr;
				},
				removeTree:		function(tree, item) {
					item.remove();
				},
				getTree:		function(tree, node) {
					return node.children('ul');
				},
							
				rpc:			function(tree, node, callback) {
					callback();
				},

				getStatus:		function(state, tree, node) {
					return state[node.attr('href')];
				},
				setStatus:		function(state, tree, node, value) {
					if (value) {
						state[node.attr('href')] = true;
					} else {
						delete state[node.attr('href')];
					}
				}
			}, o);
			this.each(function() {
				var tree = $(this);
				var state = o.state ? o.state : {};
				try {
					InstallTree(o, state, tree, tree);
					o.show(tree, tree, function(item) { });
				} catch (e) {
					//alert(e);
				}
				//alert('tree install done');
			});
			return this;
		}
	});
})(jQuery);
/*
 * jQuery form plugin
 * @requires jQuery v1.1 or later
 *
 * Examples 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
 *
 * Revision: $Id$
 * Version: 1.0.3
 */
 (function($) {
/**
 * ajaxSubmit() provides a mechanism for submitting an HTML form using AJAX.
 *
 * ajaxSubmit accepts a single argument which can be either a success callback function
 * or an options Object.  If a function is provided it will be invoked upon successful
 * completion of the submit and will be passed the response from the server.
 * If an options Object is provided, the following attributes are supported:
 *
 *  target:   Identifies the element(s) in the page to be updated with the server response.
 *            This value may be specified as a jQuery selection string, a jQuery object,
 *            or a DOM element.
 *            default value: null
 *
 *  url:      URL to which the form data will be submitted.
 *            default value: value of form's 'action' attribute
 *
 *  type:     The method in which the form data should be submitted, 'GET' or 'POST'.
 *            default value: value of form's 'method' attribute (or 'GET' if none found)
 *
 *  beforeSubmit:  Callback method to be invoked before the form is submitted.
 *            default value: null
 *
 *  success:  Callback method to be invoked after the form has been successfully submitted
 *            and the response has been returned from the server
 *            default value: null
 *
 *  dataType: Expected dataType of the response.  One of: null, 'xml', 'script', or 'json'
 *            default value: null
 *
 *  semantic: Boolean flag indicating whether data must be submitted in semantic order (slower).
 *            default value: false
 *
 *  resetForm: Boolean flag indicating whether the form should be reset if the submit is successful
 *
 *  clearForm: Boolean flag indicating whether the form should be cleared if the submit is successful
 *
 *
 * The 'beforeSubmit' callback can be provided as a hook for running pre-submit logic or for
 * validating the form data.  If the 'beforeSubmit' callback returns false then the form will
 * not be submitted. The 'beforeSubmit' callback is invoked with three arguments: the form data
 * in array format, the jQuery object, and the options object passed into ajaxSubmit.
 * The form data array takes the following form:
 *
 *     [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
 *
 * If a 'success' callback method is provided it is invoked after the response has been returned
 * from the server.  It is passed the responseText or responseXML value (depending on dataType).
 * See jQuery.ajax for further details.
 *
 *
 * The dataType option provides a means for specifying how the server response should be handled.
 * This maps directly to the jQuery.httpData method.  The following values are supported:
 *
 *      'xml':    if dataType == 'xml' the server response is treated as XML and the 'success'
 *                   callback method, if specified, will be passed the responseXML value
 *      'json':   if dataType == 'json' the server response will be evaluted and passed to
 *                   the 'success' callback, if specified
 *      'script': if dataType == 'script' the server response is evaluated in the global context
 *
 *
 * Note that it does not make sense to use both the 'target' and 'dataType' options.  If both
 * are provided the target will be ignored.
 *
 * The semantic argument can be used to force form serialization in semantic order.
 * This is normally true anyway, unless the form contains input elements of type='image'.
 * If your form must be submitted with name/value pairs in semantic order and your form
 * contains an input of type='image" then pass true for this arg, otherwise pass false
 * (or nothing) to avoid the overhead for this logic.
 *
 *
 * When used on its own, ajaxSubmit() is typically bound to a form's submit event like this:
 *
 * $("#form-id").submit(function() {
 *     $(this).ajaxSubmit(options);
 *     return false; // cancel conventional submit
 * });
 *
 * When using ajaxForm(), however, this is done for you.
 *
 * @example
 * $('#myForm').ajaxSubmit(function(data) {
 *     alert('Form submit succeeded! Server returned: ' + data);
 * });
 * @desc Submit form and alert server response
 *
 *
 * @example
 * var options = {
 *     target: '#myTargetDiv'
 * };
 * $('#myForm').ajaxSubmit(options);
 * @desc Submit form and update page element with server response
 *
 *
 * @example
 * var options = {
 *     success: function(responseText) {
 *         alert(responseText);
 *     }
 * };
 * $('#myForm').ajaxSubmit(options);
 * @desc Submit form and alert the server response
 *
 *
 * @example
 * var options = {
 *     beforeSubmit: function(formArray, jqForm) {
 *         if (formArray.length == 0) {
 *             alert('Please enter data.');
 *             return false;
 *         }
 *     }
 * };
 * $('#myForm').ajaxSubmit(options);
 * @desc Pre-submit validation which aborts the submit operation if form data is empty
 *
 *
 * @example
 * var options = {
 *     url: myJsonUrl.php,
 *     dataType: 'json',
 *     success: function(data) {
 *        // 'data' is an object representing the the evaluated json data
 *     }
 * };
 * $('#myForm').ajaxSubmit(options);
 * @desc json data returned and evaluated
 *
 *
 * @example
 * var options = {
 *     url: myXmlUrl.php,
 *     dataType: 'xml',
 *     success: function(responseXML) {
 *        // responseXML is XML document object
 *        var data = $('myElement', responseXML).text();
 *     }
 * };
 * $('#myForm').ajaxSubmit(options);
 * @desc XML data returned from server
 *
 *
 * @example
 * var options = {
 *     resetForm: true
 * };
 * $('#myForm').ajaxSubmit(options);
 * @desc submit form and reset it if successful
 *
 * @example
 * $('#myForm).submit(function() {
 *    $(this).ajaxSubmit();
 *    return false;
 * });
 * @desc Bind form's submit event to use ajaxSubmit
 *
 *
 * @name ajaxSubmit
 * @type jQuery
 * @param options  object literal containing options which control the form submission process
 * @cat Plugins/Form
 * @return jQuery
 */
$.fn.ajaxSubmit = function(options) {
    if (typeof options == 'function')
        options = { success: options };

    options = $.extend({
        url:  this.attr('action') || window.location,
        type: this.attr('method') || 'GET'
    }, options || {});

    var a = this.formToArray(options.semantic);

    // give pre-submit callback an opportunity to abort the submit
    if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) return this;

    // fire vetoable 'validate' event
    var veto = {};
    $.event.trigger('form.submit.validate', [a, this, options, veto]);
    if (veto.veto)
        return this;

    var q = $.param(a);//.replace(/%20/g,'+');

    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).attr("innerHTML", data).evalScripts().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;

    if (options.iframe || found) // options.iframe allows user to force iframe mode
        fileUpload();
    else
        $.ajax(options);

    // fire 'notify' event
    $.event.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' + $.fn.ajaxSubmit.counter++;
        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() {
            $io.appendTo('body');
            // jQuery's event binding doesn't work for iframe events in IE
            io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false);
            
            // make sure form attrs are set
            var encAttr = form.encoding ? 'encoding' : 'enctype';
            var t = $form.attr('target');
            $form.attr({
                target:   id,
                method:  'POST',
                encAttr: 'multipart/form-data',
                action:   opts.url
            });

            // support timout
            if (opts.timeout)
                setTimeout(function() { timedOut = true; cb(); }, opts.timeout);

            form.submit();
            $form.attr('target', t); // reset target
        }, 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;
                
                if (opts.dataType == 'json' || opts.dataType == 'script') {
                    var ta = doc.getElementsByTagName('textarea')[0];
                    data = ta ? ta.value : xhr.responseText;
                    if (opts.dataType == 'json')
                        eval("data = " + data);
                    else
                        $.globalEval(data);
                }
                else if (opts.dataType == 'xml') {
                    data = xhr.responseXML;
                    if (!data && xhr.responseText != null)
                        data = toXml(xhr.responseText);
                }
                else {
                    data = xhr.responseText;
                }
            }
            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.ajaxSubmit.counter = 0; // used to create unique iframe ids

/**
 * 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.
 *
 * Note that for accurate x/y coordinates of image submit elements in all browsers
 * you need to also use the "dimensions" plugin (this method will auto-detect its presence).
 *
 * 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.  See ajaxSubmit for a full description of the options argument.
 *
 *
 * @example
 * var options = {
 *     target: '#myTargetDiv'
 * };
 * $('#myForm').ajaxSForm(options);
 * @desc Bind form's submit event so that 'myTargetDiv' is updated with the server response
 *       when the form is submitted.
 *
 *
 * @example
 * var options = {
 *     success: function(responseText) {
 *         alert(responseText);
 *     }
 * };
 * $('#myForm').ajaxSubmit(options);
 * @desc Bind form's submit event so that server response is alerted after the form is submitted.
 *
 *
 * @example
 * var options = {
 *     beforeSubmit: function(formArray, jqForm) {
 *         if (formArray.length == 0) {
 *             alert('Please enter data.');
 *             return false;
 *         }
 *     }
 * };
 * $('#myForm').ajaxSubmit(options);
 * @desc Bind form's submit event so that pre-submit callback is invoked before the form
 *       is submitted.
 *
 *
 * @name   ajaxForm
 * @param  options  object literal containing options which control the form submission process
 * @return jQuery
 * @cat    Plugins/Form
 * @type   jQuery
 */
$.fn.ajaxForm = function(options) {
    return this.ajaxFormUnbind().submit(submitHandler).each(function() {
        // store options in hash
        this.formPluginId = $.fn.ajaxForm.counter++;
        $.fn.ajaxForm.optionHash[this.formPluginId] = options;
        $(":submit,input:image", this).click(clickHandler);
    });
};

$.fn.ajaxForm.counter = 1;
$.fn.ajaxForm.optionHash = {};

function clickHandler(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);
};

function submitHandler() {
    // retrieve options from hash
    var id = this.formPluginId;
    var options = $.fn.ajaxForm.optionHash[id];
    $(this).ajaxSubmit(options);
    return false;
};

/**
 * ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
 *
 * @name   ajaxFormUnbind
 * @return jQuery
 * @cat    Plugins/Form
 * @type   jQuery
 */
$.fn.ajaxFormUnbind = function() {
    this.unbind('submit', submitHandler);
    return this.each(function() {
        $(":submit,input:image", this).unbind('click', clickHandler);
    });

};

/**
 * 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.
 *
 * The semantic argument can be used to force form serialization in semantic order.
 * This is normally true anyway, unless the form contains input elements of type='image'.
 * If your form must be submitted with name/value pairs in semantic order and your form
 * contains an input of type='image" then pass true for this arg, otherwise pass false
 * (or nothing) to avoid the overhead for this logic.
 *
 * @example var data = $("#myForm").formToArray();
 * $.post( "myscript.cgi", data );
 * @desc Collect all the data from a form and submit it to the server.
 *
 * @name formToArray
 * @param semantic true if serialization must maintain strict semantic ordering of elements (slower)
 * @type Array<Object>
 * @cat Plugins/Form
 */
$.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;
};


/**
 * Serializes form data into a 'submittable' string. This method will return a string
 * in the format: name1=value1&amp;name2=value2
 *
 * The semantic argument can be used to force form serialization in semantic order.
 * If your form must be submitted with name/value pairs in semantic order then pass
 * true for this arg, otherwise pass false (or nothing) to avoid the overhead for
 * this logic (which can be significant for very large forms).
 *
 * @example var data = $("#myForm").formSerialize();
 * $.ajax('POST', "myscript.cgi", data);
 * @desc Collect all the data from a form into a single string
 *
 * @name formSerialize
 * @param semantic true if serialization must maintain strict semantic ordering of elements (slower)
 * @type String
 * @cat Plugins/Form
 */
$.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
 *
 * The successful argument controls whether or not serialization is limited to
 * 'successful' controls (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
 * The default value of the successful argument is true.
 *
 * @example var data = $("input").formSerialize();
 * @desc Collect the data from all successful input elements into a query string
 *
 * @example var data = $(":radio").formSerialize();
 * @desc Collect the data from all successful radio input elements into a query string
 *
 * @example var data = $("#myForm :checkbox").formSerialize();
 * @desc Collect the data from all successful checkbox input elements in myForm into a query string
 *
 * @example var data = $("#myForm :checkbox").formSerialize(false);
 * @desc Collect the data from all checkbox elements in myForm (even the unchecked ones) into a query string
 *
 * @example var data = $(":input").formSerialize();
 * @desc Collect the data from all successful input, select, textarea and button elements into a query string
 *
 * @name fieldSerialize
 * @param successful true if only successful controls should be serialized (default is true)
 * @type String
 * @cat Plugins/Form
 */
$.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.
 *
 * @example var data = $("#myPasswordElement").fieldValue();
 * alert(data[0]);
 * @desc Alerts the current value of the myPasswordElement element
 *
 * @example var data = $("#myForm :input").fieldValue();
 * @desc Get the value(s) of the form elements in myForm
 *
 * @example var data = $("#myForm :checkbox").fieldValue();
 * @desc Get the value(s) for the successful checkbox element(s) in the jQuery object.
 *
 * @example var data = $("#mySingleSelect").fieldValue();
 * @desc Get the value(s) of the select control
 *
 * @example var data = $(':text').fieldValue();
 * @desc Get the value(s) of the text input or textarea elements
 *
 * @example var data = $("#myMultiSelect").fieldValue();
 * @desc Get the values for the select-multiple control
 *
 * @name fieldValue
 * @param Boolean successful true if only the values for successful controls should be returned (default is true)
 * @type Array<String>
 * @cat Plugins/Form
 */
$.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.
 *
 * 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 the given element is not
 * successful and the successful arg is not false then the returned value will be null.
 *
 * Note: If the successful flag is true (default) but the element is not successful, the return will be null
 * Note: The value returned for a successful select-multiple element will always be an array.
 * Note: If the element has no value the return value will be undefined.
 *
 * @example var data = jQuery.fieldValue($("#myPasswordElement")[0]);
 * @desc Gets the current value of the myPasswordElement element
 *
 * @name fieldValue
 * @param Element el The DOM element for which the value will be returned
 * @param Boolean successful true if value returned must be for a successful controls (default is true)
 * @type String or Array<String> or null or undefined
 * @cat Plugins/Form
 */
$.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;
};


/**
 * 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
 *
 * @example $('form').clearForm();
 * @desc Clears all forms on the page.
 *
 * @name clearForm
 * @type jQuery
 * @cat Plugins/Form
 */
$.fn.clearForm = function() {
    return this.each(function() {
        $('input,select,textarea', this).clearFields();
    });
};

/**
 * Clears the selected form elements.  Takes the following actions on the matched elements:
 *  - 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
 *
 * @example $('.myInputs').clearFields();
 * @desc Clears all inputs with class myInputs
 *
 * @name clearFields
 * @type jQuery
 * @cat Plugins/Form
 */
$.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.
 *
 * @example $('form').resetForm();
 * @desc Resets all forms on the page.
 *
 * @name resetForm
 * @type jQuery
 * @cat Plugins/Form
 */
$.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();
    });
};

})(jQuery);
jQuery.fn.WSStyleSelect = function() {
 var display = this.css('display');
 this.hide().after('<div class="FormSelectStyled"><ul></ul></div>').each(function() {
  var jSelect = jQuery(this);
  var jDiv = jQuery(this.nextSibling).css('display', display);
  var ul = jQuery(this.nextSibling.firstChild);
  var imgSrc = jSelect.attr('imgSrc');
  var activator;
  var updateActivator;
  if (false && imgSrc) {
   activator = jDiv.prepend('<img class="FormSelectActivator" />').find('img');
   activator.attr(imgSrc);
   updateActivator = function() { };
  } else {
   activator = jDiv.append('<span class="FormSelectActivator" >').find('span');
   updateActivator = function() {
    activator.text(jSelect.find(':selected').text());
   };
  }
  var choices = jDiv.find('ul').hide();


  var liHover = function() {
   var jThis = jQuery(this);
   var d = jThis.hasClass('disabled') || jThis.parent().hasClass('disabled');
   if (jThis.hasClass('disabled') || jThis.parent().hasClass('disabled')) return;
   choices.find('li').removeClass('active');
   jThis.addClass('active');
  };

  var newLI = function(container, src, labelFetcher, hover) {
   var li = jQuery(container.append('<li></li>')[0].lastChild).text(labelFetcher(src));
   if (src.is(':disabled')) {
    li.addClass('disabled');
    li.attr('disabled', src.attr('disabled'));
   }
   if (hover) li.hover(hover, function() {});
   return li;
  };
  var addOption = function(container, elm, labelFetcher) {
   var jThis = jQuery(elm);
   var thisVal = jThis.val();
   var li = newLI(container, jThis, labelFetcher, liHover);
   if (jSelect.val() == thisVal) li.addClass('active');
   if (!jThis.is(':disabled')) { 
    li.click(function() {
     if (jSelect.val() != thisVal) {
      jSelect.val(thisVal);
      jSelect.change();
     }
    });
   }
  };
  var addOptGroup = function(container, elm) {
   var jThis = jQuery(elm);
   var labelFetcher = function(e) { return e.attr('label'); };
   var li = newLI(container, jThis, labelFetcher, null);
   li.addClass('optgroup');
   var ul = jQuery(container.append('<ul></ul>')[0].lastChild); 
   if (jThis.is(':disabled')) ul.addClass('disabled');
   jThis.children('option').each(function() {
    addOption(ul, this, labelFetcher);
   });
  };
  updateActivator();
  activator.transientClick(
   function(e) {
    return choices.is(':hidden');
   },
   function (e) {
    var zIndex = choices.css('z-index');
    jSelect.children().each(function() {
     if (this.nodeName == 'OPTION') {
      addOption(choices, this, function(e) { return e.text(); });
     } else if (this.nodeName == 'OPTGROUP') {
      addOptGroup(choices, this);
     }
    });
    choices.slideDown(300).css('z-index', 1000);
    return function() {
     updateActivator();
     choices.slideUp(300, function() {
      choices.css('z-index', zIndex).empty();
     });
    };
   }
  );
 });
};
/*
 * Metadata - jQuery plugin for parsing metadata from elements
 *
 * Copyright (c) 2006 John Resig, Yehuda Katz, J�örn Zaefferer, Paul McLanahan
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Revision: $Id: jquery.metadata.js 3640 2007-10-11 18:34:38Z pmclanahan $
 *
 */

/**
 * Sets the type of metadata to use. Metadata is encoded in JSON, and each property
 * in the JSON will become a property of the element itself.
 *
 * There are three supported types of metadata storage:
 *
 *   attr:  Inside an attribute. The name parameter indicates *which* attribute.
 *          
 *   class: Inside the class attribute, wrapped in curly braces: { }
 *   
 *   elem:  Inside a child element (e.g. a script tag). The
 *          name parameter indicates *which* element.
 *          
 * The metadata for an element is loaded the first time the element is accessed via jQuery.
 *
 * As a result, you can define the metadata type, use $(expr) to load the metadata into the elements
 * matched by expr, then redefine the metadata type and run another $(expr) for other elements.
 * 
 * @name $.metadata.setType
 *
 * @example <p id="one" class="some_class {item_id: 1, item_label: 'Label'}">This is a p</p>
 * @before $.metadata.setType("class")
 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 * @desc Reads metadata from the class attribute
 * 
 * @example <p id="one" class="some_class" data="{item_id: 1, item_label: 'Label'}">This is a p</p>
 * @before $.metadata.setType("attr", "data")
 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 * @desc Reads metadata from a "data" attribute
 * 
 * @example <p id="one" class="some_class"><script>{item_id: 1, item_label: 'Label'}</script>This is a p</p>
 * @before $.metadata.setType("elem", "script")
 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 * @desc Reads metadata from a nested script element
 * 
 * @param String type The encoding type
 * @param String name The name of the attribute to be used to get metadata (optional)
 * @cat Plugins/Metadata
 * @descr Sets the type of encoding to be used when loading metadata for the first time
 * @type undefined
 * @see metadata()
 */

(function($) {

$.extend({
	metadata : {
		defaults : {
			type: 'class',
			name: 'metadata',
			cre: /({.*})/,
			single: 'metadata'
		},
		setType: function( type, name ){
			this.defaults.type = type;
			this.defaults.name = name;
		},
		get: function( elem, opts ){
			var settings = $.extend({},this.defaults,opts);
			// check for empty string in single property
			if ( !settings.single.length ) settings.single = 'metadata';
			
			var data = $.data(elem, settings.single);
			// returned cached data if it already exists
			if ( data ) return data;
			
			data = "{}";
			
			if ( settings.type == "class" ) {
				var m = settings.cre.exec( elem.className );
				if ( m )
					data = m[1];
			} else if ( settings.type == "elem" ) {
				if( !elem.getElementsByTagName ) return;
				var e = elem.getElementsByTagName(settings.name);
				if ( e.length )
					data = $.trim(e[0].innerHTML);
			} else if ( elem.getAttribute != undefined ) {
				var attr = elem.getAttribute( settings.name );
				if ( attr )
					data = attr;
			}
			
			if ( data.indexOf( '{' ) <0 )
			data = "{" + data + "}";
			
			data = eval("(" + data + ")");
			
			$.data( elem, settings.single, data );
			return data;
		}
	}
});

/**
 * Returns the metadata object for the first member of the jQuery object.
 *
 * @name metadata
 * @descr Returns element's metadata object
 * @param Object opts An object contianing settings to override the defaults
 * @type jQuery
 * @cat Plugins/Metadata
 */
$.fn.metadata = function( opts ){
	return $.metadata.get( this[0], opts );
};

})(jQuery);/**
 * flashembed 1.0.2. Adobe Flash embedding script
 * 
 * Copyright (c) 2009 Tero Piirainen
 * http://flowplayer.org/tools/flash-embed.html
 *
 * Dual licensed under MIT and GPL 2+ licenses
 * http://www.opensource.org/licenses
 *
 * Launch  : March 2008
 * Version : 1.0.2 - Wed Apr 15 2009 06:26:45 GMT-0000 (GMT+00:00)
 */ 
(function() {  
		
//{{{ utility functions 
		
var jQ = typeof jQuery == 'function';


// from "Pro JavaScript techniques" by John Resig
function isDomReady() {
	
	if (domReady.done)  { return false; }
	
	var d = document;
	if (d && d.getElementsByTagName && d.getElementById && d.body) {
		clearInterval(domReady.timer);
		domReady.timer = null;
		
		for (var i = 0; i < domReady.ready.length; i++) {
			domReady.ready[i].call();	
		}
		
		domReady.ready = null;
		domReady.done = true;
	} 
}

// if jQuery is present, use it's more effective domReady method
var domReady = jQ ? jQuery : function(f) {
	
	if (domReady.done) {
		return f();	
	}
	
	if (domReady.timer) {
		domReady.ready.push(f);	
		
	} else {
		domReady.ready = [f];
		domReady.timer = setInterval(isDomReady, 13);
	} 
};	


// override extend opts function 
function extend(to, from) {
	if (from) {
		for (key in from) {
			if (from.hasOwnProperty(key)) {
				to[key] = from[key];
			}
		}
	}
	
	return to;
}	


// JSON.asString() function
function asString(obj) {
	 
	switch (typeOf(obj)){
		case 'string':
			obj = obj.replace(new RegExp('(["\\\\])', 'g'), '\\$1');
			
			// flash does not handle %- characters well. transforms "50%" to "50pct" (a dirty hack, I admit)
			obj = obj.replace(/^\s?(\d+)%/, "$1pct");
			return '"' +obj+ '"';
			
		case 'array':
			return '['+ map(obj, function(el) {
				return asString(el);
			}).join(',') +']'; 
			
		case 'function':
			return '"function()"';
			
		case 'object':
			var str = [];
			for (var prop in obj) {
				if (obj.hasOwnProperty(prop)) {
					str.push('"'+prop+'":'+ asString(obj[prop]));
				}
			}
			return '{'+str.join(',')+'}';
	}
	
	// replace ' --> "  and remove spaces
	return String(obj).replace(/\s/g, " ").replace(/\'/g, "\"");
}


// private functions
function typeOf(obj) {
	if (obj === null || obj === undefined) { return false; }
	var type = typeof obj;
	return (type == 'object' && obj.push) ? 'array' : type;
}


// version 9 bugfix: (http://blog.deconcept.com/2006/07/28/swfobject-143-released/)
if (window.attachEvent) {
	window.attachEvent("onbeforeunload", function() {
		__flash_unloadHandler = function() {};
		__flash_savedUnloadHandler = function() {};
	});
}

function map(arr, func) {
	var newArr = []; 
	for (var i in arr) {
		if (arr.hasOwnProperty(i)) {
			newArr[i] = func(arr[i]);
		}
	}
	return newArr;
}
	
function getHTML(p, c) {

		
	var e = extend({}, p);	
	
	var ie = document.all;	
	var html = '<div style="width:' +e.width+ 'px;height:' +e.height+ 'px;"><object width="' +e.width+ '" height="' +e.height+ '"';
	
	// force id for IE or Flash API cannot be returned
	if (ie && !e.id) {
		e.id = "_" + ("" + Math.random()).substring(9);
	}
	
	if (e.id) {	
		html += ' id="' + e.id + '"';	
	}
	
	// prevent possible caching problems
	e.src += ((e.src.indexOf("?") != -1 ? "&" : "?") + Math.random());		
	
	if (e.w3c || !ie) {
		html += ' data="' +e.src+ '" type="application/x-shockwave-flash"';		
	} else {
		html += ' classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"';	
	}
	
	html += '>'; 
	
	if (e.w3c || ie) {
		html += '<param name="movie" value="' +e.src+ '" />'; 	
	}

	// parameters
	e.width = e.height = e.id = e.w3c = e.src = null;
	
	for (var k in e) {
		if (e[k] !== null) {
			html += '<param name="'+ k +'" value="'+ e[k] +'" />';
		}
	}	

	// flashvars
	var vars = "";
	
	if (c) {
		for (var key in c) {
			if (c[key] !== null) {
				vars += key +'='+ (typeof c[key] == 'object' ? asString(c[key]) : c[key]) + '&';
			}
		}
		vars = vars.substring(0, vars.length -1);
		html += '<param name="flashvars" value=\'' + vars + '\' />';
	}
	
	html += "</object></div>";	
	
	return html;

}

//}}}


function Flash(root, opts, flashvars) {
	
	var version = flashembed.getVersion(); 
	
	// API methods for callback
	extend(this, {
			
		getContainer: function() {
			return root;	
		},
		
		getConf: function() {
			return conf;	
		},
	
		getVersion: function() {
			return version;	
		},	
		
		getFlashvars: function() {
			return flashvars;	
		}, 
		
		getApi: function() {
			return root.firstChild.firstChild;
		}, 
		
		getHTML: function() {
			return getHTML(opts, flashvars);	
		}
		
	});

	// variables	
	var required = opts.version; 
	var express = opts.expressInstall;
	
	
	// everything ok -> generate OBJECT tag 
	var ok = !required || flashembed.isSupported(required);
	
	if (ok) {
		opts.onFail = opts.version = opts.expressInstall = null;
		root.innerHTML = getHTML(opts, flashvars);
		
	// fail #1. express install
	} else if (required && express && flashembed.isSupported([6,65])) {
		
		extend(opts, {src: express});
		
		flashvars = {
			MMredirectURL: location.href,
			MMplayerType: 'PlugIn',
			MMdoctitle: document.title
		};
		
		root.innerHTML = getHTML(opts, flashvars);	
		
	// fail #2. 
	} else { 
	
		// fail #2.1 custom content inside container
		if (root.innerHTML.replace(/\s/g, '') !== '') {
			// minor bug fixed here 08.04.2008 (thanks JRodman)
			
		
		// fail #2.2 default content
		} else {			
			root.innerHTML = 
				"<h2>Flash version " + required + " or greater is required</h2>" + 
				"<h3>" + 
					(version[0] > 0 ? "Your version is " + version : "You have no flash plugin installed") +
				"</h3>" + 
				
				(root.tagName == 'A' ? "<p>Click here to download latest version</p>" : 
					"<p>Download latest version from <a href='http://www.adobe.com/go/getflashplayer'>here</a></p>");
				
			if (root.tagName == 'A') {	
				root.href = 'http://www.adobe.com/go/getflashplayer';
			}				
		}
	}
	
	// onFail
	if (!ok && opts.onFail) {
		var ret = opts.onFail.call(this);
		if (typeof ret == 'string') { root.innerHTML = ret; }	
	}
	
}

window.flashembed = function(root, conf, flashvars) { 
	
//{{{ construction
	
	// root must be found / loaded	
	if (typeof root == 'string') {
		var el = document.getElementById(root);
		if (el) {
			root = el;	
		} else {
			domReady(function() {
				flashembed(root, conf, flashvars);
			});
			return; 		
		} 
	}
	
	// not found
	if (!root) { return; }


	// setup opts
	var opts = {
		
		// very common opts
		width: '100%',
		height: '100%',		
		
		// flashembed defaults
		allowFullScreen: true,
		allowscriptaccess: 'always',
		quality: 'high',	
		
		
		// flashembed specific options
		version: null,
		onFail: null,
		expressInstall: null, 
		w3c: false
	};
	
	
	if (typeof conf == 'string') {
		conf = {src: conf};	
	}
	
	extend(opts, conf);		
	
	return new Flash(root, opts, flashvars);
	
//}}}
	
	
};


//{{{ static methods

extend(window.flashembed, {

	// returns arr[major, fix]
	getVersion: function() {
	
		var version = [0, 0];
		
		if (navigator.plugins && typeof navigator.plugins["Shockwave Flash"] == "object") {
			var _d = navigator.plugins["Shockwave Flash"].description;
			if (typeof _d != "undefined") {
				_d = _d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
				var _m = parseInt(_d.replace(/^(.*)\..*$/, "$1"), 10);
				var _r = /r/.test(_d) ? parseInt(_d.replace(/^.*r(.*)$/, "$1"), 10) : 0;
				version = [_m, _r];
			}
			
		} else if (window.ActiveXObject) {

			try { // avoid fp 6 crashes
				var _a = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
				
			} catch(e) {
				
				try { 
					_a = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
					version = [6, 0];
					_a.AllowScriptAccess = "always"; // throws if fp < 6.47 
					
				} catch(ee) {
					if (version[0] == 6) { return; }
				}
				try {
					_a = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
				} catch(eee) {
				
				}
				
			}
			
			if (typeof _a == "object") {
				_d = _a.GetVariable("$version"); // bugs in fp 6.21 / 6.23
				if (typeof _d != "undefined") {
					_d = _d.replace(/^\S+\s+(.*)$/, "$1").split(",");
					version = [parseInt(_d[0], 10), parseInt(_d[2], 10)];
				}
			}
		} 
		
		return version;
	},
	
	isSupported: function(version) {
		var now = flashembed.getVersion();
		var ret = (now[0] > version[0]) || (now[0] == version[0] && now[1] >= version[1]);			
		return ret;
	},
	
	domReady: domReady,
	
	// returns a String representation from JSON object 
	asString: asString,
	
	
	getHTML: getHTML
	
});

//}}}


// setup jquery support
if (jQ) {
	
	jQuery.fn.flashembed = function(conf, flashvars) { 
		return this.each(function() { 
			$(this).data('flashembed', flashembed(this, conf, flashvars));
		});
	};

}

})();
﻿/*
 *         developed by Matteo Bicocchi on JQuery
 *         © 2002-2009 Open Lab srl, Matteo Bicocchi
 *			    www.open-lab.com - info@open-lab.com
 *       	version 1.0
 *       	tested on: 	Explorer and FireFox for PC
 *                  		FireFox and Safari for Mac Os X
 *                  		FireFox for Linux
 *         GPL (GPL-LICENSE.txt) licenses.
 */


jQuery.fn.mbGallery = function(NewOptions)
{
	return this.each(function() {
		var galleryId = !this.id ? Math.floor(Math.random() * 100): this.id;
		var gallery = this;

		this.options = {
			galleryWidth: 300,
			galleryHeight: 300,
			galleryMaxWidth: 0,
			galleryColor: "white",
			galleryFrameBorder: 30,
			galleryFrameColor: "white",

			startFrom: 0,
			headerOpacity: 0.5,
			thumbsBorder: 5,
			thumbHeight: 30,
			thumbStripColor: "black",
			thumbStripPos: "right",
			thumbStripWidth:250,
			thumbSelectColor: "black",
			thumbOverColor: "#cccccc",
			imageSelector: ".imgFull",
			thumbnailSelector: ".imgThumb",
			descSelector: ".imgDesc",
			descriptionWidth:300,

			labelColor: "yellow",
			labelColorDisactive: "white",
			labelTextColor: "black",
			labelTextSize: "9px",
			labelHeight: 25,
			iconFolder: "elements/black",
			fadeTime: 300,
			autoSlide: true,
			slideTimer: 100,
			autoSize: true,
			startTimer:0

		}

		var closeThumbStrip;

		$.extend(this.options, NewOptions);
		var opt= this.options;

		opt.thumbsBorder = opt.thumbsBorder + "px solid";
		var thumbSel = {
			thumbSel:
			{
				border: opt.thumbsBorder, borderColor: opt.thumbSelectColor
			},
			thumbUnsel:
			{
				border: opt.thumbsBorder, borderColor: opt.thumbStripColor
			},
			thumbOver:
			{
				border: opt.thumbsBorder, borderColor: opt.thumbOverColor
			}
		}
		$.extend(opt, thumbSel);
		if(opt.slideTimer < 2000)
			opt.slideTimer = 2000;
		var actualImg;
		var actualThumb;
		var thumbUnsel = opt.thumbUnsel;
		var thumbOver = opt.thumbOver;
		$(this).hide();

		// GETTING THE ELEMENTS FOR THE GALLERY FROM THE PAGE
		var thumbs = $(this).find(opt.thumbnailSelector);
		var full = $(this).find(opt.imageSelector);
		var imgDesc = $(this).find(opt.descSelector);
		$(this).empty();

		if(opt.startFrom == "random")
			opt.startFrom = Math.floor(Math.random() * full.length);

		function preloadImg(i) {
			$(thumbloading).find("img").attr("src", ""+opt.iconFolder+"/loader.gif");
			var IMG_URL = $(full [i]).attr("src");
			var IMGOBJ = new Image();
			IMGOBJ.onload = function()
			{
				$(thumbloading).find("img").attr("src", ""+opt.iconFolder+"/loaded.gif");
				changePhoto(i);
			};
			IMGOBJ.onerror = function()
			{
				alert("can't load " + IMG_URL)
			};
			IMGOBJ.src = IMG_URL;
		}

		var thumbPos = "";
		function setThumbPos(w) {
			var pos=0
			switch(opt.thumbStripPos)
				{
				case "left":
					pos= 0;
					break;
				case "center":
					pos=((w / 2) -(opt.thumbStripWidth / 2));
					break;
				case "right":
					pos=(w - opt.thumbStripWidth);
					break;
				default:
					pos= 0;
					break;
			}
			return pos;
		};

		thumbPos = setThumbPos(opt.galleryWidth);

		$(this).parent().append("<table cellpadding='0' cellspacing='0' height='"+opt.galleryHeight+"'><tr><td id ='gallery_"+galleryId+"'></td></tr></table>");
		var galleryContainer= $(this).parent().find('#gallery_'+galleryId);
		$(galleryContainer).css(
		{
			border: opt.galleryFrameBorder + "px solid " + opt.galleryFrameColor,
			background: opt.galleryColor
		})
		$(galleryContainer).append(this);

		// CREATE THE GALLERY STRUCTURE FOR FULLSIZE IMAGES
		$(this).append("<div class='FullImg'></div>");
		var fullImageArea = $(this).find(" .FullImg");

		// CREATE THE GALLERY STRUCTURE FOR THUMBS IMAGES
		var headerH = opt.labelHeight > 0 ? opt.labelHeight: opt.galleryFrameBorder;


		// thumbnail container
		$(galleryContainer).prepend("<div class='thumbBox'></div>");
		var thumbBox = $(galleryContainer).find(" .thumbBox");

		//thumbnail navigator
		$(thumbBox).prepend("<div class='header'><table cellpadding='0' cellspacing='0'><td class='thumbWinBtn pointer' ></td><td class='spacer' ></td><td class='slideShow pointer' ></td><td class='spacer' ></td><td class='prev pointer' ></td><td class='next pointer' ></td><td class='spacer' ></td><td class='loader'></td><td class='indexLabel' nowrap></td></div>");
		var header = $(thumbBox).find(" .header");

		var thumbWinBtn = $(header).find(".thumbWinBtn");
		$(thumbWinBtn).append("<img src='"+opt.iconFolder+"/thumb.gif' class='thumbIco'>");

		var slideShow = $(header).find(".slideShow");
		$(slideShow).append("<img src='"+opt.iconFolder+"/play.gif' class='slideIco'>");

		var thumbloading = $(header).find(".loader");
		$(thumbloading).append("<img src='"+opt.iconFolder+"/loaded.gif'>");

		var spacer = $(header).find(".spacer");
		$(spacer).append("<img src='"+opt.iconFolder+"/separator.gif'>");

		var next = $(header).find(".next");
		$(next).append("<img src='"+opt.iconFolder+"/next.gif'>");

		var prev = $(header).find(".prev");
		$(prev).append("<img src='"+opt.iconFolder+"/prev.gif'>");

		var indexLabel = $(thumbBox).find(" .indexLabel").html((opt.startFrom + 1) + ".<b>" + full.length + "</b>");

		//Thumbnails
		$(thumbBox).append("<div class='ThumbImg'></div>");
		var thumbImages = $(thumbBox).find(" .ThumbImg");
		$(thumbImages).prepend($(thumbs));


		$(thumbBox).append("<div class='descriptionBox'></div>");
		var descriptionBox= $(galleryContainer).find(".descriptionBox");
		$(descriptionBox).css(
		{
			position:"absolute",
			padding: 10,
			zIndex:0,
			width: opt.thumbStripWidth-20
		})


		$(this).css(
		{
			width: opt.galleryWidth,
			height: opt.galleryHeight,
			overflow: "hidden"
		});

		$(thumbs).css(
		{
			width: opt.thumbHeight,
			padding: "0px",
			border: "1px solid "+opt.labelColor,
			cursor: "pointer"
		});

		$(thumbBox).css(
		{
			textAlign: "left",
			zindex: 1000,
			marginTop: "-" + headerH + "px",
			position: "absolute",
			width: opt.thumbStripWidth + "px",
			marginLeft: thumbPos + "px",
			zIndex:10000
		});

		$(thumbImages).css(
		{
			opacity:opt.headerOpacity,
			backgroundColor: opt.thumbStripColor,
			border: "5px solid "+ opt.labelColor
		});

		$(header).css(
		{
			opacity: opt.headerOpacity,
			textAlign: "left",
			color: opt.labelTextColor,
			padding: "0px",
			border: "0px",
			height: headerH
		});

		$(header).find("td").css(
		{
			background: opt.labelColorDisactive,
			padding: "2px",
			paddingRight: "10px",
			height:headerH,
			color: opt.labelTextColor,
			fontFamily: "Verdana, Arial",
			fontSize: opt.labelTextSize
		});

		$(".pointer").css(
		{
			cursor: "pointer"
		});

		jQuery.fn.extend(
		{
			getW: function() {
				var ow = $(this).width();
				if(opt.galleryMaxWidth > 0 && ow > opt.galleryMaxWidth) {
					$(this).attr("width", opt.galleryMaxWidth);
					ow = opt.galleryMaxWidth;
				}
				return ow;
			}
		});
		function changePhoto(i) {
			$(descriptionBox).fadeTo(opt.fadeTime, 0);
			$(fullImageArea).fadeTo(opt.fadeTime, 0, function() {
				//replacing the image
				$(this).html(full [i]);
				$(descriptionBox).html(imgDesc[i]);
				//showing the new image
				setTimeout(function() {
					$(fullImageArea).fadeTo(opt.fadeTime, 1)
					$(descriptionBox).fadeTo(opt.fadeTime, .8);
				}, opt.fadeTime);
				// if autosize option resize the image frame
				if(opt.autoSize) {
					//if a maxWith is set resize the image width
					var w = $(full [i]).getW();
					//resize frame
					$(gallery).animate(
					{
						height: full [i].offsetHeight,
						width: w
					}, opt.fadeTime);
					//if the thumbstrip has no width set the width according ti the frame width
					if(opt.thumbStripWidth == opt.galleryWidth) {
						$(thumbBox).animate(
						{
							width: full [i].offsetWidth
						},
							opt.fadeTime)
					} else {
						// if the thumbstrip has a width reposition it according to the image width
						var l = setThumbPos($(full [i]).width());
						$(thumbBox).animate(
						{
							marginLeft: l
						}, opt.fadeTime);
					}
				}
			});
			//redefine the indexLabeles
			$(actualThumb).css(thumbUnsel);
			actualImg = full [i];
			actualThumb = thumbs [i];
			$(actualThumb).css(opt.thumbSel);
			$(indexLabel).html((i +1)+ ".<b>" + full.length + "</b>");
		}
		thumbs.each(function(i) {
			$(this).click(function() {
				x = i;
				stopShow();
				preloadImg(i);
				setTimeout(function(){$(thumbImages).hide(500);},500)
			})
		})
		$(this).show();

		// EVENTS
		var hideTumb, thumbOpen, headerMO;
		$(thumbWinBtn).click(function() {
			if( !thumbOpen) {
				$(thumbImages).show(500);
				thumbOpen = true;
			} else {
				$(thumbImages).hide(500);
				thumbOpen = false;
			}
			stopShow();
		})
		$(fullImageArea).click(function() {
			stopShow();
		});
		$(fullImageArea).bind("dblclick",function() {
			startShow();
		});
		$(thumbBox).mouseover(function() {
			clearTimeout(hideTumb);
			clearTimeout(headerMO);
			$(header).find("td").css({opacity:opt.headerOpacity, background: opt.labelColor})
			clearTimeout(closeThumbStrip);
		})

		$(thumbBox).mouseout(function() {
			headerMO=setTimeout(function(){
				$(header).find("td").css({opacity:opt.headerOpacity, background: opt.labelColorDisactive})
			},100)
			hideTumb = setTimeout(function() {
				$(thumbImages).hide(500);
				thumbOpen = false;
			}, 1000);
		})
		$(thumbs).mouseover(function() {
			if(this != actualThumb) {
				$(this).css(thumbOver)
			}
		})
		$(thumbs).mouseout(function() {
			if(this != actualThumb) {
				$(this).css(thumbUnsel)
			}
		});
		$(slideShow).click(function() {
			startSlide = ! startSlide;
			if(startSlide) {
				startShow();
			} else
				stopShow();
		})
		var goOn;
		$(next).click( function() {
			stopShow();
			clearTimeout(goOn);
			x += 1;
			goOn = setTimeout(function() {
				if(x >= full.length) x = 0;
				preloadImg(x);
			}, 200);
		})
		$(prev).click( function() {
			stopShow();
			clearTimeout(goOn);
			x -= 1;
			goOn = setTimeout(function() {
				if(x < 0) x = full.length - 1;
				preloadImg(x);
			}, 200);
		})

		actualImg = full [opt.startFrom];
		$(thumbs).css(thumbUnsel);
		actualThumb = thumbs [opt.startFrom];
		$(actualThumb).css(thumbSel);
		closeThumbStrip = setTimeout(function() {
			$(thumbImages).hide(500)
		}, 2000);
		var slideShowTimer, x = opt.startFrom, startSlide = opt.autoSlide, startShow = function() {
			$(slideShow).find("img").attr("src", opt.iconFolder+"/stop.gif")
			if(x == full.length)
				x = 0;
			preloadImg(x);
			slideShowTimer = setTimeout(startShow, opt.slideTimer)
			x ++
		};
		function stopShow() {
			clearTimeout(slideShowTimer);
			$(slideShow).find("img").attr("src", opt.iconFolder+"/play.gif");
			startSlide = false;
		}
		if(startSlide) {
			setTimeout(startShow, opt.startTimer);
		} else {
			setTimeout(function() {
				preloadImg(opt.startFrom)
			}, opt.startTimer);
		}
	})
}
/*
 * jQuery UI 1.6rc6
 *
 * Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI
 */
;(function($) {

var _remove = $.fn.remove,
	isFF2 = $.browser.mozilla && (parseFloat($.browser.version) < 1.9);

//Helper functions and ui object
$.ui = {
	version: "1.6rc6",

	// $.ui.plugin is deprecated.  Use the proxy pattern instead.
	plugin: {
		add: function(module, option, set) {
			var proto = $.ui[module].prototype;
			for(var i in set) {
				proto.plugins[i] = proto.plugins[i] || [];
				proto.plugins[i].push([option, set[i]]);
			}
		},
		call: function(instance, name, args) {
			var set = instance.plugins[name];
			if(!set) { return; }

			for (var i = 0; i < set.length; i++) {
				if (instance.options[set[i][0]]) {
					set[i][1].apply(instance.element, args);
				}
			}
		}
	},

	contains: function(a, b) {
		return document.compareDocumentPosition
			? a.compareDocumentPosition(b) & 16
			: a !== b && a.contains(b);
	},

	cssCache: {},
	css: function(name) {
		if ($.ui.cssCache[name]) { return $.ui.cssCache[name]; }
		var tmp = $('<div class="ui-gen"></div>').addClass(name).css({position:'absolute', top:'-5000px', left:'-5000px', display:'block'}).appendTo('body');

		//if (!$.browser.safari)
			//tmp.appendTo('body');

		//Opera and Safari set width and height to 0px instead of auto
		//Safari returns rgba(0,0,0,0) when bgcolor is not set
		$.ui.cssCache[name] = !!(
			(!(/auto|default/).test(tmp.css('cursor')) || (/^[1-9]/).test(tmp.css('height')) || (/^[1-9]/).test(tmp.css('width')) ||
			!(/none/).test(tmp.css('backgroundImage')) || !(/transparent|rgba\(0, 0, 0, 0\)/).test(tmp.css('backgroundColor')))
		);
		try { $('body').get(0).removeChild(tmp.get(0));	} catch(e){}
		return $.ui.cssCache[name];
	},

	hasScroll: function(el, a) {

		//If overflow is hidden, the element might have extra content, but the user wants to hide it
		if ($(el).css('overflow') == 'hidden') { return false; }

		var scroll = (a && a == 'left') ? 'scrollLeft' : 'scrollTop',
			has = false;

		if (el[scroll] > 0) { return true; }

		// TODO: determine which cases actually cause this to happen
		// if the element doesn't have the scroll set, see if it's possible to
		// set the scroll
		el[scroll] = 1;
		has = (el[scroll] > 0);
		el[scroll] = 0;
		return has;
	},

	isOverAxis: function(x, reference, size) {
		//Determines when x coordinate is over "b" element axis
		return (x > reference) && (x < (reference + size));
	},

	isOver: function(y, x, top, left, height, width) {
		//Determines when x, y coordinates is over "b" element
		return $.ui.isOverAxis(y, top, height) && $.ui.isOverAxis(x, left, width);
	},

	keyCode: {
		BACKSPACE: 8,
		CAPS_LOCK: 20,
		COMMA: 188,
		CONTROL: 17,
		DELETE: 46,
		DOWN: 40,
		END: 35,
		ENTER: 13,
		ESCAPE: 27,
		HOME: 36,
		INSERT: 45,
		LEFT: 37,
		NUMPAD_ADD: 107,
		NUMPAD_DECIMAL: 110,
		NUMPAD_DIVIDE: 111,
		NUMPAD_ENTER: 108,
		NUMPAD_MULTIPLY: 106,
		NUMPAD_SUBTRACT: 109,
		PAGE_DOWN: 34,
		PAGE_UP: 33,
		PERIOD: 190,
		RIGHT: 39,
		SHIFT: 16,
		SPACE: 32,
		TAB: 9,
		UP: 38
	}
};

// WAI-ARIA normalization
if (isFF2) {
	var attr = $.attr,
		removeAttr = $.fn.removeAttr,
		ariaNS = "http://www.w3.org/2005/07/aaa",
		ariaState = /^aria-/,
		ariaRole = /^wairole:/;

	$.attr = function(elem, name, value) {
		var set = value !== undefined;

		return (name == 'role'
			? (set
				? attr.call(this, elem, name, "wairole:" + value)
				: (attr.apply(this, arguments) || "").replace(ariaRole, ""))
			: (ariaState.test(name)
				? (set
					? elem.setAttributeNS(ariaNS,
						name.replace(ariaState, "aaa:"), value)
					: attr.call(this, elem, name.replace(ariaState, "aaa:")))
				: attr.apply(this, arguments)));
	};

	$.fn.removeAttr = function(name) {
		return (ariaState.test(name)
			? this.each(function() {
				this.removeAttributeNS(ariaNS, name.replace(ariaState, ""));
			}) : removeAttr.call(this, name));
	};
}

//jQuery plugins
$.fn.extend({
	remove: function() {
		// Safari has a native remove event which actually removes DOM elements,
		// so we have to use triggerHandler instead of trigger (#3037).
		$("*", this).add(this).each(function() {
			$(this).triggerHandler("remove");
		});
		return _remove.apply(this, arguments );
	},

	enableSelection: function() {
		return this
			.attr('unselectable', 'off')
			.css('MozUserSelect', '')
			.unbind('selectstart.ui');
	},

	disableSelection: function() {
		return this
			.attr('unselectable', 'on')
			.css('MozUserSelect', 'none')
			.bind('selectstart.ui', function() { return false; });
	},

	scrollParent: function() {
		var scrollParent;
		if(($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
			scrollParent = this.parents().filter(function() {
				return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
			}).eq(0);
		} else {
			scrollParent = this.parents().filter(function() {
				return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
			}).eq(0);
		}

		return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
	}
});


//Additional selectors
$.extend($.expr[':'], {
	data: function(elem, i, match) {
		return !!$.data(elem, match[3]);
	},

	focusable: function(element) {
		var nodeName = element.nodeName.toLowerCase(),
			tabIndex = $.attr(element, 'tabindex');
		return (/input|select|textarea|button|object/.test(nodeName)
			? !element.disabled
			: 'a' == nodeName || 'area' == nodeName
				? element.href || !isNaN(tabIndex)
				: !isNaN(tabIndex))
			// the element and all of its ancestors must be visible
			// the browser may report that the area is hidden
			&& !$(element)['area' == nodeName ? 'parents' : 'closest'](':hidden').length;
	},

	tabbable: function(element) {
		var tabIndex = $.attr(element, 'tabindex');
		return (isNaN(tabIndex) || tabIndex >= 0) && $(element).is(':focusable');
	}
});


// $.widget is a factory to create jQuery plugins
// taking some boilerplate code out of the plugin code
function getter(namespace, plugin, method, args) {
	function getMethods(type) {
		var methods = $[namespace][plugin][type] || [];
		return (typeof methods == 'string' ? methods.split(/,?\s+/) : methods);
	}

	var methods = getMethods('getter');
	if (args.length == 1 && typeof args[0] == 'string') {
		methods = methods.concat(getMethods('getterSetter'));
	}
	return ($.inArray(method, methods) != -1);
}

$.widget = function(name, prototype) {
	var namespace = name.split(".")[0];
	name = name.split(".")[1];

	// create plugin method
	$.fn[name] = function(options) {
		var isMethodCall = (typeof options == 'string'),
			args = Array.prototype.slice.call(arguments, 1);

		// prevent calls to internal methods
		if (isMethodCall && options.substring(0, 1) == '_') {
			return this;
		}

		// handle getter methods
		if (isMethodCall && getter(namespace, name, options, args)) {
			var instance = $.data(this[0], name);
			return (instance ? instance[options].apply(instance, args)
				: undefined);
		}

		// handle initialization and non-getter methods
		return this.each(function() {
			var instance = $.data(this, name);

			// constructor
			(!instance && !isMethodCall &&
				$.data(this, name, new $[namespace][name](this, options))._init());

			// method call
			(instance && isMethodCall && $.isFunction(instance[options]) &&
				instance[options].apply(instance, args));
		});
	};

	// create widget constructor
	$[namespace] = $[namespace] || {};
	$[namespace][name] = function(element, options) {
		var self = this;

		this.namespace = namespace;
		this.widgetName = name;
		this.widgetEventPrefix = $[namespace][name].eventPrefix || name;
		this.widgetBaseClass = namespace + '-' + name;

		this.options = $.extend({},
			$.widget.defaults,
			$[namespace][name].defaults,
			$.metadata && $.metadata.get(element)[name],
			options);

		this.element = $(element)
			.bind('setData.' + name, function(event, key, value) {
				if (event.target == element) {
					return self._setData(key, value);
				}
			})
			.bind('getData.' + name, function(event, key) {
				if (event.target == element) {
					return self._getData(key);
				}
			})
			.bind('remove', function() {
				return self.destroy();
			});
	};

	// add widget prototype
	$[namespace][name].prototype = $.extend({}, $.widget.prototype, prototype);

	// TODO: merge getter and getterSetter properties from widget prototype
	// and plugin prototype
	$[namespace][name].getterSetter = 'option';
};

$.widget.prototype = {
	_init: function() {},
	destroy: function() {
		this.element.removeData(this.widgetName)
			.removeClass(this.widgetBaseClass + '-disabled' + ' ' + this.namespace + '-state-disabled')
			.removeAttr('aria-disabled');
	},

	option: function(key, value) {
		var options = key,
			self = this;

		if (typeof key == "string") {
			if (value === undefined) {
				return this._getData(key);
			}
			options = {};
			options[key] = value;
		}

		$.each(options, function(key, value) {
			self._setData(key, value);
		});
	},
	_getData: function(key) {
		return this.options[key];
	},
	_setData: function(key, value) {
		this.options[key] = value;

		if (key == 'disabled') {
			this.element
				[value ? 'addClass' : 'removeClass'](
					this.widgetBaseClass + '-disabled' + ' ' +
					this.namespace + '-state-disabled')
				.attr("aria-disabled", value);
		}
	},

	enable: function() {
		this._setData('disabled', false);
	},
	disable: function() {
		this._setData('disabled', true);
	},

	_trigger: function(type, event, data) {
		var callback = this.options[type],
			eventName = (type == this.widgetEventPrefix
				? type : this.widgetEventPrefix + type);

		event = $.Event(event);
		event.type = eventName;

		// copy original event properties over to the new event
		// this would happen if we could call $.event.fix instead of $.Event
		// but we don't have a way to force an event to be fixed multiple times
		if (event.originalEvent) {
			for (var i = $.event.props.length, prop; i;) {
				prop = $.event.props[--i];
				event[prop] = event.originalEvent[prop];
			}
		}

		this.element.trigger(event, data);

		return !($.isFunction(callback) && callback.call(this.element[0], event, data) === false
			|| event.isDefaultPrevented());
	}
};

$.widget.defaults = {
	disabled: false
};


/** Mouse Interaction Plugin **/

$.ui.mouse = {
	_mouseInit: function() {
		var self = this;

		this.element
			.bind('mousedown.'+this.widgetName, function(event) {
				return self._mouseDown(event);
			})
			.bind('click.'+this.widgetName, function(event) {
				if(self._preventClickEvent) {
					self._preventClickEvent = false;
					return false;
				}
			});

		// Prevent text selection in IE
		if ($.browser.msie) {
			this._mouseUnselectable = this.element.attr('unselectable');
			this.element.attr('unselectable', 'on');
		}

		this.started = false;
	},

	// TODO: make sure destroying one instance of mouse doesn't mess with
	// other instances of mouse
	_mouseDestroy: function() {
		this.element.unbind('.'+this.widgetName);

		// Restore text selection in IE
		($.browser.msie
			&& this.element.attr('unselectable', this._mouseUnselectable));
	},

	_mouseDown: function(event) {
		// don't let more than one widget handle mouseStart
		if (event.originalEvent.mouseHandled) { return; }

		// we may have missed mouseup (out of window)
		(this._mouseStarted && this._mouseUp(event));

		this._mouseDownEvent = event;

		var self = this,
			btnIsLeft = (event.which == 1),
			elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
		if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
			return true;
		}

		this.mouseDelayMet = !this.options.delay;
		if (!this.mouseDelayMet) {
			this._mouseDelayTimer = setTimeout(function() {
				self.mouseDelayMet = true;
			}, this.options.delay);
		}

		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
			this._mouseStarted = (this._mouseStart(event) !== false);
			if (!this._mouseStarted) {
				event.preventDefault();
				return true;
			}
		}

		// these delegates are required to keep context
		this._mouseMoveDelegate = function(event) {
			return self._mouseMove(event);
		};
		this._mouseUpDelegate = function(event) {
			return self._mouseUp(event);
		};
		$(document)
			.bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
			.bind('mouseup.'+this.widgetName, this._mouseUpDelegate);

		// preventDefault() is used to prevent the selection of text here -
		// however, in Safari, this causes select boxes not to be selectable
		// anymore, so this fix is needed
		($.browser.safari || event.preventDefault());

		event.originalEvent.mouseHandled = true;
		return true;
	},

	_mouseMove: function(event) {
		// IE mouseup check - mouseup happened when mouse was out of window
		if ($.browser.msie && !event.button) {
			return this._mouseUp(event);
		}

		if (this._mouseStarted) {
			this._mouseDrag(event);
			return event.preventDefault();
		}

		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
			this._mouseStarted =
				(this._mouseStart(this._mouseDownEvent, event) !== false);
			(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
		}

		return !this._mouseStarted;
	},

	_mouseUp: function(event) {
		$(document)
			.unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
			.unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);

		if (this._mouseStarted) {
			this._mouseStarted = false;
			this._preventClickEvent = true;
			this._mouseStop(event);
		}

		return false;
	},

	_mouseDistanceMet: function(event) {
		return (Math.max(
				Math.abs(this._mouseDownEvent.pageX - event.pageX),
				Math.abs(this._mouseDownEvent.pageY - event.pageY)
			) >= this.options.distance
		);
	},

	_mouseDelayMet: function(event) {
		return this.mouseDelayMet;
	},

	// These are placeholder methods, to be overriden by extending plugin
	_mouseStart: function(event) {},
	_mouseDrag: function(event) {},
	_mouseStop: function(event) {},
	_mouseCapture: function(event) { return true; }
};

$.ui.mouse.defaults = {
	cancel: null,
	distance: 1,
	delay: 0
};

})(jQuery);
/*
 * jQuery UI Tabs 1.6rc6
 *
 * Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Tabs
 *
 * Depends:
 *	ui.core.js
 */
(function($) {

$.widget("ui.tabs", {

	_init: function() {
		// create tabs
		this._tabify(true);
	},

	_setData: function(key, value) {
		if ((/^selected/).test(key))
			this.select(value);
		else {
			this.options[key] = value;
			this._tabify();
		}
	},

	_tabId: function(a) {
		return a.title && a.title.replace(/\s/g, '_').replace(/[^A-Za-z0-9\-_:\.]/g, '')
			|| this.options.idPrefix + $.data(a);
	},

	_sanitizeSelector: function(hash) {
		return hash.replace(/:/g, '\\:'); // we need this because an id may contain a ":"
	},

	_cookie: function() {
		var cookie = this.cookie || (this.cookie = this.options.cookie.name || 'ui-tabs-' + $.data(this.list[0]));
		return $.cookie.apply(null, [cookie].concat($.makeArray(arguments)));
	},
	
	_ui: function(tab, panel) {
		return {
			tab: tab,
			panel: panel,
			index: this.$tabs.index(tab)
		};
	},

	_tabify: function(init) {

		this.list = this.element.is('div') ? this.element.children('ul:first, ol:first').eq(0) : this.element;
		this.$lis = $('li:has(a[href])', this.list);
		this.$tabs = this.$lis.map(function() { return $('a', this)[0]; });
		this.$panels = $([]);

		var self = this, o = this.options;

		var fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
		this.$tabs.each(function(i, a) {
			var href = $(a).attr('href');

			// inline tab
			if (fragmentId.test(href))
				self.$panels = self.$panels.add(self._sanitizeSelector(href));

			// remote tab
			else if (href != '#') { // prevent loading the page itself if href is just "#"
				$.data(a, 'href.tabs', href); // required for restore on destroy

				// TODO until #3808 is fixed strip fragment identifier from url
				// (IE fails to load from such url)
				$.data(a, 'load.tabs', href.replace(/#.*$/, '')); // mutable data

				var id = self._tabId(a);
				a.href = '#' + id;
				var $panel = $('#' + id);
				if (!$panel.length) {
					$panel = $(o.panelTemplate).attr('id', id).addClass('ui-tabs-panel ui-widget-content ui-corner-bottom')
						.insertAfter(self.$panels[i - 1] || self.list);
					$panel.data('destroy.tabs', true);
				}
				self.$panels = self.$panels.add($panel);
			}

			// invalid tab href
			else
				o.disabled.push(i + 1);
		});

		// initialization from scratch
		if (init) {

			// attach necessary classes for styling
			if (this.element.is('div')) {
				this.element.addClass('ui-tabs ui-widget ui-widget-content ui-corner-all');
			}
			this.list.addClass('ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all');
			this.$lis.addClass('ui-state-default ui-corner-top');
			this.$panels.addClass('ui-tabs-panel ui-widget-content ui-corner-bottom');

			// Selected tab
			// use "selected" option or try to retrieve:
			// 1. from fragment identifier in url
			// 2. from cookie
			// 3. from selected class attribute on <li>
			if (o.selected === undefined) {
				if (location.hash) {
					this.$tabs.each(function(i, a) {
						if (a.hash == location.hash) {
							o.selected = i;
							return false; // break
						}
					});
				}
				else if (o.cookie)
					o.selected = parseInt(self._cookie(), 10);

				else if (this.$lis.filter('.ui-tabs-selected').length)
					o.selected = this.$lis.index(this.$lis.filter('.ui-tabs-selected'));

				else
				 	o.selected = 0;

			}
			else if (o.selected === null)
				o.selected = -1;

			// sanity check
			o.selected = ((o.selected >= 0 && this.$tabs[o.selected]) || o.selected < 0) ? o.selected : 0; // default to first tab

			// Take disabling tabs via class attribute from HTML
			// into account and update option properly.
			// A selected tab cannot become disabled.
			o.disabled = $.unique(o.disabled.concat(
				$.map(this.$lis.filter('.ui-state-disabled'),
					function(n, i) { return self.$lis.index(n); } )
			)).sort();
			if ($.inArray(o.selected, o.disabled) != -1)
				o.disabled.splice($.inArray(o.selected, o.disabled), 1);

			// highlight selected tab
			this.$panels.addClass('ui-tabs-hide');
			this.$lis.removeClass('ui-tabs-selected ui-state-active');
			if (o.selected >= 0 && this.$tabs.length) { // check for length avoids error when initializing empty list
				this.$panels.eq(o.selected).removeClass('ui-tabs-hide');
				var classes = ['ui-tabs-selected ui-state-active'];
				if (o.deselectable) classes.push('ui-tabs-deselectable');
				this.$lis.eq(o.selected).addClass(classes.join(' '));

				// seems to be expected behavior that the show callback is fired
				var onShow = function() {
					self._trigger('show', null,
						self._ui(self.$tabs[o.selected], self.$panels[o.selected]));
				};

				// load if remote tab
				if ($.data(this.$tabs[o.selected], 'load.tabs'))
					this.load(o.selected, onShow);
				// just trigger show event
				else onShow();
			}

			// states
			if (o.event != 'mouseover') {
				var handleState = function(state, el) {
					if (el.is(':not(.ui-state-disabled)')) el.toggleClass('ui-state-' + state);
				};
				this.$lis.bind('mouseover.tabs mouseout.tabs', function() {
					handleState('hover', $(this));
				});
				// TODO focus/blur don't seem to work with namespace
				this.$tabs.bind('focus.tabs blur.tabs', function() {
					handleState('focus', $(this).parents('li:first'));
				});
			}

			// clean up to avoid memory leaks in certain versions of IE 6
			$(window).bind('unload', function() {
				self.$lis.add(self.$tabs).unbind('.tabs');
				self.$lis = self.$tabs = self.$panels = null;
			});

		}
		// update selected after add/remove
		else
			o.selected = this.$lis.index(this.$lis.filter('.ui-tabs-selected'));

		// set or update cookie after init and add/remove respectively
		if (o.cookie) this._cookie(o.selected, o.cookie);

		// disable tabs
		for (var i = 0, li; li = this.$lis[i]; i++)
			$(li)[$.inArray(i, o.disabled) != -1 && !$(li).hasClass('ui-tabs-selected') ? 'addClass' : 'removeClass']('ui-state-disabled');

		// reset cache if switching from cached to not cached
		if (o.cache === false) this.$tabs.removeData('cache.tabs');

		// set up animations
		var hideFx, showFx;
		if (o.fx) {
			if ($.isArray(o.fx)) {
				hideFx = o.fx[0];
				showFx = o.fx[1];
			}
			else hideFx = showFx = o.fx;
		}

		// Reset certain styles left over from animation
		// and prevent IE's ClearType bug...
		function resetStyle($el, fx) {
			$el.css({ display: '' });
			if ($.browser.msie && fx.opacity) $el[0].style.removeAttribute('filter');
		}

		// Show a tab...
		var showTab = showFx ?
			function(clicked, $show) {
				$show.hide().removeClass('ui-tabs-hide') // avoid flicker that way
					.animate(showFx, 500, function() {
						resetStyle($show, showFx);
						self._trigger('show', null, self._ui(clicked, $show[0]));
					});
			} :
			function(clicked, $show) {
				$show.removeClass('ui-tabs-hide');
				self._trigger('show', null, self._ui(clicked, $show[0]));
			};

		// Hide a tab, $show is optional...
		var hideTab = hideFx ?
			function(clicked, $hide, $show) {
				$hide.animate(hideFx, hideFx.duration || 'normal', function() {
					$hide.addClass('ui-tabs-hide');
					resetStyle($hide, hideFx);
					if ($show) showTab(clicked, $show);
				});
			} :
			function(clicked, $hide, $show) {
				$hide.addClass('ui-tabs-hide');
				if ($show) showTab(clicked, $show);
			};

		// Switch a tab...
		function switchTab(clicked, $li, $hide, $show) {
			var classes = ['ui-tabs-selected ui-state-active'];
			if (o.deselectable) classes.push('ui-tabs-deselectable');
			$li.removeClass('ui-state-default').addClass(classes.join(' '))
				.siblings().removeClass(classes.join(' ')).addClass('ui-state-default');
			hideTab(clicked, $hide, $show);
		}

		// attach tab event handler, unbind to avoid duplicates from former tabifying...
		this.$tabs.unbind('.tabs').bind(o.event + '.tabs', function() {

			var $li = $(this).parents('li:eq(0)'),
				$hide = self.$panels.filter(':visible'),
				$show = $(self._sanitizeSelector(this.hash));

			// If tab is already selected and not deselectable or tab disabled or
			// or is already loading or click callback returns false stop here.
			// Check if click handler returns false last so that it is not executed
			// for a disabled or loading tab!
			if (($li.hasClass('ui-state-active') && !o.deselectable)
				|| $li.hasClass('ui-state-disabled')
				|| $(this).hasClass('ui-tabs-loading')
				|| self._trigger('select', null, self._ui(this, $show[0])) === false
				) {
				this.blur();
				return false;
			}

			o.selected = self.$tabs.index(this);

			// if tab may be closed TODO avoid redundant code in this block
			if (o.deselectable) {
				if ($li.hasClass('ui-state-active')) {
					o.selected = -1;
					if (o.cookie) self._cookie(o.selected, o.cookie);
					$li.removeClass('ui-tabs-selected ui-state-active ui-tabs-deselectable')
						.addClass('ui-state-default');
					self.$panels.stop();
					hideTab(this, $hide);
					this.blur();
					return false;
				} else if (!$hide.length) {
					if (o.cookie) self._cookie(o.selected, o.cookie);
					self.$panels.stop();
					var a = this;
					self.load(self.$tabs.index(this), function() {
						$li.addClass('ui-tabs-selected ui-state-active ui-tabs-deselectable')
							.removeClass('ui-state-default');
						showTab(a, $show);
					});
					this.blur();
					return false;
				}
			}

			if (o.cookie) self._cookie(o.selected, o.cookie);

			// stop possibly running animations
			self.$panels.stop();

			// show new tab
			if ($show.length) {
				var a = this;
				self.load(self.$tabs.index(this), $hide.length ?
					function() {
						switchTab(a, $li, $hide, $show);
					} :
					function() {
						$li.addClass('ui-tabs-selected ui-state-active').removeClass('ui-state-default');
						showTab(a, $show);
					}
				);
			} else
				throw 'jQuery UI Tabs: Mismatching fragment identifier.';

			// Prevent IE from keeping other link focussed when using the back button
			// and remove dotted border from clicked link. This is controlled via CSS
			// in modern browsers; blur() removes focus from address bar in Firefox
			// which can become a usability and annoying problem with tabs('rotate').
			if ($.browser.msie) this.blur();

			return false;

		});

		// disable click if event is configured to something else
		if (o.event != 'click') this.$tabs.bind('click.tabs', function(){return false;});

	},
	
	destroy: function() {
		var o = this.options;

		this.element
			.removeClass('ui-tabs ui-widget ui-widget-content ui-corner-all');

		this.list.unbind('.tabs')
			.removeClass('ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all')
			.removeData('tabs');

		this.$tabs.each(function() {
			var href = $.data(this, 'href.tabs');
			if (href)
				this.href = href;
			var $this = $(this).unbind('.tabs');
			$.each(['href', 'load', 'cache'], function(i, prefix) {
				$this.removeData(prefix + '.tabs');
			});
		});

		this.$lis.unbind('.tabs').add(this.$panels).each(function() {
			if ($.data(this, 'destroy.tabs'))
				$(this).remove();
			else
				$(this).removeClass(
					'ui-state-default ' +
					'ui-corner-top ' +
					'ui-tabs-selected ' +
					'ui-state-active ' +
					'ui-tabs-deselectable ' +
					'ui-state-disabled ' +
					'ui-tabs-panel ' +
					'ui-widget-content ' +
					'ui-corner-bottom ' +
					'ui-tabs-hide');
		});

		if (o.cookie)
			this._cookie(null, o.cookie);
	},

	add: function(url, label, index) {
		if (index == undefined)
			index = this.$tabs.length; // append by default

		var self = this, o = this.options;
		var $li = $(o.tabTemplate.replace(/#\{href\}/g, url).replace(/#\{label\}/g, label));
		$li.addClass('ui-state-default ui-corner-top').data('destroy.tabs', true);

		var id = url.indexOf('#') == 0 ? url.replace('#', '') : this._tabId( $('a:first-child', $li)[0] );

		// try to find an existing element before creating a new one
		var $panel = $('#' + id);
		if (!$panel.length) {
			$panel = $(o.panelTemplate).attr('id', id).data('destroy.tabs', true);
		}
		$panel.addClass('ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide');
		if (index >= this.$lis.length) {
			$li.appendTo(this.list);
			$panel.appendTo(this.list[0].parentNode);
		}
		else {
			$li.insertBefore(this.$lis[index]);
			$panel.insertBefore(this.$panels[index]);
		}

		o.disabled = $.map(o.disabled,
			function(n, i) { return n >= index ? ++n : n });

		this._tabify();

		if (this.$tabs.length == 1) { // after tabify
			$li.addClass('ui-tabs-selected ui-state-active');
			$panel.removeClass('ui-tabs-hide');
			var href = $.data(this.$tabs[0], 'load.tabs');
			if (href) this.load(0, function() {
				self._trigger('show', null,
					self._ui(self.$tabs[0], self.$panels[0]));
			});
		}

		// callback
		this._trigger('add', null, this._ui(this.$tabs[index], this.$panels[index]));
	},

	remove: function(index) {
		var o = this.options, $li = this.$lis.eq(index).remove(),
			$panel = this.$panels.eq(index).remove();

		// If selected tab was removed focus tab to the right or
		// in case the last tab was removed the tab to the left.
		if ($li.hasClass('ui-tabs-selected') && this.$tabs.length > 1)
			this.select(index + (index + 1 < this.$tabs.length ? 1 : -1));

		o.disabled = $.map($.grep(o.disabled, function(n, i) { return n != index; }),
			function(n, i) { return n >= index ? --n : n });

		this._tabify();

		// callback
		this._trigger('remove', null, this._ui($li.find('a')[0], $panel[0]));
	},

	enable: function(index) {
		var o = this.options;
		if ($.inArray(index, o.disabled) == -1)
			return;

		this.$lis.eq(index).removeClass('ui-state-disabled');
		o.disabled = $.grep(o.disabled, function(n, i) { return n != index; });

		// callback
		this._trigger('enable', null, this._ui(this.$tabs[index], this.$panels[index]));
	},

	disable: function(index) {
		var self = this, o = this.options;
		if (index != o.selected) { // cannot disable already selected tab
			this.$lis.eq(index).addClass('ui-state-disabled');

			o.disabled.push(index);
			o.disabled.sort();

			// callback
			this._trigger('disable', null, this._ui(this.$tabs[index], this.$panels[index]));
		}
	},

	select: function(index) {
		if (typeof index == 'string')
			index = this.$tabs.index(this.$tabs.filter('[href$=' + index + ']'));
		this.$tabs.eq(index).trigger(this.options.event + '.tabs');
	},

	load: function(index, callback) { // callback is for internal usage only

		var self = this, o = this.options, $a = this.$tabs.eq(index), a = $a[0],
				bypassCache = callback == undefined || callback === false, url = $a.data('load.tabs');
				// TODO bypassCache == false should work

		callback = callback || function() {};

		// no remote or from cache - just finish with callback
		// TODO in any case: insert cancel running load here..!
		
		if (!url || !bypassCache && $.data(a, 'cache.tabs')) {
			callback();
			return;
		}

		// load remote from here on

		var inner = function(parent) {
			var $parent = $(parent), $inner = $parent.find('*:last');
			return $inner.length && $inner.is(':not(img)') && $inner || $parent;
		};
		var cleanup = function() {
			self.$tabs.filter('.ui-tabs-loading').removeClass('ui-tabs-loading')
					.each(function() {
						if (o.spinner)
							inner(this).parent().html(inner(this).data('label.tabs'));
					});
			self.xhr = null;
		};

		if (o.spinner) {
			var label = inner(a).html();
			inner(a).wrapInner('<em></em>')
				.find('em').data('label.tabs', label).html(o.spinner);
		}

		var ajaxOptions = $.extend({}, o.ajaxOptions, {
			url: url,
			success: function(r, s) {
				$(self._sanitizeSelector(a.hash)).html(r);
				cleanup();

				if (o.cache)
					$.data(a, 'cache.tabs', true); // if loaded once do not load them again

				// callbacks
				self._trigger('load', null, self._ui(self.$tabs[index], self.$panels[index]));
				try {
					o.ajaxOptions.success(r, s);
				}
				catch (er) {}

				// This callback is required because the switch has to take
				// place after loading has completed. Call last in order to
				// fire load before show callback...
				callback();
			}
		});
		if (this.xhr) {
			// terminate pending requests from other tabs and restore tab label
			this.xhr.abort();
			cleanup();
		}
		$a.addClass('ui-tabs-loading');
		self.xhr = $.ajax(ajaxOptions);
	},

	url: function(index, url) {
		this.$tabs.eq(index).removeData('cache.tabs').data('load.tabs', url);
	},
	
	length: function() {
		return this.$tabs.length;
	}

});

$.extend($.ui.tabs, {
	version: '1.6rc6',
	getter: 'length',
	defaults: {
		ajaxOptions: null,
		cache: false,
		cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
		deselectable: false,
		disabled: [],
		event: 'click',
		fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
		idPrefix: 'ui-tabs-',
		panelTemplate: '<div></div>',
		spinner: 'Loading&#8230;',
		tabTemplate: '<li><a href="#{href}"><span>#{label}</span></a></li>'
	}
});

/*
 * Tabs Extensions
 */

/*
 * Rotate
 */
$.extend($.ui.tabs.prototype, {
	rotation: null,
	rotate: function(ms, continuing) {

		var self = this, t = this.options.selected;

		function rotate() {
			clearTimeout(self.rotation);
			self.rotation = setTimeout(function() {
				t = ++t < self.$tabs.length ? t : 0;
				self.select(t);
			}, ms);
		}

		// start rotation
		if (ms) {
			this.element.bind('tabsshow', rotate); // will not be attached twice
			this.$tabs.bind(this.options.event + '.tabs', !continuing ?
				function(e) {
					if (e.clientX) { // in case of a true click
						clearTimeout(self.rotation);
						self.element.unbind('tabsshow', rotate);
					}
				} :
				function(e) {
					t = self.options.selected;
					rotate();
				}
			);
			rotate();
		}
		// stop rotation
		else {
			clearTimeout(self.rotation);
			this.element.unbind('tabsshow', rotate);
			this.$tabs.unbind(this.options.event + '.tabs', stop);
		}
	}
});

})(jQuery);
/*
 * Date picker plugin for jQuery
 * http://kelvinluck.com/assets/jquery/datePicker
 *
 * Copyright (c) 2006 Kelvin Luck (kelvinluck.com)
 * Licensed under the MIT License:
 *   http://www.opensource.org/licenses/mit-license.php
 *
 * $LastChangedDate: 2007-04-12 10:01:01 +0100 (Thu, 12 Apr 2007) $
 * $Rev: 1672 $
 */

eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('8.E=f(){9(1v.23==M){1v.23={3X:f(){}}}4 X=[\'3q\',\'3j\',\'3b\',\'32\',\'45\',\'43\',\'3W\',\'3T\',\'3Q\',\'3M\',\'3E\',\'3x\'];4 1p=[\'3n\',\'3i\',\'3d\',\'3a\',\'35\',\'31\',\'2X\'];4 W={p:\'42\',n:\'3V\',c:\'3S\',b:\'3P 1d\'};4 1h=\'1R\';4 x="/";4 1f=C;4 N;4 G;4 H;4 S;4 A;4 1P=f(2k){4 s=\'0\'+2k;h s.38(s.1C-2)};4 19=f(P){2H(1h){O\'2R\':r=P.1l(x);h t v(r[0],Q(r[1])-1,r[2]);O\'1R\':r=P.1l(x);h t v(r[2],Q(r[1])-1,Q(r[0]));O\'2L\':r=P.1l(x);1N(4 m=0;m<12;m++){9(r[1].1j()==X[m].1J(0,3).1j()){h t v(Q(r[2]),m,Q(r[0]))}}h M;O\'2v\':2D:4 1G=1G?1G:[2,1,0];r=P.1l(x);h t v(r[2],Q(r[0])-1,Q(r[1]))}};4 1F=f(d){4 18=d.g();4 1g=1P(d.k()+1);4 1b=1P(d.14());2H(1h){O\'2R\':h 18+x+1g+x+1b;O\'1R\':h 1b+x+1g+x+18;O\'2L\':h 1b+x+X[d.k()].1J(0,3)+x+18;O\'2v\':2D:h 1g+x+1b+x+18}};4 Y=f(P){4 U=t v();9(P==M){d=t v(U.g(),U.k(),1)}I{d=P;d.2i(1)}9((d.k()<G.k()&&d.g()==G.g())||d.g()<G.g()){d=t v(G.g(),G.k(),1)}I 9((d.k()>H.k()&&d.g()==H.g())||d.g()>H.g()){d=t v(H.g(),H.k(),1)}4 R=8("<j></j>").q(\'u\',\'B-D\');4 1q=17;4 2b=G.14();4 1s=\'\';9(!(d.k()==G.k()&&d.g()==G.g())){1q=C;4 2d=d.k()==0?t v(d.g()-1,11,1):t v(d.g(),d.k()-1,1);4 2c=8("<a></a>").q(\'13\',\'Z:;\').J(W.p).1a(f(){8.E.1S(2d,l);h C});1s=8("<j></j>").q(\'u\',\'1o-37\').J(\'&36;\').o(2c)}4 1B=17;4 1Z=H.14();1H=\'\';9(!(d.k()==H.k()&&d.g()==H.g())){1B=C;4 1X=t v(d.g(),d.k()+1,1);4 1V=8("<a></a>").q(\'13\',\'Z:;\').J(W.n).1a(f(){8.E.1S(1X,l);h C});1H=8("<j></j>").q(\'u\',\'1o-30\').J(\'&2Y;\').2W(1V)}4 1U=8("<a></a>").q(\'13\',\'Z:;\').J(W.c).1a(f(){8.E.2O()});R.o(8("<j></j>").q(\'u\',\'1o-2S\').o(1U),8("<2Q></2Q>").J(X[d.k()]+\' \'+d.g()));4 1T=8("<1n></1n>");1N(4 i=N;i<N+7;i++){4 L=i%7;4 1k=1p[L];1T.o(8("<2P></2P>").q({\'41\':\'40\',\'3Z\':1k,\'1Q\':1k,\'u\':(L==0||L==6?\'2M\':\'L\')}).J(1k.1J(0,1)))}4 1O=8("<2K></2K>");4 2G=(t v(d.g(),d.k()+1,0)).14();4 y=N-d.3U();9(y>0)y-=7;4 2F=(t v()).14();4 2B=d.k()==U.k()&&d.g()==U.g();4 w=0;2z(w++<6){4 1K=8("<1n></1n>");1N(4 i=0;i<7;i++){4 L=(N+i)%7;4 16={\'u\':(L==0||L==6?\'2M \':\'L \')};9(y<0||y>=2G){V=\' \'}I 9(1q&&y<2b-1){V=y+1;16[\'u\']+=\'2x\'}I 9(1B&&y>1Z-1){V=y+1;16[\'u\']+=\'2x\'}I{d.2i(y+1);4 1I=1F(d);V=8("<a></a>").q({\'13\':\'Z:;\',\'2A\':1I}).J(y+1).1a(f(e){8.E.2C(8.q(l,\'2A\'),l);h C})[0];9(S&&S==1I){8(V).q(\'u\',\'3R\')}}9(2B&&y+1==2F){16[\'u\']+=\'U\'}1K.o(8("<2t></2t>").q(16).o(V));y++}1O.o(1K)}R.o(8("<2s></2s>").q(\'3O\',2).o("<1L></1L>").2q("1L").o(1T).1M().o(1O.3N())).o(1s).o(1H);9(8.2p.2o){4 1D=[\'<1D u="3L" 3K="-1" 3J="3I.J" \',\'3F="1x:2m; 3D:3C;\',\'3B: 0;\',\'3A:0;\',\'z-3z:-1; 3y:3w(3v=\\\'0\\\');\',\'3u:2h;\',\'3t:2h"/>\'].3s(\'\');R.o(1y.3r(1D))}R.2g({\'1x\':\'2m\'});h R[0]};4 10=f(c){8(\'j.B-D a\',A[0]).1w();8(\'j.B-D\',A[0]).2f();8(\'j.B-D\',A[0]).3p();A.o(c)};4 T=f(){8(\'j.B-D a\',A).1w();8(\'j.B-D\',A).2f();8(\'j.B-D\',A).2g({\'1x\':\'3o\'});8(1y).1w(\'2e\',1u);3m A;A=3l};4 3k=f(e){4 2a=e.29?e.29:(e.28?e.28:0);9(2a==27){T()}h C};4 1u=f(e){9(!1f){4 1t=8.2p.2o?1v.3h.3g:e.1t;4 26=8(1t).1m(\'j.B-D-1r\');9(26.3f(0).3e!=\'1d-1e-25\'){T()}}};h{24:f(){h W.b},2j:f(){9(A){T()}l.3c();4 F=8(\'F\',8(l).1m(\'F\')[0])[0];G=F.1A;H=F.15;N=F.N;A=8(l).1M().2q(\'>j.B-D-1r\');4 d=8(F).22();9(d!=\'\'){9(1F(19(d))==d){S=d;10(Y(19(d)))}I{S=C;10(Y())}}I{S=C;10(Y())}8(1y).2l(\'2e\',1u)},1S:f(d,e){1f=17;10(Y(d));1f=C},2C:f(d,K){39=d;4 $1z=8(\'F\',8(K).1m(\'F\')[0]);$1z.22(d);$1z.3G(\'3H\');T(K)},2O:f(){T(l)},2u:f(i){i.21=17},2n:f(i){h i.21!=M},34:f(20,1E){1h=20.1j();x=1E?1E:"/"},33:f(1Y,2r,1W){1p=1Y;X=2r;W=1W},2J:f(i,w){9(w==M)w={};9(w.2y==M){i.1A=t v()}I{i.1A=19(w.2y)}9(w.2w==M){i.15=t v();i.15.2Z(i.15.g()+5)}I{i.15=19(w.2w)};i.N=w.2I==M?0:w.2I}}}();8.2E.1m=f(s){4 K=l;2z(17){9(8(s,K[0]).1C>0){h(K)}K=K.1M();9(K[0].1C==0){h C}}};8.2E.E=f(a){l.2V(f(){9(l.3Y.1j()!=\'F\')h;8.E.2J(l,a);9(!8.E.2n(l)){4 1i=8.E.24();4 1c;9(a&&a.2U){1c=8(l).q(\'1Q\',1i).2T(\'1d-1e\')}I{1c=8("<a></a>").q({\'13\':\'Z:;\',\'u\':\'1d-1e\',\'1Q\':1i}).o("<2N>"+1i+"</2N>")}8(l).44(\'<j u="1d-1e-25"></j>\').46(8(\'<j></j>\').q(\'u\',\'B-D-1r\').o(8("<j></j>").q({\'u\':\'B-D\'})),1c);1c.2l(\'1a\',8.E.2j);8.E.2u(l)}});h l};',62,255,'||||var||||jQuery|if||||||function|getFullYear|return||div|getMonth|this|||append||attr|dParts||new|class|Date||dateSeparator|curDay||_openCal|popup|false|calendar|datePicker|input|_firstDate|_lastDate|else|html|ele|weekday|undefined|_firstDayOfWeek|case|dIn|Number|jCalDiv|_selectedDate|_closeDatePicker|today|dayStr|navLinks|months|_getCalendarDiv|javascript|_draw|||href|getDate|_endDate|atts|true|dY|_strToDate|click|dD|calBut|date|picker|_drawingMonth|dM|dateFormat|chooseDate|toLowerCase|day|split|findClosestParent|tr|link|days|firstMonth|wrapper|prevLinkDiv|target|_checkMouse|window|unbind|display|document|theInput|_startDate|finalMonth|length|iframe|separator|_dateToStr|parts|nextLinkDiv|dStr|substr|thisRow|thead|parent|for|tBody|_zeroPad|title|dmy|changeMonth|headRow|closeLink|nextLink|aNavLinks|nextMonth|aDays|lastDate|format|_inited|val|console|getChooseDateStr|holder|cp||which|keyCode|key|firstDate|prevLink|lastMonth|mousedown|empty|css|3000px|setDate|show|num|bind|block|isInited|msie|browser|find|aMonths|table|td|setInited|mdy|endDate|inactive|startDate|while|rel|thisMonth|selectDate|default|fn|todayDate|lastDay|switch|firstDayOfWeek|setDateWindow|tbody|dmmy|weekend|span|closeCalendar|th|h3|ymd|close|addClass|inputClick|each|prepend|Saturday|gt|setFullYear|next|Friday|April|setLanguageStrings|setDateFormat|Thursday|lt|prev|substring|selectedDate|Wednesday|March|blur|Tuesday|className|get|srcElement|event|Monday|February|_handleKeys|null|delete|Sunday|none|remove|January|createElement|join|height|width|Opacity|Alpha|December|filter|index|left|top|absolute|position|November|style|trigger|change|blank|src|tabindex|bgiframe|October|children|cellspacing|Choose|September|selected|Close|August|getDay|Next|July|log|nodeName|abbr|col|scope|Prev|June|wrap|May|after'.split('|'),0,{}))
document.write("<style>.formHelp{display:none;}</style>");
document.write("<style>.formValidator{display:none;}</style>");
jQuery.addMutator(function(ctx) {
 var $ctx = jQuery(ctx);
 var links = jQuery("a.select_addedit", ctx);
 links.each(function() {
  var actionButton = jQuery(this);
  var fieldName = this.getAttribute("fieldName");
  var ptr = this.parentNode;
  while (ptr != null && ptr.nodeName != "FORM") ptr = ptr.parentNode;
  if (ptr == null) return;
  var selector = jQuery("select[name='" + fieldName + "']", ptr);
  if (selector.length == 0) return;
  if (!selector.attr("changer_installed")) {
   selector.attr("changer_installed", true).change(function() {
    if (this.selectedIndex == 0) {
     actionButton
      .show()
      .empty()
      .append("<span>" + actionButton.attr("addTitle") + "</span>")
      .attr("wsWidgetName", actionButton.attr("addWidget"))
      .attr("wsTitle", actionButton.attr("addTitle"))
      .attr("href", actionButton.attr("addHref"));
    } else {
     actionButton
      .show()
      .empty()
      .append("<span>" + actionButton.attr("editTitle") + "</span>")
      .attr("wsWidgetName", actionButton.attr("editWidget"))
      .attr("wsTitle", actionButton.attr("editTitle"))
      .attr("href", actionButton.attr("editHref") + this.options[this.selectedIndex].value);
    }
    selector.WidgetSendResizeEvent();
   });
  }
  selector.change();
  actionButton.applyMutators();
 });
 jQuery.datePicker.setDateFormat('mdy','/');
 $('.date-picker', ctx).datePicker({startDate: "01/01/1970"}); //.bind("dpClosed", function() { alert("dpClosed"); jQuery(this).sendResizeEvent(); });;
 //jQuery("a.date-picker", ctx).click(function() { setTimeout(function() { jQuery(this).sendResizeEvent(); }, 1000); return false; });
 var s = jQuery(".formValidator", ctx).hide();
 jQuery(".formHelp:not(:empty)", ctx)
  .before("<span class='formHelpIcon' style='display: inline; font-size: 120%; color: red; cursor: pointer;' href='#'>?</span>")
  .css("background-color", "#ffffff")
  .css("border", "1px solid black")
  .css("display", "none")
  .css("position", "absolute")
  .each(
   function() {
    var helpBox = jQuery(this);
    jQuery(this.previousSibling)
     .mousemove(
      function(e) {
       var xy = webslinger.fixMouseEvent(e);
       helpBox.css("top", xy[1] + 10).css("left", xy[0] + 10);
      }
     ).hover(
      function(e) {
       var xy = webslinger.fixMouseEvent(e);
       helpBox.css("top", xy[1] + 10).css("left", xy[0] + 10).show();
      },
      function(e) {
       helpBox.hide();
      }
     ).click(function() { return false; });
    jQuery("body").append(this);
   }
  );
 jQuery("input[disabled], textarea[disabled], select[disabled]", ctx).addClass("disabled");
 jQuery("input[overlayLabel], textarea[overlayLabel]").each(function() {
  var $this = jQuery(this);
  var id = this.getAttribute('id');
  this.removeAttribute('id');
  $this.css('position', 'relative');
  $this.after('<span style="position: relative;"></span>');
  var $container = $($this.get(0).nextSibling);
  if (id) $container.attr('id', id);
  $container.append($this);
  $container.append('<span style="position: absolute; top: 0px; left: 5px;"></span>');
  var $label = $($container.get(0).lastChild);
  $label.append(this.getAttribute('overlayLabel'));
  $this.focus(function() {
   $label.hide();
  }).blur(function() {
   if ($this.val() == null || $this.val().length == 0) {
    $label.show();
   } else {
    $label.hide();
   }
  }).blur();
 });
 jQuery("input[SFLookup]", ctx)
  .each(function() {
   jQuery(this).after("<span class='formLookup' style='display: inline; font-size: 120%; color: green; cursor: pointer;'>" + this.getAttribute('SFLookup') + "?</span>");
   var input = this;
   jQuery(this.nextSibling).click(function() {
    alert('clicked(' + input.getAttribute('SFLookup') + ')');
   });
  }
 );
 $ctx.find('form').each(function() {
  var $form = jQuery(this);
  var deps = {};
  $form.find('[sfDisplay]').each(function() {
   deps[this.getAttribute('sfDisplay')] = true;
  });
  for (var id in deps) {
   $form.find('[speedFormId="' + id + '"]').change(function() {
    var $items = $form.find('[sfDisplay="' + this.getAttribute('speedFormId') + '"]');
    var type = this.getAttribute('type');
    if (type == null) type = 'text';
    type = type.toLowerCase();
    var active;
    if ('checkbox' == type || 'radio' == type) {
     active = this.checked;
    } else {
     active = jQuery(this).val() != '';
    }
    if (active) {
     $items.show();
    } else {
     $items.hide();
    }
   }).change();
  }
 });
});


/* Shindig Support */
 try {
   //gadgets.IfrGadget.serverBase_ = '/shindig/gadgets/';
//     gadgets.IfrGadget.setServerBase('/shindig/gadgets/');
//   gadgets.IfrGadget.setServerBase('/shindig/gadgets/');
 } catch (e) {
  alert('foo:' + e);
 }
 /*
window.dhtmlHistory.create({
 toJSON: function(o) { return JSON.stringify(o); },
 fromJSON: function(s) { return JSON.parse(s); }
});
jQuery(window).load(function() {
 window.dhtmlHistory.initialize();
});
*/

var lastPathLoaded = window.location.pathname;
$.metadata.setType("attr", "data");

function pageTree(selector) {
	var $nodes = $(selector);
	$nodes.each(function() {
		var $node = $(this);
		var metadata = $node.metadata();
		$node.data('pageTree', {path: metadata.path});
	});
	var rootNodes = [];
	$nodes.each(function() {
		var $node = $(this);
		var ptr = this.parentNode;
		while (ptr != null) {
			var $ptr = $(ptr);
			var parentTree = $ptr.data('pageTree');
			if (parentTree) {
				//alert('found parent:[' + parentTree + ':' + typeof parentTree + ']');
				if (!parentTree.children) {
					parentTree.children = [];
				}
				parentTree.children.push($node);
				return
			}
			ptr = ptr.parentNode;
		}
		rootNodes.push($node);
	});
	$nodes.each(function() {
		var $node = $(this);
		var pageTree = $node.data('pageTree');
		if (pageTree.children) {
			var tree = {};
			for (var i = 0; i < pageTree.children.length; i++) {
				var child = pageTree.children[i];
				var data = pageTree.children[i].data('pageTree');
				tree[child.metadata().name] = child.data('pageTree');
			}
			delete pageTree.children;
			pageTree.tree = tree;
		}
	});
	var result = {};
	$.each(rootNodes, function() {
		result[this.metadata().name] = this.data('pageTree');
	});
	$nodes.each(function() {
		$(this).removeData('pageTree');
	});
	return result;
}

function setMenu() {
	$('#setleftform').attr('action','/Edit' + webslinger.getPath());
	$('#setleftform').ajaxSubmit(function() { 
		webslinger.pageReload();
	});
}

function insertToolbar(id) {
	$('.mceToolbarExternal').appendTo(id);
}

function findPos(obj) {
	var curleft = curtop = 0;
	if (obj.offsetParent) {
		curleft = obj.offsetLeft
		curtop = obj.offsetTop
		while (obj = obj.offsetParent) {
			curleft += obj.offsetLeft
			curtop += obj.offsetTop
		}
	}
	return [curleft,curtop];
}
function createPathTimeoutHandler(handler, href) {
	return function(type, error) {
		switch (type) {
			case "server":
				if (error.timeout) {
					window.location.replace(href);
				}
				return;
		}
		if (handler) handler(type, error);
	};
}

function getContent(path, loadParameters, callback) {
	jQuery.ajax({
		type:		"POST",
		url:		"/AJAX/Load/" + path,
		data:		loadParameters,
		dataType:	'html',
		error:		function() {
			window.location.replace(path);
		},
		success:	callback
	});
}

function preopenMenu(path) {
	var treeItem = $("#menuwrapper li[href$='" + path + "']");
	var nodes = [];
	var ptr = treeItem[0];
	while (ptr && ptr.getAttribute("id") != 'menuwrapper') {
		nodes[nodes.length] = ptr;
		ptr = ptr.parentNode;
	}
	for (var i = nodes.length - 1; i >= 0; i--) {
		$(nodes[i]).trigger('Tree:Node:Open');
	}
}

(function() {
	var $busy;
	webslinger.addBusyHandler(function(cmd) {
		$busy = $('#AjaxBusy');
		if (cmd == 'start') {
			var $win = $(window);
			$busy.css({
				top:	($win.height() - $busy.height()) / 2,
				left:	($win.width() - $busy.width()) / 2
			});
			$busy.fadeIn(500);
		} else if (cmd == 'end') {
			$busy.fadeOut(500);
		}
	});
})();
(function($) {
	$.fx.step.width = $.fx.step.height = function(fx) {
		var ptr = fx.elem;
		while (ptr != null) {
			$(ptr).resize();
			if (ptr.style && ptr.style.position == 'absolute') break;
			ptr = ptr.parentNode;
		}
		return $.fx.step._default(fx);
	};
})(jQuery);
(function($) {
	jQuery.timedEventHandler = function(period, handler) {
		var timerId = null;
		return function() {
			if (!timerId) {
				timerId = setTimeout(function() {
					timerId = null;
					handler();
				}, period);
				handler();
			}

		};
	};
})(jQuery);
(function($) {
	var $win = $(window);
	var animationSpeed = 1000;
	var modalPanelHtml = '<div class="ModalContainer"><div class="ModalOverlay"></div></div>';
	var modalWindowHtml = '<div class="ModalWindow"><div class="ModalHeader"><h1 class="ModalTitle PageTitle">&nbsp;</h1><div class="ModalActions"><a href="#" class="ModalClose"></a></div></div><div class="ModalContent"></div></div>';
	var $modalPanel, $modalWindow;
	var overlaySetPosition = function() {
		if (!$modalWindow) return;
		$modalPanel.css({
			left: $win.scrollLeft(),
			top: $win.scrollTop()
		});
	};
	var modalSetPosition = function() {
		if (!$modalWindow) return;
		var dims = {
			win:	{ width: $win.width(), height: $win.height() },
			modal:	{ width: $modalWindow.width(), height: $modalWindow.height() }
		};
		$modalPanel.find('.ModalOverlay').height(Math.max(dims.modal.height, dims.win.height));
		$modalPanel.find('.ModalOverlay').width(Math.max(dims.modal.width, dims.win.width));
		$modalWindow.css({
			left: Math.max((dims.win.width - dims.modal.width) / 2, 0) + 'px',
			top: Math.max((dims.win.height - dims.modal.height) / 2, 0) + 'px'
		});
	};
	var onWindowResize = $.timedEventHandler(50, modalSetPosition);
	var setModalContents = function($content, withTitle) {
		var $animationCtx;
		if (!$modalPanel) {
			$animationCtx = $modalPanel = $(modalPanelHtml).appendTo(document.body);
			$modalPanel.find('.ModalOverlay').click(function() {
				$modalPanel.find('.ModalClose').click();
			});
			$.disableFlash();
			$modalWindow = $(modalWindowHtml).appendTo(document.body);
			$win.bind('resize', onWindowResize).bind('scroll', overlaySetPosition);
		} else {
			$animationCtx = $modalWindow = $(modalWindowHtml).appendTo(document.body);
		}
		$animationCtx.css({
			visibility: 'hidden'
		});
		$modalWindow.find('.ModalClose').attr('href', lastPathLoaded);
		if (!withTitle) $modalWindow.find('.ModalTitle').remove();
		$modalWindow.find('.ModalContent').append($content);
		$modalWindow.applyMutators().appendTo($modalPanel);
		$modalWindow.resize(modalSetPosition);
		modalSetPosition();
		overlaySetPosition();
		$animationCtx.fadeIn(animationSpeed).css({
			visibility: 'visible'
		});
	};
	var kill = function($ctx, speed) {
		$ctx.fadeOut(speed, function() {
			$ctx.remove();
		});
		return null;
	};
	$.setModalContents = function($content, withTitle) {
		if (withTitle == null) withTitle = true;
		if (!$content) {
			if ($modalPanel) {
				$.enableFlash();
				isAttached = false;
				$modalPanel = kill($modalPanel, animationSpeed);
				$modalWindow = null;
				$win.unbind('resize', onWindowResize).unbind('scroll', overlaySetPosition);
			}
		} else {
			if ($modalPanel) {
				$modalWindow = kill($modalWindow, animationSpeed);
			}
			setModalContents($content, withTitle);
		}
	};
})(jQuery);
(function($) {
	$.fn.applyAjaxContent = function($contents) {
		return this.each(function() {
			var $this = $(this);
			var meta = $this.metadata();
			var $target;
			var ajaxUpdateStyle
			switch (meta.ajaxUpdateStyle) {
				case 'fade':
					ajaxUpdateStyle = function($target, $contents) {
						$target.fadeOut(function() {
							$target.empty().append($contents).applyMutators().fadeIn();
						});
					};
					break;
				case 'slide':
					ajaxUpdateStyle = function($target, $contents) {
						$target.slideUp(function() {
							$target.empty().append($contents).applyMutators().slideDown();
						});
					};
					break;
				case 'slide-slow':
					ajaxUpdateStyle = function($target, $contents) {
						$target.slideUp('slow', function() {
							$target.empty().append($contents).applyMutators().slideDown('slow');
						});
					};
					break;
				default:
					ajaxUpdateStyle = function($target, $contents) {
						$target.empty().append($contents).applyMutators();
					};
			}
			if (meta.ajaxTargetSelector) {
				$target = $this.find(meta.ajaxTargetSelector);
			} else {
				$target = $this;
			}
			ajaxUpdateStyle($target, $contents.clone());
		});
	};
})(jQuery);
function processAjaxResult(path, data, $target) {
	var $div = $($('body').prepend(document.createElement('div'))[0].firstChild).hide();
	var $data = $div.html(data).children();
	var isDirect = $data.find('input[name="isDirect"]').val();
	var isPopup = 'true' == $data.find('input[name="isPopup"]').val();
	var newHistoryItem = $data.find('input[name="newHistoryItem"]').val();

	var currentPagePath = webslinger.getPath();
	var hash = path.indexOf('#');
	var jumpPoint;
	var href;
	var hasTarget = $target != null;
	if (hash != -1) {
		jumpPoint = path.substring(hash + 1);
		href = path.substring(0, hash);
	} else {
		href = path;
	}
	if (isDirect == 'true') {
		window.location.replace(href);
		return;
	}
	if (newHistoryItem) {
		fireDummyClick(newHistoryItem);
		return;
	}
	if (currentPagePath == href && jumpPoint) return;
	if (!isPopup) lastPathLoaded = href;
	if (hasTarget) {
		$target.applyAjaxContent($data.find('.AJAX_hasTarget').contents());
	} else {
		if (isPopup) {
			$.setModalContents($data.find('.AJAX_hasTarget').contents());
		} else {
			$.setModalContents(null);
			$data.find('.AJAX_content').each(function() {
				var $this = $(this);
				var meta = $this.metadata();
				var $target = $(meta.selector);
				$target.metadata().path = meta.path;
				$target.applyAjaxContent($this.contents());
			});
		}
		var $docTitleData = $data.find('div[class="AJAX_doctitle"]');
		if ($docTitleData.length) document.title = $docTitleData.text();
		var $titleData = $data.find('div[class="AJAX_title"]');
		if ($titleData.length) {
			title = $titleData.text();
			$('.PageTitle').text(title).attr('path', href);
		}
	}
	$div.remove();
}
function fireDummyClick(path) {
	var $historyDummy = $('<div><a>dummy</a></div>');
	$historyDummy.find('a').attr('href', path);
	$historyDummy.applyMutators();
	$historyDummy.find('a').click();
}
function loadPath(path, doHistory, $target) {
	if (doHistory) {
		fireDummyClick(path);
		return;
	}
	var currentPagePath = webslinger.getPath();
	var hash = path.indexOf('#');
	var jumpPoint;
	var href;
	var hasTarget = $target != null;
	if (hash != -1) {
		jumpPoint = path.substring(hash + 1);
		href = path.substring(0, hash);
	} else {
		href = path;
	}
	function finish() {
		preopenMenu(path);

		$(document.body).trigger('ajaxStop');
		if (jumpPoint) {
			var $a = jQuery("a[name='" + jumpPoint + "']");
			//alert("jumpPoint(" + jumpPoint + "): $a.length=" + $a.length);
			var offset = $a.offset();
			//alert(webslinger.toJSON(offset));
			var scrollTo = offset.top + offset.scrollTop;
			setTimeout(function() { window.scrollTo(0, scrollTo); }, 0);
		}
	}
	if (href.indexOf("mailto:") == 1) {
		window.location = href.substring(1);
		return;
	}
	$(document.body).trigger('ajaxStart');
	if (currentPagePath == href && jumpPoint) {
		finish();
		return;
	}
	jQuery('a[ajax-href-prefix]').each(function() {
		this.setAttribute('href', this.getAttribute('ajax-href-prefix') + path);
	});
	var params = {};
	if (hasTarget) {
		params.AJAX_hasTarget = true;
	} else {
		params.AJAX_pageTree = webslinger.toJSON(pageTree('.ajax-target'), false, false);
	}
	getContent(
		href,
		params,
		webslinger.cleanupFunction(function(data) {
			processAjaxResult(path, data, $target);
		}, finish),
		createPathTimeoutHandler(null, href)
	);
}
//webslinger.setHistoryListener(loadPath);

/*
 * This is the main JQuery documentReady segment. This activates most of the app logic when
 * a page load successfully completes.
 */
$(document).ready(function(){
	$('#quick_resources').transientClick(
		function(e) {
			return $('#drop_down_menu').is(':hidden');
		},
		function(e) {
			$('#drop_down_menu').slideDown();
			return function() {
				$('#drop_down_menu').slideUp();
			};
		}
	);
});
(function($) {
	var busyCount = 0;
	jQuery.extend({
		enableFlash:	function() {
			busyCount--;
			if (busyCount == 0) {
				$('.FlashMovie').flashstatus(true);
			}
		},
		disableFlash:	function() {
			if (busyCount == 0) {
				$('.FlashMovie').flashstatus(false);
			}
			busyCount++;
		},
		isFlashEnabled:	function() {
			return busyCount == 0;
		}
	});
})(jQuery);
(function() {
 var toPrepend = '<img style="position:relative;" align="left" class="TreeActionToggle" closeImg="/Images/tree/tree-plus-mid" openImg="/Images/tree/tree-minus-mid" src="/Images/tree/tree-minus-mid" />';
 var installTree = function(tree) {
  var uls = tree.find('ul:not(.DynamicTree):not([_TreeFixed_])').attr('_TreeFixed_', true).hide();
  uls.each(function() {
   var found = [];
   jQuery(this).parents('li:first:not(.DynamicNode)').each(function() {
    if (this.getAttribute('_TreeFixed_')) return;
    this.setAttribute('href', jQuery(this).children('a').attr('href'));
    this.setAttribute('_TreeFixed_', true);
    found.push(this);
   });
   jQuery(found).prepend(toPrepend);
  });
  tree.wstree({
   removeTree: function(tree, item) {
   }
  });
 };
 jQuery.addMutator(function(ctx) {
  installTree($(ctx).find('.Tree'));
 });
 jQuery.addMutator(function(ctx) {
  var tree = $('#menuwrapper > div > ul, #menuwrapper > div > div > ul').not('.Tree, .DynamicTree');
  installTree(tree);
  if (webslinger.getPath()) preopenMenu(webslinger.getPath());
 });
})();
(function($) {
	var wrapper = '<div class="BoxWrapper"><div class="BoxContent"></div><div class="BoxWest"></div><div class="BoxEast"></div><div class="BoxNorth"></div><div class="BoxNorthWest"></div><div class="BoxNorthEast"></div><div class="BoxSouth"></div><div class="BoxSouthWest"></div><div class="BoxSouthEast"></div></div>';
	var classes = ['.box-phd', '.box-simple', '.box-simple2', '.box-simple3', '.box-inset_white', '.box-alert', '.box-goldstrip', '.box-main', '.box-dev1', '.box-yummain'].join(', ');
	$.addMutator(function(ctx) {
		var $found = $(ctx).find(classes);
		$found.wrapInner(wrapper).filter('td').each(function() {
			var thiz = this;
			setTimeout(function() {
				$(thiz.firstChild).height($(thiz).height());
			}, 0);
		});
	});
})(jQuery);
(function($) {
	$.fn.extend({
		toggleFlipper: function($a, $b, setter) {
			return this.toggle(function() {
				setter($a, $b);
			}, function() {
				setter($b, $a);
			});
		}
	});
})(jQuery);
(function($) {
	var directionsHtml = '<div><form class="AjaxForm"><table border="1"><tbody><tr><td align="right">From:</td><td><input name="from" /></td><td class="switch" rowspan="2" style="cursor: pointer;">switch</td></tr><tr><td align="right">To:</td><td><input name="to" /></td></tr><tr><td>&nbsp;</td><td colspan="2"><input type="submit" /></td></tr></tbody></table></form></div>';
	$.fn.extend({
		directions:	function(action, address) {
			return this.each(function() {
				var $this = $(this);
				if (!address) {
					address = $this.text();
				}
				var $directions = $(directionsHtml);
				$directions.find('form').attr('action', action);
				$directions.applyMutators();

				var $from = $directions.find('input[name="from"]');
				var $to = $directions.find('input[name="to"]');
				$this.empty().append($directions);
				$directions.find('.switch').toggleFlipper($from, $to, function($a, $b) {
					$a.attr('readonly', false).val($b.val());
					$b.val(address).attr('readonly', true);
				}).click();
			});
		}
	});
})(jQuery);
jQuery.addMutator(function(ctx) {
	var onblur = function() {
		var $doc = $(document);
		var $foo = $doc.find('.FormLabelOverlay').each(function() {
			var for_ = this.getAttribute('for');
			if (!for_) return;
			var $label = $(this);
			var $input = $doc.find('#' + for_);
			if ($input.length == 0) return;
			if (!$input.val()) {
				$label.show();
			} else {
				$label.hide();
			}
		});
	};
	var foo = $(ctx).find('.FormLabelOverlay').each(function() {
		var for_ = this.getAttribute('for');
		if (!for_) return;
		var $label = $(this);
		$(ctx).find('#' + for_).blur(onblur).focus(function() {
			$label.hide();
		});
		onblur();
	});
});
var gformdata;
jQuery.addMutator(function(ctx) {
$('.tabs > ul').tabs();
	var $ctx = $(ctx);
	$ctx.find('.Heading_1:first').children("a").addClass('first');
	$ctx.find('#submenu ul li:first').addClass('first');
	$ctx.find('form.AjaxForm').each(function() {
			var $this = jQuery(this);
			$this.ajaxForm({
				beforeSubmit: function(formData, $form, options) {
					if (!$form.attr('action')) options.url = webslinger.getPath();
					if (options.url != webslinger.url.removeProtocol(options.url)) {
						$form[0].submit();
						return false;
					}
					options.url = webslinger.url.fix(options.url);
					var files = $('input:file', this).fieldValue();
					var found = false;
					for (var j=0; j < files.length; j++)
						if (files[j]) found = true;
					if (!$form.attr('ajaxSuccess') && !found && !options.iframe) {
						options.url = '/AJAX/Load' + options.url;
					} else {
						options.dataType = 'json';
					}
					if (options.type.toUpperCase() == 'GET') {
						var action = options.url;
						//alert('action(' + action + ')');
						loadPath(action + '?' + $.param(formData), true);
						return false;
					}
					formData.unshift({name: 'isJson', value: 'true'});
					return true;
				},
				success: function(data) {
					var ajaxSuccess = $this.attr("ajaxSuccess");
					if (ajaxSuccess == undefined) {
						processAjaxResult('', data);
						//var location = webslinger.getLocation();
						//var fixedHref = webslinger.url.removeProtocol(location.href);
						//loadPath(fixedHref);
					} else {
						gformdata = data;
						$.globalEval(ajaxSuccess);
					}
				}
			});
	});

	$ctx.find(".tablesorter").tablesorter(); 
	$ctx.find("a.LinkReloadPage").click(function() {
		jQuery.get(this.getAttribute("href"), null, function() {
			window.location.reload();
		});
		return false;
	});
	$ctx.find(".PopupExpandableDown").each(function() {
		var $this = $(this);
		var $kids = $this.children();
		var $title = $kids.filter('.PopupExpandableTitle');
		var $pane = $($kids[1]);
		$pane.hide();
		$title.toggle(function() {
			$pane.slideDown(50);
		}, function() {
			$pane.slideUp(50);
		});
	});
	$ctx.find(".gallery").each(function() {
		$(this).mbGallery($(this).metadata());
	});
	$.fn.flashstatus = function(state) {
		return $(this).each(function() {
			var $this = $(this);
			var data = $this.data('flashstatus');
			if (!data) return;
			data.setState(state);
		});
	};
	if (true) $ctx.find('.FlashMovie').each(function() {
		var $this = $(this);
		var data = {
			flashEnable:	function() {
				$this.find('object').each(function() {
					var $this = $(this);
					$(this.parentNode).css({
						visibility:	'',
						height:		$this.css('height'),
						width:		$this.css('width')
					});
				});
			},
			flashDisable:	function() {
				$this.find('object').each(function() {
					$(this.parentNode).css({
						visibility:	'hidden',
						height:		'0px',
						width:		'0px'
					});
				});
			},
			state:		true,
			setState:	function(state) {
				if (data.state == state) return;
				if (state) {
					data.staticDisable();
					data.flashEnable();
				} else {
					data.staticEnable();
					data.flashDisable();
				}
				data.state = state;
			}
		};
		$this.data('flashstatus', data);
	}).filter('.FlashStatic').each(function() {
		var $this = $(this), origChildren = [], ptr = this.firstChild;
		while (ptr != null) {
			if (ptr.style) {
				origChildren.push(ptr);
				ptr.style.display = 'none';
			}
			ptr = ptr.nextSibling;
		}
		$this.flashembed($this.metadata());
		$.each(origChildren, function() {
			$this.append(this);
		});
		var $origChildren = $(origChildren);
		$.extend($this.data('flashstatus'), {
			staticEnable:	function() {
				$origChildren.show();
			},
			staticDisable:	function() {
				$origChildren.hide();
			}
		});
	}).end().not('.FlashStatic').each(function() {
		var $this = $(this);
		$this.flashembed($this.metadata());
		var cleanups = [];
		$.extend($this.data('flashstatus'), {
			staticEnable:	function() {
				var $newElement = $('<div></div>');
				cleanups.push(function() {
					$newElement.remove();
				});
				$newElement.width($this.width());
				$newElement.height($this.height());
				$this.before($newElement);
			},
			staticDisable:	function() {
				$.each(cleanups, function() {
					this();
				});
				cleanups = [];
			}
		});
	});
	$ctx.find('.googlemap').googlemap({
		directionsAction:	'/DrivingDirections'
	});
	$ctx.find('.googlemapdirections').googlemapdirections();
});
(function($) {
	var g = {
		markerShadowImage:	"/Images/mapfiles/shadow50.png",
		markerIconSize:		[20, 34],
		markerShadowSize:	[37, 34],
		markerIconAnchor:	[9, 34],
		markerInfoAnchor:	[9, 2],
		markerImageBase:	"/Images/mapfiles/",

		geoBusyDelay:		500,
		geoBusyMaxAttempt:	10
	};
	var geo = function() {
		var geocoder = new GClientGeocoder();
		geo = function() {
			return geocoder;
		};
		return geocoder;
	};
	var createMarker = function(point, imageName, labels) {
		var base = new GIcon(G_DEFAULT_ICON);
		base.shadow = g.markerShadowImage;
		base.iconSize = new GSize(g.markerIconSize[0], g.markerIconSize[1]);
		base.shadowSize = new GSize(g.markerShadowSize[0], g.markerShadowSize[1]);
		base.iconAnchor = new GPoint(g.markerIconAnchor[0], g.markerIconAnchor[1]);
		base.infoWindowAnchor = new GPoint(g.markerInfoAnchor[0], g.markerInfoAnchor[1]);
		var icon = new GIcon(base);
		icon.image = g.markerImageBase + imageName;
		return labels ? new GMarker(point, {icon: icon, bouncy: true}) : new GMarker(point);
	};
	var controlMap;
	$(window).unload(GUnload);
	controlMap = {
		'large-map-3d':		GLargeMapControl3D,
		'large-map':		GLargeMapControl,
		'small-map':		GSmallMapControl,
		'small-zoom-3d':	GSmallZoomControl3D,
		'small-zoom':		GSmallZoomControl,
		'scale':		GScaleControl,
		'map-type':		GMapTypeControl,
		'h-map-type':		GHierarchicalMapTypeControl,
		'overview-map':		GOverviewMapControl,
		'nav-label':		GNavLabelControl
	};
	var InstallMap = function(o, element, onMapLoaded) {
		var bounds = new GLatLngBounds();
		$(document.body).trigger('ajaxStart');
		var map = new GMap2(element);
		new GKeyboardHandler(map);

		var createPoint = function(i, p) {
			var latch = webslinger.Latch(2, function() {
				//alert('createPoint:latch.point=' + webslinger.toJSON(latch.point));
				var point = new GLatLng(latch.point[1], latch.point[0], true);
				bounds.extend(point);
				var marker = createMarker(point, 'markerA.png', o.labels);
				if (p.description) {
					$(p.description).resize(function() {
						map.updateInfoWindow();
					});
				}
				GEvent.addListener(marker, 'click', function() {
					map.setCenter(marker.getLatLng(), map.getZoom());
					if (p.description) {
						marker.openInfoWindow(p.description);
					}
				});
				map.addOverlay(marker);
				map.setZoom(Math.min(o.maxAutoZoom, map.getBoundsZoomLevel(bounds)));
				map.setCenter(bounds.getCenter());
			});
			$.googlegeo(p.address, function(point) {
				//alert('createPoint:geo.point[' + i + ']=' + webslinger.toJSON(point));
				latch.point = point.coordinates;
				latch();
			});
			return latch;
		};

		var points = [];
		for (var i = 0; i < o.points.length; i++) {
			points[i] = createPoint(i, o.points[i]);
		}
		//alert('points=' + points);

		var setMapData = function() {
			//alert('map loaded, controlMap=' + controlMap);
			try {
			$(document.body).trigger('ajaxStop');
			map.enableContinuousZoom();
			for (var i = 0; i < points.length; i++) {
				points[i]();
			}
			for (var i = 0; i < o.overlays.length; i++) {
				var overlayDef = o.overlays[i];
				var overlayBounds = new GLatLngBounds();
				overlayBounds.extend(new GLatLng(overlayDef.ul[0], overlayDef.ul[1], true));
				overlayBounds.extend(new GLatLng(overlayDef.lr[0], overlayDef.lr[1], true));
				var groundOverlay = new GGroundOverlay(overlayDef.img, overlayBounds);
				map.addOverlay(groundOverlay);
			}
			for (var i = 0; i < o.controls.length; i++) {
				var name = o.controls[i];
				var constructor = controlMap[name];
				if (!constructor) continue;
				map.addControl(new constructor());
			}
			//map.addOverlay(new GTileLayerOverlay(tileLayer));
			} catch (e) {
			alert('map loaded: ' + e);
			}
		};

		var setCenter = function(center) {
			//alert('setCenter:latch.center=' + webslinger.toJSON(center));
			GEvent.addListener(map, 'load', setMapData);
			if (!center) return;
			map.setCenter(new GLatLng(center[1], center[0]), o.defaultZoom);
		};
		if (!o.center) {
			o.center = o.points[0].address;
		}
		switch (typeof o.center) {
			case 'array':
				setCenter(o.center);
				break;
			case 'string':
				$.googlegeo(o.center, function(point) {
					//alert('setCenter:geo.point=' + webslinger.toJSON(point));
					setCenter(point.coordinates);
				});
				break;
			default:
		}
		if (onMapLoaded) onMapLoaded(map);
		return map;
	};
	var parseOverlays = function(o, $this) {
		var overlays = [];
		if (o.overlays) {
			overlays = overlays.concat(o.overlays);
		}
		o.overlays = overlays;
		$this.children('.overlay').each(function() {
			var $this = $(this);
			var position = $this.find('.position').text().replace(/[\r\n\s]/g, '');
			var match = position.match(/^(\d+):\(([-+]?\d+\.\d+),([-+]?\d+\.\d+)\)-\(([-+]?\d+\.\d+),([-+]?\d+\.\d+)\)$/);
			overlays.push({
				zoom:	match[1],
				ul:	[match[2], match[3]],
				lr:	[match[4], match[5]],
				img:	$this.find('img').attr('src')
			});
		}).remove();
	};

	var optionDefaults = {
		controls:	['map-type', 'large-map-3d', 'overview-map'],
		labels:		true,
		defaultZoom:	13,
		maxAutoZoom:	13,
		center:		null,
		overlays:	[],
		points:		null
	};
	var jQueryMethods = {
		base:	{
			googlemapconfig:	function(config) {
				g = $.extend(g, config);
			},
			googlegeo:		function(address, callback) {
				var attemptsLeft = g.geoBusyMaxAttempt;
				if (!callback) callback = function() { };
				var done = function(point) {
					$(document.body).trigger('ajaxStop');
					callback(point);
				};
				var f = function() {
					attemptsLeft--;
					if (attemptsLeft < 0) {
						done(null);
						return;
					}
					geo().getLocations(address, function(response) {
						switch (response.Status.code) {
							case G_GEO_SUCCESS:
								done(response.Placemark[0].Point);
								break;
							case G_GEO_TOO_MANY_QUERIES:
								setTimeout(f, g.geoBusyDelay);
								break;
							default:
						}
					});
				};
				$(document.body).trigger('ajaxStart');
				f();
			}
		},
		fn:	{
			googlemap:		function(o) {
				var $this = this;
				o = $.extend({}, optionDefaults, o);
				if (!o.points) {
					o.points = [];
					$this.find('.mapmarker').each(function() {
						var $this = $(this);
						var point = {
							address:	$this.find('.address').text()
						};
						var $container = $('<div></div>');
						$container.append($this.find('.description'));

						if (o.directionsAction) {
							$container.find('.autodirections').directions(o.directionsAction, point.address);
						}
						$container.applyMutators();
						if ($container.children().length) point.description = $container[0];
						o.points.push(point);
					});
				}
				parseOverlays(o, $this);
				return this.runWhenAttached(function() {
					InstallMap(o, $this[0]);
				});
			},
			googlemapdirections:	function(o) {
				var $this = $(this);
				o = $.extend({}, optionDefaults, o);
				var from = $this.find('input[name="from"]').val();
				var to = $this.find('input[name="to"]').val();
				o.points = [{address: from}, {address: to}];
				var d = $this.find('.directions');
				parseOverlays(o, $this);
				return this.runWhenAttached(function() {
					var map = InstallMap(o, $this.find('.map')[0]);
					var directions = new GDirections(map, d[0]);
					directions.load('from: ' + from + ' to: ' + to);
					GEvent.addListener(directions, 'addoverlay', function() {
						$this.resize();
					});
				});
			}
		}
	};

	if (!($.isFunction(GBrowserIsCompatible) && GBrowserIsCompatible())) {
		var set_doNothing = function() {
			return this;
		}
		var helper_doNothing = function() {
			return;
		}
		for (name in jQueryMethods.base) {
			jQueryMethods.base[name] = helper_doNothing;
		}
		for (name in jQueryMethods.fn) {
			jQueryMethods.fn[name] = set_doNothing;
		}
	}
	$.fn.extend(jQueryMethods.fn);
	$.extend(jQueryMethods.base);
})(jQuery);
/* =========================================================

// jquery.innerfade.js

// Datum: 2007-01-29
// Firma: Medienfreunde Hofmann & Baldes GbR
// Autor: Torsten Baldes
// Mail: t.baldes@medienfreunde.com
// Web: http://medienfreunde.com

// based on the work of Matt Oakes http://portfolio.gizone.co.uk/applications/slideshow/

// ========================================================= */


(function($) {

$.fn.innerfade = function(options) {

	this.each(function(){ 	
		
		var settings = {
			animationtype: 'fade',
			speed: 'normal',
			timeout: 2000,
			type: 'sequence',
			containerheight: 'auto',
			runningclass: 'innerfade'
		};
		
		if(options)
			$.extend(settings, options);
		
		var elements = $(this).children();
	
		if (elements.length > 1) {
		
			$(this).css('position', 'relative');
	
			$(this).css('height', settings.containerheight);
			$(this).addClass(settings.runningclass);
			
			for ( var i = 0; i < elements.length; i++ ) {
				$(elements[i]).css('z-index', String(elements.length-i)).css('position', 'absolute');
				$(elements[i]).hide();
			};
		
			if ( settings.type == 'sequence' ) {
				setTimeout(function(){
					$.innerfade.next(elements, settings, 1, 0);
				}, settings.timeout);
				$(elements[0]).show();
			} else if ( settings.type == 'random' ) {
				setTimeout(function(){
					do { current = Math.floor ( Math.random ( ) * ( elements.length ) ); } while ( current == 0 )
					$.innerfade.next(elements, settings, current, 0);
				}, settings.timeout);
				$(elements[0]).show();
			}	else {
				alert('type must either be \'sequence\' or \'random\'');
			}
			
		}
		
	});
};


$.innerfade = function() {}
$.innerfade.next = function (elements, settings, current, last) {

	if ( settings.animationtype == 'slide' ) {
		$(elements[last]).slideUp(settings.speed, $(elements[current]).slideDown(settings.speed));
	} else if ( settings.animationtype == 'fade' ) {
		$(elements[last]).fadeOut(settings.speed);
		$(elements[current]).fadeIn(settings.speed);
	} else {
		alert('animationtype must either be \'slide\' or \'fade\'');
	};
	
	if ( settings.type == 'sequence' ) {
		if ( ( current + 1 ) < elements.length ) {
			current = current + 1;
			last = current - 1;
		} else {
			current = 0;
			last = elements.length - 1;
		};
	}	else if ( settings.type == 'random' ) {
		last = current;
		while (	current == last ) {
			current = Math.floor ( Math.random ( ) * ( elements.length ) );
		};
	}	else {
		alert('type must either be \'sequence\' or \'random\'');
	};
	setTimeout((function(){$.innerfade.next(elements, settings, current, last);}), settings.timeout);
};
})(jQuery);
(function() {
 function isCommandKey(code) {
  if (code > 63232) {
   // safari keypress
   switch (code) {
    case 63232: //
    case 63233: //
    case 63234: //
    case 63235: //
     // FIXME:
    code -= 63232 + 38; break;
    case 63236: // F1
    case 63237: // F2
    case 63238: // F3
    case 63239: // F4
    case 63240: // F5
    case 63241: // F6
    case 63242: // F7
    case 63243: // F8
    case 63244: // F9
    case 63245: // F10
    case 63246: // F11
    case 63247: // F12
     code = code - 63236 + 112; break;
    case 63272: // delete
     code = 46; break;
    case 63273: // home 
     code = 36;
    case 63275: // end
     code = 35; break;
    case 63276: // page up
     code = 33; break;
    case 63277: // page down
     code = 34; break;
    case 63289: // numlock
     code = 144; break;
   }
  }
  // FIXME: help key on mac
  switch (code) {
   case 8:   // backspace
   case 9:   // tab
   case 13:  // enter
   case 16:  // shift
   case 17:  // ctrl/cmd
   case 18:  // alt
   case 19:  // break
   case 20:  // caps lock
   case 27:  // escape
   case 33:  // page up
   case 34:  // page down
   case 35:  // end
   case 36:  // home
   case 37:  // left
   case 38:  // up
   case 39:  // right
   case 40:  // down
   case 44:  // print screen
   case 45:  // insert
   case 46:  // delete
   case 91:  // windows start key
   case 106: // numpad *
   case 107: // numpad +
   case 109: // numpad -
   case 111: // numpad /
   case 112: // F1
   case 113: // F2
   case 114: // F3
   case 115: // F4
   case 116: // F5
   case 117: // F6
   case 118: // F7
   case 119: // F8
   case 120: // F9
   case 121: // F10
   case 122: // F11
   case 123: // F12
   case 144: // numlock
   case 145: // scrolllock
    return true;
  }
  return false;
 }
 jQuery.fn.formTextLimiter = function(callback) {
  this.each(function() {
   var maxLengthValue = this.getAttribute("maxlength");
   if (!maxLengthValue) return;
   var maxLength = parseInt(maxLengthValue);
   var eThis = this;
   var jThis = jQuery(this);
   //if (jThis.next("span.textcounter").length != 0) return;
   if (callback) callback(maxLength, maxLength - this.value.length, eThis);
   jThis.keypress(function(e) {
    if (isCommandKey(e.keyCode)) return true;
    var curLength = maxLength - eThis.value.length;
    if (curLength <= 0) {
     return false;
    } else {
     if (callback) callback(maxLength, curLength, eThis);
     return true;
    }
   }).keyup(function(e) {
    var curLength = maxLength - eThis.value.length;
    if (callback) callback(maxLength, curLength, eThis);
    return true;
   }).keydown(function(e) {
    var keyCode = e.keyCode
    if (isCommandKey(e.keyCode)) return true;
    return maxLength > eThis.value.length;
   });
  });
 };
})();
(function($) {
var nameLinkObject;
var showObject;
var indx = -1;
var timerID;
function sendMovieSignal(movieName, funcName) {
	var movie;
	if (navigator.appName.indexOf("Microsoft") != -1) {
		movie = window[movieName];
	} else {
		movie = document[movieName];
	}
	if (movie === null) {
		return;
	}
	var args = $.makeArray(arguments);
	args.shift();
	args.shift();
	try {
		movie[funcName].apply(movie, args);
	} catch (e) {
		//alert('sendMovieSignal(' + movieName + ', ' + funcName + ')');
	}

}
function showMenu (nameObject, animationIndex) {
	var obj = nameObject.getElementsByTagName("div")[0];
	if (obj !== undefined) {
		if (typeof(showObject) != "undefined") {
			if (showObject != obj) {
				$(showObject).slideUp();
			}
		}
		showObject = obj;
		$(obj).slideDown();
	}
	if (typeof(timerID) != "undefined") {
		clearTimeout(timerID);
	}
	if (animationIndex != indx) {
		sendMovieSignal('headerflash', 'headOut');
		timerID = setTimeout(function() {
			indx = animationIndex;
			sendMovieSignal("headerflash", 'headOver', animationIndex);
		}, 1000);
	}
}
function hideMenu (nameObject) {
	var obj = nameObject.getElementsByTagName("div")[0];
	if (typeof(timerID) != "undefined") {
		clearTimeout(timerID);
	}
	if (obj !== undefined) {
		timerID = setTimeout(function() {
			$(showObject).slideUp();
			sendMovieSignal('headerflash', 'headOut');
			indx = -1;
		}, 500);
	} else {
		timerID = setTimeout(function() {
			sendMovieSignal('headerflash', 'headOut');
			indx = -1;
		}, 500);
	}
}
function clearValue(obj, sVal) {
	if (obj.value == sVal) {
		obj.value = "";
	}
}
function fillValue(obj, sVal) {
	if (obj.value === "") {
		obj.value = sVal;
	}
}
function showLeftMenu (nameObject) {
	var obj = nameObject.getElementsByTagName("ul")[0];
	var objA = nameObject.getElementsByTagName("a")[0];
	if (obj.style.display != "block") {
		obj.style.display = "block";
		objA.className = "minus";
	} else {
		obj.style.display = "none";
		objA.className = "plus";
	}
}
	var indexMap = {
		work:		1,
		services:	3,
		company:	0,
		blog:		2
	};
	$.addMutator(function(ctx) {
		$(ctx).find('ul:first').each(function() {
			if ($(this).closest('#menu-header').length === 0) {
				return;
			}
			$(this).children('li').each(function() {
				var $this = $(this);
				var animationIndex = indexMap[$this.attr('class')];
				$this.hover(function() {
					showMenu(this, animationIndex);
				}, function() {
					hideMenu(this);
				});
			});
		});

	});
})(jQuery);

