1 var nodeHook, boolHook, fixSpecified,
4 rtype = /^(?:button|input)$/i,
5 rfocusable = /^(?:button|input|object|select|textarea)$/i,
6 rclickable = /^a(?:rea|)$/i,
7 rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
8 getSetAttribute = jQuery.support.getSetAttribute;
11 attr: function( name, value ) {
12 return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
15 removeAttr: function( name ) {
16 return this.each(function() {
17 jQuery.removeAttr( this, name );
21 prop: function( name, value ) {
22 return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
25 removeProp: function( name ) {
26 name = jQuery.propFix[ name ] || name;
27 return this.each(function() {
28 // try/catch handles cases where IE balks (such as removing a property on window)
30 this[ name ] = undefined;
36 addClass: function( value ) {
37 var classNames, i, l, elem,
40 if ( jQuery.isFunction( value ) ) {
41 return this.each(function( j ) {
42 jQuery( this ).addClass( value.call(this, j, this.className) );
46 if ( value && typeof value === "string" ) {
47 classNames = value.split( core_rspace );
49 for ( i = 0, l = this.length; i < l; i++ ) {
52 if ( elem.nodeType === 1 ) {
53 if ( !elem.className && classNames.length === 1 ) {
54 elem.className = value;
57 setClass = " " + elem.className + " ";
59 for ( c = 0, cl = classNames.length; c < cl; c++ ) {
60 if ( setClass.indexOf( " " + classNames[ c ] + " " ) < 0 ) {
61 setClass += classNames[ c ] + " ";
64 elem.className = jQuery.trim( setClass );
73 removeClass: function( value ) {
74 var removes, className, elem, c, cl, i, l;
76 if ( jQuery.isFunction( value ) ) {
77 return this.each(function( j ) {
78 jQuery( this ).removeClass( value.call(this, j, this.className) );
81 if ( (value && typeof value === "string") || !arguments.length ) {
82 removes = ( value || "" ).split( core_rspace );
84 for ( i = 0, l = this.length; i < l; i++ ) {
86 if ( elem.nodeType === 1 && elem.className ) {
88 className = (" " + elem.className + " ").replace( rclass, " " );
90 // loop over each item in the removal list
91 for ( c = 0, cl = removes.length; c < cl; c++ ) {
92 // Remove until there is nothing to remove,
93 while ( className.indexOf(" " + removes[ c ] + " ") >= 0 ) {
94 className = className.replace( " " + removes[ c ] + " " , " " );
97 elem.className = value ? jQuery.trim( className ) : "";
105 toggleClass: function( value, stateVal ) {
106 var type = typeof value,
107 isBool = typeof stateVal === "boolean";
109 if ( jQuery.isFunction( value ) ) {
110 return this.each(function( i ) {
111 jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
115 return this.each(function() {
116 if ( type === "string" ) {
117 // toggle individual class names
120 self = jQuery( this ),
122 classNames = value.split( core_rspace );
124 while ( (className = classNames[ i++ ]) ) {
125 // check each className given, space separated list
126 state = isBool ? state : !self.hasClass( className );
127 self[ state ? "addClass" : "removeClass" ]( className );
130 } else if ( type === "undefined" || type === "boolean" ) {
131 if ( this.className ) {
132 // store className if set
133 jQuery._data( this, "__className__", this.className );
136 // toggle whole className
137 this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
142 hasClass: function( selector ) {
143 var className = " " + selector + " ",
146 for ( ; i < l; i++ ) {
147 if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
155 val: function( value ) {
156 var hooks, ret, isFunction,
159 if ( !arguments.length ) {
161 hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
163 if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
169 return typeof ret === "string" ?
170 // handle most common string cases
171 ret.replace(rreturn, "") :
172 // handle cases where value is null/undef or number
173 ret == null ? "" : ret;
179 isFunction = jQuery.isFunction( value );
181 return this.each(function( i ) {
185 if ( this.nodeType !== 1 ) {
190 val = value.call( this, i, self.val() );
195 // Treat null/undefined as ""; convert numbers to string
198 } else if ( typeof val === "number" ) {
200 } else if ( jQuery.isArray( val ) ) {
201 val = jQuery.map(val, function ( value ) {
202 return value == null ? "" : value + "";
206 hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
208 // If set returns undefined, fall back to normal setting
209 if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
219 get: function( elem ) {
220 // attributes.value is undefined in Blackberry 4.7 but
221 // uses .value. See #6932
222 var val = elem.attributes.value;
223 return !val || val.specified ? elem.value : elem.text;
227 get: function( elem ) {
229 options = elem.options,
230 index = elem.selectedIndex,
231 one = elem.type === "select-one" || index < 0,
232 values = one ? null : [],
233 max = one ? index + 1 : options.length,
238 // Loop through all the selected options
239 for ( ; i < max; i++ ) {
240 option = options[ i ];
242 // oldIE doesn't update selected after form reset (#2551)
243 if ( ( option.selected || i === index ) &&
244 // Don't return options that are disabled or in a disabled optgroup
245 ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
246 ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
248 // Get the specific value for the option
249 value = jQuery( option ).val();
251 // We don't need an array for one selects
256 // Multi-Selects return an array
257 values.push( value );
264 set: function( elem, value ) {
265 var values = jQuery.makeArray( value );
267 jQuery(elem).find("option").each(function() {
268 this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
271 if ( !values.length ) {
272 elem.selectedIndex = -1;
279 attr: function( elem, name, value, pass ) {
280 var ret, hooks, notxml,
281 nType = elem.nodeType;
283 // don't get/set attributes on text, comment and attribute nodes
284 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
288 if ( pass && jQuery.isFunction( jQuery.fn[ name ] ) ) {
289 return jQuery( elem )[ name ]( value );
292 // Fallback to prop when attributes are not supported
293 if ( typeof elem.getAttribute === "undefined" ) {
294 return jQuery.prop( elem, name, value );
297 notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
299 // All attributes are lowercase
300 // Grab necessary hook if one is defined
302 name = name.toLowerCase();
303 hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
306 if ( value !== undefined ) {
308 if ( value === null ) {
309 jQuery.removeAttr( elem, name );
312 } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
316 elem.setAttribute( name, value + "" );
320 } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
325 ret = elem.getAttribute( name );
327 // Non-existent attributes return null, we normalize to undefined
328 return ret === null ?
334 removeAttr: function( elem, value ) {
335 var propName, attrNames, name, isBool,
338 if ( value && elem.nodeType === 1 ) {
340 attrNames = value.split( core_rspace );
342 for ( ; i < attrNames.length; i++ ) {
343 name = attrNames[ i ];
346 propName = jQuery.propFix[ name ] || name;
347 isBool = rboolean.test( name );
349 // See #9699 for explanation of this approach (setting first, then removal)
350 // Do not do this for boolean attributes (see #10870)
352 jQuery.attr( elem, name, "" );
354 elem.removeAttribute( getSetAttribute ? name : propName );
356 // Set corresponding property to false for boolean attributes
357 if ( isBool && propName in elem ) {
358 elem[ propName ] = false;
367 set: function( elem, value ) {
368 // We can't allow the type property to be changed (since it causes problems in IE)
369 if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
370 jQuery.error( "type property can't be changed" );
371 } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
372 // Setting the type on a radio button after the value resets the value in IE6-9
373 // Reset value to it's default in case type is set after value
374 // This is for element creation
375 var val = elem.value;
376 elem.setAttribute( "type", value );
384 // Use the value property for back compat
385 // Use the nodeHook for button elements in IE6/7 (#1954)
387 get: function( elem, name ) {
388 if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
389 return nodeHook.get( elem, name );
391 return name in elem ?
395 set: function( elem, value, name ) {
396 if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
397 return nodeHook.set( elem, value, name );
399 // Does not return so that setAttribute is also used
406 tabindex: "tabIndex",
407 readonly: "readOnly",
409 "class": "className",
410 maxlength: "maxLength",
411 cellspacing: "cellSpacing",
412 cellpadding: "cellPadding",
416 frameborder: "frameBorder",
417 contenteditable: "contentEditable"
420 prop: function( elem, name, value ) {
421 var ret, hooks, notxml,
422 nType = elem.nodeType;
424 // don't get/set properties on text, comment and attribute nodes
425 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
429 notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
432 // Fix name and attach hooks
433 name = jQuery.propFix[ name ] || name;
434 hooks = jQuery.propHooks[ name ];
437 if ( value !== undefined ) {
438 if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
442 return ( elem[ name ] = value );
446 if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
457 get: function( elem ) {
458 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
459 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
460 var attributeNode = elem.getAttributeNode("tabindex");
462 return attributeNode && attributeNode.specified ?
463 parseInt( attributeNode.value, 10 ) :
464 rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
472 // Hook for boolean attributes
474 get: function( elem, name ) {
475 // Align boolean attributes with corresponding properties
476 // Fall back to attribute presence where some booleans are not supported
478 property = jQuery.prop( elem, name );
479 return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
483 set: function( elem, value, name ) {
485 if ( value === false ) {
486 // Remove boolean attributes when set to false
487 jQuery.removeAttr( elem, name );
489 // value is true since we know at this point it's type boolean and not false
490 // Set boolean attributes to the same name and set the DOM property
491 propName = jQuery.propFix[ name ] || name;
492 if ( propName in elem ) {
493 // Only set the IDL specifically if it already exists on the element
494 elem[ propName ] = true;
497 elem.setAttribute( name, name.toLowerCase() );
503 // IE6/7 do not support getting/setting some attributes with get/setAttribute
504 if ( !getSetAttribute ) {
512 // Use this for any attribute in IE6/7
513 // This fixes almost every IE6/7 issue
514 nodeHook = jQuery.valHooks.button = {
515 get: function( elem, name ) {
517 ret = elem.getAttributeNode( name );
518 return ret && ( fixSpecified[ name ] ? ret.value !== "" : ret.specified ) ?
522 set: function( elem, value, name ) {
523 // Set the existing or create a new attribute node
524 var ret = elem.getAttributeNode( name );
526 ret = elem.ownerDocument.createAttribute( name );
527 elem.setAttributeNode( ret );
529 return ( ret.value = value + "" );
533 // Set width and height to auto instead of 0 on empty string( Bug #8150 )
534 // This is for removals
535 jQuery.each([ "width", "height" ], function( i, name ) {
536 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
537 set: function( elem, value ) {
538 if ( value === "" ) {
539 elem.setAttribute( name, "auto" );
546 // Set contenteditable to false on removals(#10429)
547 // Setting to empty string throws an error as an invalid value
548 jQuery.attrHooks.contenteditable = {
550 set: function( elem, value, name ) {
551 if ( value === "" ) {
554 nodeHook.set( elem, value, name );
560 // Some attributes require a special call on IE
561 if ( !jQuery.support.hrefNormalized ) {
562 jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
563 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
564 get: function( elem ) {
565 var ret = elem.getAttribute( name, 2 );
566 return ret === null ? undefined : ret;
572 if ( !jQuery.support.style ) {
573 jQuery.attrHooks.style = {
574 get: function( elem ) {
575 // Return undefined in the case of empty string
576 // Normalize to lowercase since IE uppercases css property names
577 return elem.style.cssText.toLowerCase() || undefined;
579 set: function( elem, value ) {
580 return ( elem.style.cssText = value + "" );
585 // Safari mis-reports the default selected property of an option
586 // Accessing the parent's selectedIndex property fixes it
587 if ( !jQuery.support.optSelected ) {
588 jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
589 get: function( elem ) {
590 var parent = elem.parentNode;
593 parent.selectedIndex;
595 // Make sure that it also works with optgroups, see #5701
596 if ( parent.parentNode ) {
597 parent.parentNode.selectedIndex;
605 // IE6/7 call enctype encoding
606 if ( !jQuery.support.enctype ) {
607 jQuery.propFix.enctype = "encoding";
610 // Radios and checkboxes getter/setter
611 if ( !jQuery.support.checkOn ) {
612 jQuery.each([ "radio", "checkbox" ], function() {
613 jQuery.valHooks[ this ] = {
614 get: function( elem ) {
615 // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
616 return elem.getAttribute("value") === null ? "on" : elem.value;
621 jQuery.each([ "radio", "checkbox" ], function() {
622 jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
623 set: function( elem, value ) {
624 if ( jQuery.isArray( value ) ) {
625 return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );