A more modest valHooks proposal
- The main difference is that this does not allow arbitrarily adding hooks to any collection of elements. - Modularizes val into a set of easily maintainable and conditional hooks. - valHooks is placed at jQuery.valHooks + This could technically be extended, but I do not see it being used except in very rare cases since you can only apply valHooks to nodeNames and input types, and not a collection of elements as before. We could theoretically privatize valHooks taking it off of jQuery and only use it internally for our own convenience, but again, I do not believe this patch carries with it the dangers of the first proposal. - Slightly improved performance of val on radios and checkboxes for browsers that support checkOn, given the conditional attachment of its hook.
This commit is contained in:
parent
ff06d411d2
commit
64a0005a3b
|
@ -154,82 +154,35 @@ jQuery.fn.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
val: function( value ) {
|
val: function( value ) {
|
||||||
|
var hooks, val,
|
||||||
|
elem = this[0];
|
||||||
|
|
||||||
if ( !arguments.length ) {
|
if ( !arguments.length ) {
|
||||||
var elem = this[0];
|
|
||||||
|
|
||||||
if ( elem ) {
|
if ( elem ) {
|
||||||
if ( jQuery.nodeName( elem, "option" ) ) {
|
hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ];
|
||||||
// attributes.value is undefined in Blackberry 4.7 but
|
|
||||||
// uses .value. See #6932
|
if ( hooks && "get" in hooks && (val = hooks.get( elem )) !== undefined ) {
|
||||||
var val = elem.attributes.value;
|
return val;
|
||||||
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 (elem.value || "").replace(rreturn, "");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
var isFunction = jQuery.isFunction(value);
|
var isFunction = jQuery.isFunction( value );
|
||||||
|
|
||||||
return this.each(function(i) {
|
return this.each(function( i ) {
|
||||||
var self = jQuery(this), val = value;
|
var self = jQuery(this);
|
||||||
|
|
||||||
if ( this.nodeType !== 1 ) {
|
if ( this.nodeType !== 1 ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val = value;
|
||||||
if ( isFunction ) {
|
if ( isFunction ) {
|
||||||
val = value.call(this, i, self.val());
|
val = value.call( this, i, self.val() );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Treat null/undefined as ""; convert numbers to string
|
// Treat null/undefined as ""; convert numbers to string
|
||||||
|
@ -237,27 +190,16 @@ jQuery.fn.extend({
|
||||||
val = "";
|
val = "";
|
||||||
} else if ( typeof val === "number" ) {
|
} else if ( typeof val === "number" ) {
|
||||||
val += "";
|
val += "";
|
||||||
} else if ( jQuery.isArray(val) ) {
|
} else if ( jQuery.isArray( val ) ) {
|
||||||
val = jQuery.map(val, function (value) {
|
val = jQuery.map(val, function ( value ) {
|
||||||
return value == null ? "" : value + "";
|
return value == null ? "" : value + "";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) {
|
hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];
|
||||||
this.checked = jQuery.inArray( self.val(), val ) >= 0;
|
|
||||||
|
|
||||||
} else if ( jQuery.nodeName( this, "select" ) ) {
|
// If set returns undefined, fall back to normal setting
|
||||||
var values = jQuery.makeArray(val);
|
if ( !hooks || ("set" in hooks && hooks.set( this, val ) === undefined) ) {
|
||||||
|
|
||||||
jQuery( "option", this ).each(function() {
|
|
||||||
this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
if ( !values.length ) {
|
|
||||||
this.selectedIndex = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
this.value = val;
|
this.value = val;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -265,6 +207,71 @@ jQuery.fn.extend({
|
||||||
});
|
});
|
||||||
|
|
||||||
jQuery.extend({
|
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 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;
|
||||||
|
},
|
||||||
|
|
||||||
|
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: {
|
attrFn: {
|
||||||
val: true,
|
val: true,
|
||||||
css: true,
|
css: true,
|
||||||
|
@ -386,4 +393,25 @@ jQuery.extend({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 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 );
|
})( jQuery );
|
||||||
|
|
Loading…
Reference in a new issue