- Having fixed this automatically with the use of removeAttribute in browsers that support it, this will fix it for IE6/7 as well. - This has no effect on width/height styles set elsewhere( test added to removeAttr ) - With this addition, I need to call attr in removeAttr for IE6/7, which means boolean calls like .attr("checked", "") will no longer remove the attribute, which I think is fine. .attr("checked", false) will still remove. If I had left it, it would have gone in an infinite loop since setting to empty string is the only way to remove it in these browsers. - The hrefNormalized hooks were returning null if they weren't present. Added the null check to the getter. - Now that the style support fails in IE8 as well due to uppercasing everything, no need to have style included with the hrefNormalized hooks
517 lines
13 KiB
JavaScript
517 lines
13 KiB
JavaScript
(function( jQuery ) {
|
|
|
|
var rclass = /[\n\t\r]/g,
|
|
rspaces = /\s+/,
|
|
rreturn = /\r/g,
|
|
rtype = /^(?:button|input)$/i,
|
|
rfocusable = /^(?:button|input|object|select|textarea)$/i,
|
|
rclickable = /^a(?:rea)?$/i,
|
|
rradiocheck = /^(?:radio|checkbox)$/i,
|
|
formHook;
|
|
|
|
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 ) {
|
|
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 ) {
|
|
if ( jQuery.isFunction( value ) ) {
|
|
return this.each(function(i) {
|
|
var self = jQuery(this);
|
|
self.addClass( value.call(this, i, self.attr("class") || "") );
|
|
});
|
|
}
|
|
|
|
if ( value && typeof value === "string" ) {
|
|
var classNames = (value || "").split( rspaces );
|
|
|
|
for ( var i = 0, l = this.length; i < l; i++ ) {
|
|
var elem = this[i];
|
|
|
|
if ( elem.nodeType === 1 ) {
|
|
if ( !elem.className ) {
|
|
elem.className = value;
|
|
|
|
} else {
|
|
var className = " " + elem.className + " ",
|
|
setClass = elem.className;
|
|
|
|
for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
|
|
if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) {
|
|
setClass += " " + classNames[c];
|
|
}
|
|
}
|
|
elem.className = jQuery.trim( setClass );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
removeClass: function( value ) {
|
|
if ( jQuery.isFunction(value) ) {
|
|
return this.each(function(i) {
|
|
var self = jQuery(this);
|
|
self.removeClass( value.call(this, i, self.attr("class")) );
|
|
});
|
|
}
|
|
|
|
if ( (value && typeof value === "string") || value === undefined ) {
|
|
var classNames = (value || "").split( rspaces );
|
|
|
|
for ( var i = 0, l = this.length; i < l; i++ ) {
|
|
var elem = this[i];
|
|
|
|
if ( elem.nodeType === 1 && elem.className ) {
|
|
if ( value ) {
|
|
var className = (" " + elem.className + " ").replace(rclass, " ");
|
|
for ( var 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) {
|
|
var self = jQuery(this);
|
|
self.toggleClass( value.call(this, i, self.attr("class"), 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( rspaces );
|
|
|
|
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 + " ";
|
|
for ( var i = 0, l = this.length; i < l; i++ ) {
|
|
if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
},
|
|
|
|
val: function( value ) {
|
|
if ( !arguments.length ) {
|
|
var elem = this[0];
|
|
|
|
if ( elem ) {
|
|
if ( jQuery.nodeName( elem, "option" ) ) {
|
|
// 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;
|
|
}
|
|
|
|
// 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 ];
|
|
|
|
// 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;
|
|
}
|
|
|
|
// Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
|
|
if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) {
|
|
return elem.getAttribute("value") === null ? "on" : elem.value;
|
|
}
|
|
|
|
// Everything else, we just grab the value
|
|
return (elem.value || "").replace(rreturn, "");
|
|
|
|
}
|
|
|
|
return undefined;
|
|
}
|
|
|
|
var isFunction = jQuery.isFunction(value);
|
|
|
|
return this.each(function(i) {
|
|
var self = jQuery(this), val = value;
|
|
|
|
if ( this.nodeType !== 1 ) {
|
|
return;
|
|
}
|
|
|
|
if ( isFunction ) {
|
|
val = value.call(this, i, self.val());
|
|
}
|
|
|
|
// 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 + "";
|
|
});
|
|
}
|
|
|
|
if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) {
|
|
this.checked = jQuery.inArray( self.val(), val ) >= 0;
|
|
|
|
} else if ( jQuery.nodeName( this, "select" ) ) {
|
|
var values = jQuery.makeArray(val);
|
|
|
|
jQuery( "option", this ).each(function() {
|
|
this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
|
|
});
|
|
|
|
if ( !values.length ) {
|
|
this.selectedIndex = -1;
|
|
}
|
|
|
|
} else {
|
|
this.value = val;
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
jQuery.extend({
|
|
attrFn: {
|
|
val: true,
|
|
css: true,
|
|
html: true,
|
|
text: true,
|
|
data: true,
|
|
width: true,
|
|
height: true,
|
|
offset: true
|
|
},
|
|
|
|
attrFix: {
|
|
// Always normalize to ensure hook usage
|
|
tabindex: "tabIndex",
|
|
readonly: "readOnly"
|
|
},
|
|
|
|
attr: function( elem, name, value, pass ) {
|
|
var 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 );
|
|
}
|
|
|
|
var ret, hooks,
|
|
notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
|
|
|
|
// Normalize the name if needed
|
|
name = notxml && jQuery.attrFix[ name ] || name;
|
|
|
|
// Get the appropriate hook, or the formHook
|
|
// if getSetAttribute is not supported and we have form objects in IE6/7
|
|
hooks = jQuery.attrHooks[ name ] || ( elem.nodeName === "FORM" && formHook );
|
|
|
|
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 ) {
|
|
return hooks.get( elem, name );
|
|
|
|
} else {
|
|
|
|
ret = elem.getAttribute( name );
|
|
|
|
// Non-existent attributes return null, we normalize to undefined
|
|
return ret === null ?
|
|
undefined :
|
|
ret;
|
|
}
|
|
}
|
|
},
|
|
|
|
removeAttr: function( elem, name ) {
|
|
if ( elem.nodeType === 1 ) {
|
|
name = jQuery.attrFix[ name ] || name;
|
|
|
|
if ( jQuery.support.getSetAttribute ) {
|
|
// Use removeAttribute in browsers that support it
|
|
elem.removeAttribute( name );
|
|
} else {
|
|
jQuery.attr( elem, name, "" );
|
|
elem.removeAttributeNode( elem.getAttributeNode( name ) );
|
|
}
|
|
}
|
|
},
|
|
|
|
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" );
|
|
}
|
|
}
|
|
},
|
|
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;
|
|
}
|
|
}
|
|
},
|
|
|
|
propFix: {},
|
|
|
|
prop: function( elem, name, value ) {
|
|
var nType = elem.nodeType;
|
|
|
|
// don't get/set properties on text, comment and attribute nodes
|
|
if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
|
|
return undefined;
|
|
}
|
|
|
|
var ret, hooks,
|
|
notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
|
|
|
|
// Try to normalize/fix the name
|
|
name = notxml && 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 )) !== undefined ) {
|
|
return ret;
|
|
|
|
} else {
|
|
return elem[ name ];
|
|
}
|
|
}
|
|
},
|
|
|
|
propHooks: {}
|
|
});
|
|
|
|
// IE6/7 do not support getting/setting some attributes with get/setAttribute
|
|
if ( !jQuery.support.getSetAttribute ) {
|
|
jQuery.attrFix = jQuery.extend( jQuery.attrFix, {
|
|
"for": "htmlFor",
|
|
"class": "className",
|
|
maxlength: "maxLength",
|
|
cellspacing: "cellSpacing",
|
|
rowspan: "rowSpan",
|
|
colspan: "colSpan",
|
|
usemap: "useMap",
|
|
frameborder: "frameBorder"
|
|
});
|
|
|
|
// Use this for any attribute on a form in IE6/7
|
|
// And the name attribute
|
|
formHook = jQuery.attrHooks.name = {
|
|
get: function( elem, name ) {
|
|
var ret = elem.getAttributeNode( name );
|
|
// Return undefined if not specified instead of empty string
|
|
return ret && ret.specified ?
|
|
ret.nodeValue :
|
|
undefined;
|
|
},
|
|
set: function( elem, value, name ) {
|
|
// Check form objects in IE (multiple bugs related)
|
|
// Only use nodeValue if the attribute node exists on the form
|
|
var ret = elem.getAttributeNode( name );
|
|
if ( ret ) {
|
|
ret.nodeValue = value;
|
|
return value;
|
|
}
|
|
}
|
|
};
|
|
|
|
// 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;
|
|
}
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
// Remove certain attrs if set to false
|
|
jQuery.each([ "selected", "checked", "readOnly", "disabled" ], function( i, name ) {
|
|
jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
|
|
set: function( elem, value ) {
|
|
if ( value === false ) {
|
|
jQuery.removeAttr( elem, name );
|
|
return value;
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
// Some attributes require a special call on IE
|
|
if ( !jQuery.support.hrefNormalized ) {
|
|
jQuery.each([ "href", "src", "width", "height", "list" ], 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;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
})( jQuery ); |