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,
12 attr: function( name, value ) {
13 return jQuery.access( this, name, value, true, jQuery.attr );
16 removeAttr: function( name ) {
17 return this.each(function() {
18 jQuery.removeAttr( this, name );
22 prop: function( name, value ) {
23 return jQuery.access( this, name, value, true, jQuery.prop );
26 removeProp: function( 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 if ( jQuery.isFunction( value ) ) {
38 return this.each(function(i) {
39 var self = jQuery(this);
40 self.addClass( value.call(this, i, self.attr("class") || "") );
44 if ( value && typeof value === "string" ) {
45 var classNames = (value || "").split( rspaces );
47 for ( var i = 0, l = this.length; i < l; i++ ) {
50 if ( elem.nodeType === 1 ) {
51 if ( !elem.className ) {
52 elem.className = value;
55 var className = " " + elem.className + " ",
56 setClass = elem.className;
58 for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
59 if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) {
60 setClass += " " + classNames[c];
63 elem.className = jQuery.trim( setClass );
72 removeClass: function( value ) {
73 if ( jQuery.isFunction(value) ) {
74 return this.each(function(i) {
75 var self = jQuery(this);
76 self.removeClass( value.call(this, i, self.attr("class")) );
80 if ( (value && typeof value === "string") || value === undefined ) {
81 var classNames = (value || "").split( rspaces );
83 for ( var i = 0, l = this.length; i < l; i++ ) {
86 if ( elem.nodeType === 1 && elem.className ) {
88 var className = (" " + elem.className + " ").replace(rclass, " ");
89 for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
90 className = className.replace(" " + classNames[c] + " ", " ");
92 elem.className = jQuery.trim( className );
104 toggleClass: function( value, stateVal ) {
105 var type = typeof value,
106 isBool = typeof stateVal === "boolean";
108 if ( jQuery.isFunction( value ) ) {
109 return this.each(function(i) {
110 var self = jQuery(this);
111 self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal );
115 return this.each(function() {
116 if ( type === "string" ) {
117 // toggle individual class names
120 self = jQuery( this ),
122 classNames = value.split( rspaces );
124 while ( (className = classNames[ i++ ]) ) {
125 // check each className given, space seperated 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 + " ";
144 for ( var i = 0, l = this.length; i < l; i++ ) {
145 if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
153 val: function( value ) {
157 if ( !arguments.length ) {
159 hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ];
161 if ( hooks && "get" in hooks && (ret = hooks.get( elem )) !== undefined ) {
165 return (elem.value || "").replace(rreturn, "");
171 var isFunction = jQuery.isFunction( value );
173 return this.each(function( i ) {
174 var self = jQuery(this), val;
176 if ( this.nodeType !== 1 ) {
181 val = value.call( this, i, self.val() );
186 // Treat null/undefined as ""; convert numbers to string
189 } else if ( typeof val === "number" ) {
191 } else if ( jQuery.isArray( val ) ) {
192 val = jQuery.map(val, function ( value ) {
193 return value == null ? "" : value + "";
197 hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];
199 // If set returns undefined, fall back to normal setting
200 if ( !hooks || ("set" in hooks && hooks.set( this, val ) === undefined) ) {
210 get: function( elem ) {
211 // attributes.value is undefined in Blackberry 4.7 but
212 // uses .value. See #6932
213 var val = elem.attributes.value;
214 return !val || val.specified ? elem.value : elem.text;
218 get: function( elem ) {
219 var index = elem.selectedIndex,
221 options = elem.options,
222 one = elem.type === "select-one";
224 // Nothing was selected
229 // Loop through all the selected options
230 for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
231 var option = options[ i ];
233 // Don't return options that are disabled or in a disabled optgroup
234 if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
235 (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
237 // Get the specific value for the option
238 value = jQuery( option ).val();
240 // We don't need an array for one selects
245 // Multi-Selects return an array
246 values.push( value );
250 // Fixes Bug #2551 -- select.val() broken in IE after form.reset()
251 if ( one && !values.length && options.length ) {
252 return jQuery( options[ index ] ).val();
258 set: function( elem, value ) {
259 var values = jQuery.makeArray( value );
261 jQuery(elem).find("option").each(function() {
262 this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
265 if ( !values.length ) {
266 elem.selectedIndex = -1;
285 // Always normalize to ensure hook usage
286 tabindex: "tabIndex",
290 attr: function( elem, name, value, pass ) {
291 var nType = elem.nodeType;
293 // don't get/set attributes on text, comment and attribute nodes
294 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
298 if ( pass && name in jQuery.attrFn ) {
299 return jQuery( elem )[ name ]( value );
303 notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
305 // Normalize the name if needed
306 name = notxml && jQuery.attrFix[ name ] || name;
308 // Get the appropriate hook, or the formHook
309 // if getSetAttribute is not supported and we have form objects in IE6/7
310 hooks = jQuery.attrHooks[ name ] || ( elem.nodeName === "FORM" && formHook );
312 if ( value !== undefined ) {
314 if ( value === null ) {
315 jQuery.removeAttr( elem, name );
318 } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
322 elem.setAttribute( name, "" + value );
328 if ( hooks && "get" in hooks && notxml ) {
329 return hooks.get( elem, name );
333 ret = elem.getAttribute( name );
335 // Non-existent attributes return null, we normalize to undefined
336 return ret === null ?
343 removeAttr: function( elem, name ) {
344 if ( elem.nodeType === 1 ) {
345 name = jQuery.attrFix[ name ] || name;
347 if ( jQuery.support.getSetAttribute ) {
348 // Use removeAttribute in browsers that support it
349 elem.removeAttribute( name );
351 jQuery.attr( elem, name, "" );
352 elem.removeAttributeNode( elem.getAttributeNode( name ) );
359 set: function( elem, value ) {
360 // We can't allow the type property to be changed (since it causes problems in IE)
361 if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
362 jQuery.error( "type property can't be changed" );
367 get: function( elem ) {
368 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
369 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
370 var attributeNode = elem.getAttributeNode("tabIndex");
372 return attributeNode && attributeNode.specified ?
373 parseInt( attributeNode.value, 10 ) :
374 rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
383 prop: function( elem, name, value ) {
384 var nType = elem.nodeType;
386 // don't get/set properties on text, comment and attribute nodes
387 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
392 notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
394 // Try to normalize/fix the name
395 name = notxml && jQuery.propFix[ name ] || name;
397 hooks = jQuery.propHooks[ name ];
399 if ( value !== undefined ) {
400 if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
404 return (elem[ name ] = value);
408 if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== undefined ) {
420 // IE6/7 do not support getting/setting some attributes with get/setAttribute
421 if ( !jQuery.support.getSetAttribute ) {
422 jQuery.attrFix = jQuery.extend( jQuery.attrFix, {
424 "class": "className",
425 maxlength: "maxLength",
426 cellspacing: "cellSpacing",
430 frameborder: "frameBorder"
433 // Use this for any attribute on a form in IE6/7
434 // And the name attribute
435 formHook = jQuery.attrHooks.name = {
436 get: function( elem, name ) {
437 var ret = elem.getAttributeNode( name );
438 // Return undefined if not specified instead of empty string
439 return ret && ret.specified ?
443 set: function( elem, value, name ) {
444 // Check form objects in IE (multiple bugs related)
445 // Only use nodeValue if the attribute node exists on the form
446 var ret = elem.getAttributeNode( name );
448 ret.nodeValue = value;
454 // Set width and height to auto instead of 0 on empty string( Bug #8150 )
455 // This is for removals
456 jQuery.each([ "width", "height" ], function( i, name ) {
457 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
458 set: function( elem, value ) {
459 if ( value === "" ) {
460 elem.setAttribute( name, "auto" );
468 // Remove certain attrs if set to false
469 jQuery.each([ "selected", "checked", "readOnly", "disabled" ], function( i, name ) {
470 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
471 set: function( elem, value ) {
472 if ( value === false ) {
473 jQuery.removeAttr( elem, name );
480 // Some attributes require a special call on IE
481 if ( !jQuery.support.hrefNormalized ) {
482 jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
483 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
484 get: function( elem ) {
485 var ret = elem.getAttribute( name, 2 );
486 return ret === null ? undefined : ret;
492 if ( !jQuery.support.style ) {
493 jQuery.attrHooks.style = {
494 get: function( elem ) {
495 // Return undefined in the case of empty string
496 // Normalize to lowercase since IE uppercases css property names
497 return elem.style.cssText.toLowerCase() || undefined;
499 set: function( elem, value ) {
500 return (elem.style.cssText = "" + value);
505 // Safari mis-reports the default selected property of an option
506 // Accessing the parent's selectedIndex property fixes it
507 if ( !jQuery.support.optSelected ) {
508 jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
509 get: function( elem ) {
510 var parent = elem.parentNode;
513 parent.selectedIndex;
515 // Make sure that it also works with optgroups, see #5701
516 if ( parent.parentNode ) {
517 parent.parentNode.selectedIndex;
524 // Radios and checkboxes getter/setter
525 if ( !jQuery.support.checkOn ) {
526 jQuery.each([ "radio", "checkbox" ], function() {
527 jQuery.valHooks[ this ] = {
528 get: function( elem ) {
529 // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
530 return elem.getAttribute("value") === null ? "on" : elem.value;
535 jQuery.each([ "radio", "checkbox" ], function() {
536 jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
537 set: function( elem, value ) {
538 if ( jQuery.isArray( value ) ) {
539 return (elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0);