text: (function( jQuery ) {
  
  var rclass = /[\n\t\r]/g,
  	rspace = /\s+/,
  	rreturn = /\r/g,
  	rtype = /^(?:button|input)$/i,
  	rfocusable = /^(?:button|input|object|select|textarea)$/i,
  	rclickable = /^a(?:rea)?$/i,
  	rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
  	getSetAttribute = jQuery.support.getSetAttribute,
  	nodeHook, boolHook, fixSpecified;
  
  jQuery.fn.extend({
  	attr: function( name, value ) {
  		return jQuery.access( this, name, value, true, jQuery.attr );
  	},
  
  	removeAttr: function( name ) {
  		return this.each(function() {
  			jQuery.removeAttr( this, name );
  		});
  	},
  
  	prop: function( name, value ) {
  		return jQuery.access( this, name, value, true, jQuery.prop );
  	},
  
  	removeProp: function( name ) {
  		name = jQuery.propFix[ name ] || name;
  		return this.each(function() {
  			// try/catch handles cases where IE balks (such as removing a property on window)
  			try {
  				this[ name ] = undefined;
  				delete this[ name ];
  			} catch( e ) {}
  		});
  	},
  
  	addClass: function( value ) {
  		var classNames, i, l, elem,
  			setClass, c, cl;
  
  		if ( jQuery.isFunction( value ) ) {
  			return this.each(function( j ) {
  				jQuery( this ).addClass( value.call(this, j, this.className) );
  			});
  		}
  
  		if ( value && typeof value === "string" ) {
  			classNames = value.split( rspace );
  
  			for ( i = 0, l = this.length; i < l; i++ ) {
  				elem = this[ i ];
  
  				if ( elem.nodeType === 1 ) {
  					if ( !elem.className && classNames.length === 1 ) {
  						elem.className = value;
  
  					} else {
  						setClass = " " + elem.className + " ";
  
  						for ( c = 0, cl = classNames.length; c < cl; c++ ) {
  							if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) {
  								setClass += classNames[ c ] + " ";
  							}
  						}
  						elem.className = jQuery.trim( setClass );
  					}
  				}
  			}
  		}
  
  		return this;
  	},
  
  	removeClass: function( value ) {
  		var classNames, i, l, elem, className, c, cl;
  
  		if ( jQuery.isFunction( value ) ) {
  			return this.each(function( j ) {
  				jQuery( this ).removeClass( value.call(this, j, this.className) );
  			});
  		}
  
  		if ( (value && typeof value === "string") || value === undefined ) {
  			classNames = (value || "").split( rspace );
  
  			for ( i = 0, l = this.length; i < l; i++ ) {
  				elem = this[ i ];
  
  				if ( elem.nodeType === 1 && elem.className ) {
  					if ( value ) {
  						className = (" " + elem.className + " ").replace( rclass, " " );
  						for ( c = 0, cl = classNames.length; c < cl; c++ ) {
  							className = className.replace(" " + classNames[ c ] + " ", " ");
  						}
  						elem.className = jQuery.trim( className );
  
  					} else {
  						elem.className = "";
  					}
  				}
  			}
  		}
  
  		return this;
  	},
  
  	toggleClass: function( value, stateVal ) {
  		var type = typeof value,
  			isBool = typeof stateVal === "boolean";
  
  		if ( jQuery.isFunction( value ) ) {
  			return this.each(function( i ) {
  				jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
  			});
  		}
  
  		return this.each(function() {
  			if ( type === "string" ) {
  				// toggle individual class names
  				var className,
  					i = 0,
  					self = jQuery( this ),
  					state = stateVal,
  					classNames = value.split( rspace );
  
  				while ( (className = classNames[ i++ ]) ) {
  					// check each className given, space seperated list
  					state = isBool ? state : !self.hasClass( className );
  					self[ state ? "addClass" : "removeClass" ]( className );
  				}
  
  			} else if ( type === "undefined" || type === "boolean" ) {
  				if ( this.className ) {
  					// store className if set
  					jQuery._data( this, "__className__", this.className );
  				}
  
  				// toggle whole className
  				this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
  			}
  		});
  	},
  
  	hasClass: function( selector ) {
  		var className = " " + selector + " ",
  			i = 0,
  			l = this.length;
  		for ( ; i < l; i++ ) {
  			if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
  				return true;
  			}
  		}
  
  		return false;
  	},
  
  	val: function( value ) {
  		var hooks, ret, isFunction,
  			elem = this[0];
  
  		if ( !arguments.length ) {
  			if ( elem ) {
  				hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ];
  
  				if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
  					return ret;
  				}
  
  				ret = elem.value;
  
  				return typeof ret === "string" ?
  					// handle most common string cases
  					ret.replace(rreturn, "") :
  					// handle cases where value is null/undef or number
  					ret == null ? "" : ret;
  			}
  
  			return undefined;
  		}
  
  		isFunction = jQuery.isFunction( value );
  
  		return this.each(function( i ) {
  			var self = jQuery(this), val;
  
  			if ( this.nodeType !== 1 ) {
  				return;
  			}
  
  			if ( isFunction ) {
  				val = value.call( this, i, self.val() );
  			} else {
  				val = value;
  			}
  
  			// Treat null/undefined as ""; convert numbers to string
  			if ( val == null ) {
  				val = "";
  			} else if ( typeof val === "number" ) {
  				val += "";
  			} else if ( jQuery.isArray( val ) ) {
  				val = jQuery.map(val, function ( value ) {
  					return value == null ? "" : value + "";
  				});
  			}
  
  			hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];
  
  			// If set returns undefined, fall back to normal setting
  			if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
  				this.value = val;
  			}
  		});
  	}
  });
  
  jQuery.extend({
  	valHooks: {
  		option: {
  			get: function( elem ) {
  				// attributes.value is undefined in Blackberry 4.7 but
  				// uses .value. See #6932
  				var val = elem.attributes.value;
  				return !val || val.specified ? elem.value : elem.text;
  			}
  		},
  		select: {
  			get: function( elem ) {
  				var value, i, max, option,
  					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
  				i = one ? index : 0;
  				max = one ? index + 1 : options.length;
  				for ( ; i < max; i++ ) {
  					option = options[ i ];
  
  					// Don't return options that are disabled or in a disabled optgroup
  					if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
  							(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
  
  						// Get the specific 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 );
  					}
  				}
  
  				// Fixes Bug #2551 -- select.val() broken in IE after form.reset()
  				if ( one && !values.length && options.length ) {
  					return jQuery( options[ index ] ).val();
  				}
  
  				return values;
  			},
  
  			set: function( elem, value ) {
  				var values = jQuery.makeArray( value );
  
  				jQuery(elem).find("option").each(function() {
  					this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
  				});
  
  				if ( !values.length ) {
  					elem.selectedIndex = -1;
  				}
  				return values;
  			}
  		}
  	},
  
  	attrFn: {
  		val: true,
  		css: true,
  		html: true,
  		text: true,
  		data: true,
  		width: true,
  		height: true,
  		offset: true
  	},
  
  	attr: function( elem, name, value, pass ) {
  		var ret, hooks, notxml,
  			nType = elem.nodeType;
  
  		// don't get/set attributes on text, comment and attribute nodes
  		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
  			return undefined;
  		}
  
  		if ( pass && name in jQuery.attrFn ) {
  			return jQuery( elem )[ name ]( value );
  		}
  
  		// Fallback to prop when attributes are not supported
  		if ( !("getAttribute" in elem) ) {
  			return jQuery.prop( elem, name, value );
  		}
  
  		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
  
  		// All attributes are lowercase
  		// Grab necessary hook if one is defined
  		if ( notxml ) {
  			name = name.toLowerCase();
  			hooks = jQuery.attrHooks[ name ] || (rboolean.test( name ) ? boolHook : nodeHook);
  		}
  
  		if ( value !== undefined ) {
  
  			if ( value === null ) {
  				jQuery.removeAttr( elem, name );
  				return undefined;
  
  			} else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
  				return ret;
  
  			} else {
  				elem.setAttribute( name, "" + value );
  				return value;
  			}
  
  		} else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
  			return ret;
  
  		} else {
  
  			ret = elem.getAttribute( name );
  
  			// Non-existent attributes return null, we normalize to undefined
  			return ret === null ?
  				undefined :
  				ret;
  		}
  	},
  
  	removeAttr: function( elem, value ) {
  		var propName, attrNames, name, l,
  			i = 0;
  
  		if ( elem.nodeType === 1 ) {
  			attrNames = (value || "").split( rspace );
  			l = attrNames.length;
  
  			for ( ; i < l; i++ ) {
  				name = attrNames[ i ].toLowerCase();
  				propName = jQuery.propFix[ name ] || name;
  
  				// See #9699 for explanation of this approach (setting first, then removal)
  				jQuery.attr( elem, name, "" );
  				elem.removeAttribute( getSetAttribute ? name : propName );
  
  				// Set corresponding property to false for boolean attributes
  				if ( rboolean.test( name ) && propName in elem ) {
  					elem[ propName ] = false;
  				}
  			}
  		}
  	},
  
  	attrHooks: {
  		type: {
  			set: function( elem, value ) {
  				// We can't allow the type property to be changed (since it causes problems in IE)
  				if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
  					jQuery.error( "type property can't be changed" );
  				} else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
  					// Setting the type on a radio button after the value resets the value in IE6-9
  					// Reset value to it's default in case type is set after value
  					// This is for element creation
  					var val = elem.value;
  					elem.setAttribute( "type", value );
  					if ( val ) {
  						elem.value = val;
  					}
  					return value;
  				}
  			}
  		},
  		// Use the value property for back compat
  		// Use the nodeHook for button elements in IE6/7 (#1954)
  		value: {
  			get: function( elem, name ) {
  				if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
  					return nodeHook.get( elem, name );
  				}
  				return name in elem ?
  					elem.value :
  					null;
  			},
  			set: function( elem, value, name ) {
  				if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
  					return nodeHook.set( elem, value, name );
  				}
  				// Does not return so that setAttribute is also used
  				elem.value = value;
  			}
  		}
  	},
  
  	propFix: {
  		tabindex: "tabIndex",
  		readonly: "readOnly",
  		"for": "htmlFor",
  		"class": "className",
  		maxlength: "maxLength",
  		cellspacing: "cellSpacing",
  		cellpadding: "cellPadding",
  		rowspan: "rowSpan",
  		colspan: "colSpan",
  		usemap: "useMap",
  		frameborder: "frameBorder",
  		contenteditable: "contentEditable"
  	},
  
  	prop: function( elem, name, value ) {
  		var ret, hooks, notxml,
  			nType = elem.nodeType;
  
  		// don't get/set properties on text, comment and attribute nodes
  		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
  			return undefined;
  		}
  
  		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
  
  		if ( notxml ) {
  			// Fix name and attach hooks
  			name = jQuery.propFix[ name ] || name;
  			hooks = jQuery.propHooks[ name ];
  		}
  
  		if ( value !== undefined ) {
  			if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
  				return ret;
  
  			} else {
  				return (elem[ name ] = value);
  			}
  
  		} else {
  			if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
  				return ret;
  
  			} else {
  				return elem[ name ];
  			}
  		}
  	},
  
  	propHooks: {
  		tabIndex: {
  			get: function( elem ) {
  				// 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/
  				var attributeNode = elem.getAttributeNode("tabindex");
  
  				return attributeNode && attributeNode.specified ?
  					parseInt( attributeNode.value, 10 ) :
  					rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
  						0 :
  						undefined;
  			}
  		}
  	}
  });
  
  // Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)
  jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;
  
  // Hook for boolean attributes
  boolHook = {
  	get: function( elem, name ) {
  		// Align boolean attributes with corresponding properties
  		// Fall back to attribute presence where some booleans are not supported
  		var attrNode,
  			property = jQuery.prop( elem, name );
  		return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
  			name.toLowerCase() :
  			undefined;
  	},
  	set: function( elem, value, name ) {
  		var propName;
  		if ( value === false ) {
  			// Remove boolean attributes when set to false
  			jQuery.removeAttr( elem, name );
  		} else {
  			// value is true since we know at this point it's type boolean and not false
  			// Set boolean attributes to the same name and set the DOM property
  			propName = jQuery.propFix[ name ] || name;
  			if ( propName in elem ) {
  				// Only set the IDL specifically if it already exists on the element
  				elem[ propName ] = true;
  			}
  
  			elem.setAttribute( name, name.toLowerCase() );
  		}
  		return name;
  	}
  };
  
  // IE6/7 do not support getting/setting some attributes with get/setAttribute
  if ( !getSetAttribute ) {
  
  	fixSpecified = {
  		name: true,
  		id: true
  	};
  
  	// Use this for any attribute in IE6/7
  	// This fixes almost every IE6/7 issue
  	nodeHook = jQuery.valHooks.button = {
  		get: function( elem, name ) {
  			var ret;
  			ret = elem.getAttributeNode( name );
  			return ret && (fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified) ?
  				ret.nodeValue :
  				undefined;
  		},
  		set: function( elem, value, name ) {
  			// Set the existing or create a new attribute node
  			var ret = elem.getAttributeNode( name );
  			if ( !ret ) {
  				ret = document.createAttribute( name );
  				elem.setAttributeNode( ret );
  			}
  			return (ret.nodeValue = value + "");
  		}
  	};
  
  	// Apply the nodeHook to tabindex
  	jQuery.attrHooks.tabindex.set = nodeHook.set;
  
  	// Set width and height to auto instead of 0 on empty string( Bug #8150 )
  	// This is for removals
  	jQuery.each([ "width", "height" ], function( i, name ) {
  		jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
  			set: function( elem, value ) {
  				if ( value === "" ) {
  					elem.setAttribute( name, "auto" );
  					return value;
  				}
  			}
  		});
  	});
  
  	// Set contenteditable to false on removals(#10429)
  	// Setting to empty string throws an error as an invalid value
  	jQuery.attrHooks.contenteditable = {
  		get: nodeHook.get,
  		set: function( elem, value, name ) {
  			if ( value === "" ) {
  				value = "false";
  			}
  			nodeHook.set( elem, value, name );
  		}
  	};
  }
  
  
  // Some attributes require a special call on IE
  if ( !jQuery.support.hrefNormalized ) {
  	jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
  		jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
  			get: function( elem ) {
  				var ret = elem.getAttribute( name, 2 );
  				return ret === null ? undefined : ret;
  			}
  		});
  	});
  }
  
  if ( !jQuery.support.style ) {
  	jQuery.attrHooks.style = {
  		get: function( elem ) {
  			// Return undefined in the case of empty string
  			// Normalize to lowercase since IE uppercases css property names
  			return elem.style.cssText.toLowerCase() || undefined;
  		},
  		set: function( elem, value ) {
  			return (elem.style.cssText = "" + value);
  		}
  	};
  }
  
  // Safari mis-reports the default selected property of an option
  // Accessing the parent's selectedIndex property fixes it
  if ( !jQuery.support.optSelected ) {
  	jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
  		get: function( elem ) {
  			var parent = elem.parentNode;
  
  			if ( parent ) {
  				parent.selectedIndex;
  
  				// Make sure that it also works with optgroups, see #5701
  				if ( parent.parentNode ) {
  					parent.parentNode.selectedIndex;
  				}
  			}
  			return null;
  		}
  	});
  }
  
  // IE6/7 call enctype encoding
  if ( !jQuery.support.enctype ) {
  	jQuery.propFix.enctype = "encoding";
  }
  
  // Radios and checkboxes getter/setter
  if ( !jQuery.support.checkOn ) {
  	jQuery.each([ "radio", "checkbox" ], function() {
  		jQuery.valHooks[ this ] = {
  			get: function( elem ) {
  				// Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
  				return elem.getAttribute("value") === null ? "on" : elem.value;
  			}
  		};
  	});
  }
  jQuery.each([ "radio", "checkbox" ], function() {
  	jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
  		set: function( elem, value ) {
  			if ( jQuery.isArray( value ) ) {
  				return (elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0);
  			}
  		}
  	});
  });
  
  })( jQuery );
  
  