3 var rclass = /[\n\t\r]/g,
6 rtype = /^(?:button|input)$/i,
7 rfocusable = /^(?:button|input|object|select|textarea)$/i,
8 rclickable = /^a(?:rea)?$/i,
9 rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
13 attr: function( name, value ) {
14 return jQuery.access( this, name, value, true, jQuery.attr );
17 removeAttr: function( name ) {
18 return this.each(function() {
19 jQuery.removeAttr( this, name );
23 prop: function( name, value ) {
24 return jQuery.access( this, name, value, true, jQuery.prop );
27 removeProp: function( name ) {
28 name = jQuery.propFix[ name ] || name;
29 return this.each(function() {
30 // try/catch handles cases where IE balks (such as removing a property on window)
32 this[ name ] = undefined;
38 addClass: function( value ) {
39 var classNames, i, l, elem,
42 if ( jQuery.isFunction( value ) ) {
43 return this.each(function( j ) {
44 jQuery( this ).addClass( value.call(this, j, this.className) );
48 if ( value && typeof value === "string" ) {
49 classNames = value.split( rspace );
51 for ( i = 0, l = this.length; i < l; i++ ) {
54 if ( elem.nodeType === 1 ) {
55 if ( !elem.className && classNames.length === 1 ) {
56 elem.className = value;
59 setClass = " " + elem.className + " ";
61 for ( c = 0, cl = classNames.length; c < cl; c++ ) {
62 if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) {
63 setClass += classNames[ c ] + " ";
66 elem.className = jQuery.trim( setClass );
75 removeClass: function( value ) {
76 var classNames, i, l, elem, className, c, cl;
78 if ( jQuery.isFunction( value ) ) {
79 return this.each(function( j ) {
80 jQuery( this ).removeClass( value.call(this, j, this.className) );
84 if ( (value && typeof value === "string") || value === undefined ) {
85 classNames = (value || "").split( rspace );
87 for ( i = 0, l = this.length; i < l; i++ ) {
90 if ( elem.nodeType === 1 && elem.className ) {
92 className = (" " + elem.className + " ").replace( rclass, " " );
93 for ( c = 0, cl = classNames.length; c < cl; c++ ) {
94 className = className.replace(" " + classNames[ c ] + " ", " ");
96 elem.className = jQuery.trim( className );
108 toggleClass: function( value, stateVal ) {
109 var type = typeof value,
110 isBool = typeof stateVal === "boolean";
112 if ( jQuery.isFunction( value ) ) {
113 return this.each(function( i ) {
114 jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
118 return this.each(function() {
119 if ( type === "string" ) {
120 // toggle individual class names
123 self = jQuery( this ),
125 classNames = value.split( rspace );
127 while ( (className = classNames[ i++ ]) ) {
128 // check each className given, space seperated list
129 state = isBool ? state : !self.hasClass( className );
130 self[ state ? "addClass" : "removeClass" ]( className );
133 } else if ( type === "undefined" || type === "boolean" ) {
134 if ( this.className ) {
135 // store className if set
136 jQuery._data( this, "__className__", this.className );
139 // toggle whole className
140 this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
145 hasClass: function( selector ) {
146 var className = " " + selector + " ";
147 for ( var i = 0, l = this.length; i < l; i++ ) {
148 if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
156 val: function( value ) {
160 if ( !arguments.length ) {
162 hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ];
164 if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
170 return typeof ret === "string" ?
171 // handle most common string cases
172 ret.replace(rreturn, "") :
173 // handle cases where value is null/undef or number
174 ret == null ? "" : ret;
180 var isFunction = jQuery.isFunction( value );
182 return this.each(function( i ) {
183 var self = jQuery(this), val;
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.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];
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 index = elem.selectedIndex,
231 options = elem.options,
232 one = elem.type === "select-one";
234 // Nothing was selected
239 // Loop through all the selected options
240 for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
241 var option = options[ i ];
243 // Don't return options that are disabled or in a disabled optgroup
244 if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
245 (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
247 // Get the specific value for the option
248 value = jQuery( option ).val();
250 // We don't need an array for one selects
255 // Multi-Selects return an array
256 values.push( value );
260 // Fixes Bug #2551 -- select.val() broken in IE after form.reset()
261 if ( one && !values.length && options.length ) {
262 return jQuery( options[ index ] ).val();
268 set: function( elem, value ) {
269 var values = jQuery.makeArray( value );
271 jQuery(elem).find("option").each(function() {
272 this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
275 if ( !values.length ) {
276 elem.selectedIndex = -1;
295 // Always normalize to ensure hook usage
299 attr: function( elem, name, value, pass ) {
300 var nType = elem.nodeType;
302 // don't get/set attributes on text, comment and attribute nodes
303 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
307 if ( pass && name in jQuery.attrFn ) {
308 return jQuery( elem )[ name ]( value );
311 // Fallback to prop when attributes are not supported
312 if ( !("getAttribute" in elem) ) {
313 return jQuery.prop( elem, name, value );
317 notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
319 // Normalize the name if needed
321 name = jQuery.attrFix[ name ] || name;
323 hooks = jQuery.attrHooks[ name ];
326 // Use boolHook for boolean attributes
327 if ( rboolean.test( name ) ) {
330 // Use nodeHook if available( IE6/7 )
331 } else if ( nodeHook ) {
337 if ( value !== undefined ) {
339 if ( value === null ) {
340 jQuery.removeAttr( elem, name );
343 } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
347 elem.setAttribute( name, "" + value );
351 } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
356 ret = elem.getAttribute( name );
358 // Non-existent attributes return null, we normalize to undefined
359 return ret === null ?
365 removeAttr: function( elem, name ) {
367 if ( elem.nodeType === 1 ) {
368 name = jQuery.attrFix[ name ] || name;
370 jQuery.attr( elem, name, "" );
371 elem.removeAttribute( name );
373 // Set corresponding property to false for boolean attributes
374 if ( rboolean.test( name ) && (propName = jQuery.propFix[ name ] || name) in elem ) {
375 elem[ propName ] = false;
382 set: function( elem, value ) {
383 // We can't allow the type property to be changed (since it causes problems in IE)
384 if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
385 jQuery.error( "type property can't be changed" );
386 } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
387 // Setting the type on a radio button after the value resets the value in IE6-9
388 // Reset value to it's default in case type is set after value
389 // This is for element creation
390 var val = elem.value;
391 elem.setAttribute( "type", value );
399 // Use the value property for back compat
400 // Use the nodeHook for button elements in IE6/7 (#1954)
402 get: function( elem, name ) {
403 if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
404 return nodeHook.get( elem, name );
406 return name in elem ?
410 set: function( elem, value, name ) {
411 if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
412 return nodeHook.set( elem, value, name );
414 // Does not return so that setAttribute is also used
421 tabindex: "tabIndex",
422 readonly: "readOnly",
424 "class": "className",
425 maxlength: "maxLength",
426 cellspacing: "cellSpacing",
427 cellpadding: "cellPadding",
431 frameborder: "frameBorder",
432 contenteditable: "contentEditable"
435 prop: function( elem, name, value ) {
436 var nType = elem.nodeType;
438 // don't get/set properties on text, comment and attribute nodes
439 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
444 notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
447 // Fix name and attach hooks
448 name = jQuery.propFix[ name ] || name;
449 hooks = jQuery.propHooks[ name ];
452 if ( value !== undefined ) {
453 if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
457 return (elem[ name ] = value);
461 if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
472 get: function( elem ) {
473 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
474 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
475 var attributeNode = elem.getAttributeNode("tabindex");
477 return attributeNode && attributeNode.specified ?
478 parseInt( attributeNode.value, 10 ) :
479 rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
487 // Add the tabindex propHook to attrHooks for back-compat
488 jQuery.attrHooks.tabIndex = jQuery.propHooks.tabIndex;
490 // Hook for boolean attributes
492 get: function( elem, name ) {
493 // Align boolean attributes with corresponding properties
494 // Fall back to attribute presence where some booleans are not supported
496 return jQuery.prop( elem, name ) === true || ( attrNode = elem.getAttributeNode( name ) ) && attrNode.nodeValue !== false ?
500 set: function( elem, value, name ) {
502 if ( value === false ) {
503 // Remove boolean attributes when set to false
504 jQuery.removeAttr( elem, name );
506 // value is true since we know at this point it's type boolean and not false
507 // Set boolean attributes to the same name and set the DOM property
508 propName = jQuery.propFix[ name ] || name;
509 if ( propName in elem ) {
510 // Only set the IDL specifically if it already exists on the element
511 elem[ propName ] = true;
514 elem.setAttribute( name, name.toLowerCase() );
520 // IE6/7 do not support getting/setting some attributes with get/setAttribute
521 if ( !jQuery.support.getSetAttribute ) {
523 // Use this for any attribute in IE6/7
524 // This fixes almost every IE6/7 issue
525 nodeHook = jQuery.valHooks.button = {
526 get: function( elem, name ) {
528 ret = elem.getAttributeNode( name );
529 // Return undefined if nodeValue is empty string
530 return ret && ret.nodeValue !== "" ?
534 set: function( elem, value, name ) {
535 // Set the existing or create a new attribute node
536 var ret = elem.getAttributeNode( name );
538 ret = document.createAttribute( name );
539 elem.setAttributeNode( ret );
541 return (ret.nodeValue = value + "");
545 // Set width and height to auto instead of 0 on empty string( Bug #8150 )
546 // This is for removals
547 jQuery.each([ "width", "height" ], function( i, name ) {
548 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
549 set: function( elem, value ) {
550 if ( value === "" ) {
551 elem.setAttribute( name, "auto" );
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 // Radios and checkboxes getter/setter
606 if ( !jQuery.support.checkOn ) {
607 jQuery.each([ "radio", "checkbox" ], function() {
608 jQuery.valHooks[ this ] = {
609 get: function( elem ) {
610 // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
611 return elem.getAttribute("value") === null ? "on" : elem.value;
616 jQuery.each([ "radio", "checkbox" ], function() {
617 jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
618 set: function( elem, value ) {
619 if ( jQuery.isArray( value ) ) {
620 return (elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0);