One of the new feature in jQuery 1.4 is setter function. For a while now, you’ve been able to pass a function into .attr() and the return value of that function is set into the appropriate attribute. This functionalilty has now been extended into all setter methods: .css(), .attr(), .val(), .html(), .text(), .append(), .prepend(), .before(), .after(), .replaceWith(), .wrap(), .wrapInner(), .offset(), .addClass(), .removeClass(), and .toggleClass(). Addtionally, for the following options, the current value of the item is passed into the function as the second argument: .css(), .attr(), .val(), .html(), .text(), .append(), .prepend(), .offset(), .addClass(), .removeClass(), and .toggleClass().
$('a[target]').attr("title", function(i, currentValue){
return currentValue+ " (Opens in External Window)";
});
$("#xx").text(function (i, currentValue) {
return currentValue+ "modified by fred";
});
In jQuery 1.32, the attr is defined as follow
attr: function( name, value, type ) {
var options = name;
// Look for the case where we're accessing a style value
if ( typeof name === "string" )
if ( value === undefined )
return this[0] && jQuery[ type || "attr" ]( this[0], name ); //jQuery.attr(this[0], name);
else {
options = {};
options[ name ] = value;
}
// Check to see if we're setting style values
return this.each(function(i){
// Set all the styles
for ( name in options )
jQuery.attr(
type ?
this.style :
this,
name, jQuery.prop( this, options[ name ], type, i, name )
);
});
},
But in 1.4.2, it is defined as followed.
attr: function( name, value ) {
//the access function is defined in core module
return access( this, name, value, true, jQuery.attr );
},
We can see that a protected access function really does the job.
// Mutifunctional method to get and set values to a collection
// The value/s can be optionally by executed if its a function
// elems is an array
// key, value is dictionary pair
// exec is an boolean, put it true if you want to call the value as a function
// fn is a function used to access the element
// passe is usually false, I am not sure it is intention
function access( elems, key, value, exec, fn, pass ) {
var length = elems.length;
// Setting many attributes
//if key is complext object like { name: "fred", age: 18 }
if ( typeof key === "object" ) {
for ( var k in key ) {
access( elems, k, key[k], exec, fn, value );
}
return elems;
}
// Setting one attribute
if ( value !== undefined ) {
// Optionally, function values get executed if exec is true
//if value is a function which dyanmically return a true value
//and pass is null
//and exec is true
//then set exec to true
//if caller pass is undefined and caller want to evalueate the value function and value is a function
exec = !pass && exec && jQuery.isFunction(value);
//your callback function is like
//function( elem, name, value)
//for example
//Query.fn.css = function( name, value ) {
// return access( this, name, value, true, function( elem, name, value ) {
//or function( elem, name, value, pass )
//for example attr: function( elem, name, value, pass )
for ( var i = 0; i length; i++ ) {
//fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
//exec means your value to set is need to be determined by the callback functio
var elem = elems[i];
var valueToSet;
if (exec)
{
//get the current value first
var currentValue = fn(elem, key);
//then call the value function to get the new value
valueToSet = value.call(elem, i , currentValue);
}
else
{
valueToSet = value;
}
fn(elem, key, valueToSet, pass);
}
return elems;
}
// Getting an attribute
return length ? fn( elems[0], key ) : undefined;
}
jQuery.fn.css method also used this protected method.
jQuery.fn.css = function( name, value ) {
//rather call function(elem, name, value) call
//access function, and let access function to call back function(elem, name, value)
return access( this, name, value, true, function( elem, name, value ) {
if ( value === undefined ) {
return jQuery.curCSS( elem, name );
}
if ( typeof value === "number" && !rexclude.test(name) ) {
value += "px";
}
jQuery.style( elem, name, value );
});
};