Good catch - and thanks for the patch! I just landed the improvement:
http://dev.jquery.com/ticket/4884

I made one minor tweak to the patch: In the case where .attr("name",
function(){}) occurs the jQuery.isFunction(value) check is cached (rather
than occurring at every iteration in the array).

Thanks again!

--John


On Fri, Jul 10, 2009 at 7:17 PM, David Flanagan <da...@davidflanagan.com>wrote:

> The 1.3.3pre version of the attr() method doesn't handle object
> arguments where property values are functions in the same way that 1.3.2
> does (and the way that the docs say it should). I think because in the
> code reorganization the jQuery.prop() helper function went away. I
> believe that a very similar bug exists in the css() method, but I
> haven't looked closely enough at it.
>
> I can't figure out how to submit a bug report against 1.3.3pre, so I'm
> posting this here.  Let me know if I should file it as a bug against
> some other version on the tracker.
>
> I've attached a patch to src/attributes.js and also to
> tests/unit/attributes.js
>
> In my patch I also try to optimze the (I assume common) case where
> attr() is called with two arguments.  It no longer creates and then
> iterates over a new object in this case.  But it does make the code
> slightly longer.
>
>        David Flanagan
>
> >
>
> Index: test/unit/attributes.js
> ===================================================================
> --- test/unit/attributes.js     (revision 6415)
> +++ test/unit/attributes.js     (working copy)
> @@ -68,12 +68,15 @@
>  });
>
>  test("attr(Hash)", function() {
> -       expect(1);
> +       expect(3);
>        var pass = true;
>        jQuery("div").attr({foo: 'baz', zoo: 'ping'}).each(function(){
>                if ( this.getAttribute('foo') != "baz" &&
> this.getAttribute('zoo') != "ping" ) pass = false;
>        });
>        ok( pass, "Set Multiple Attributes" );
> +       equals( jQuery('#text1').attr({'value': function() { return
> this.id; }})[0].value, "text1", "Set attribute to computed value #1" );
> +       equals( jQuery('#text1').attr({'title': function(i) { return i;
> }}).attr('title'), "0", "Set attribute to computed value #2");
> +
>  });
>
>  test("attr(String, Object)", function() {
> @@ -334,9 +337,9 @@
>        e.toggleClass(false);
>        e.toggleClass();
>        ok( e.is(".testD.testE"), "Assert class present (restored from
> data)" );
> -
> -
>
> +
> +
>        // Cleanup
>        e.removeClass("testD");
>        e.removeData('__className__');
> Index: src/attributes.js
> ===================================================================
> --- src/attributes.js   (revision 6415)
> +++ src/attributes.js   (working copy)
> @@ -1,34 +1,30 @@
>  jQuery.fn.extend({
>        attr: function( name, value ) {
> -               var options = name, isFunction = jQuery.isFunction( value
> );
> +               var elem, options;
>
> -               if ( typeof name === "string" ) {
> -                       // Are we setting the attribute?
> -                       if ( value === undefined ) {
> +               if ( typeof name === "string" ) {     // A single attribute
> +                       if ( value === undefined ) {        // Query it on
> first element
>                                return this.length ?
>                                        jQuery.attr( this[0], name ) :
>                                        null;
> -
> -                       // Convert name, value params to options hash
> format
> -                       } else {
> -                               options = {};
> -                               options[ name ] = value;
> +                       } else {                            // Set it on
> all elements
> +                               for ( var i = 0, l = this.length; i < l;
> i++ ) {
> +                                       elem = this[i];
> +                                       if ( jQuery.isFunction(value) )
> +                                               value = value.call(elem,i);
> +                                       jQuery.attr( elem, name, value );
> +                               }
>                        }
> -               }
> -
> -               // For each element...
> -               for ( var i = 0, l = this.length; i < l; i++ ) {
> -                       var elem = this[i];
> -
> -                       // Set all the attributes
> -                       for ( var prop in options ) {
> -                               value = options[prop];
> -
> -                               if ( isFunction ) {
> -                                       value = value.call( elem, i );
> +               } else {                              // Multiple
> attributes to set on all
> +                       options = name;
> +                       for ( var i = 0, l = this.length; i < l; i++ ) {
> +                               elem = this[i];
> +                               for ( name in options ) {
> +                                       value = options[name];
> +                                       if ( jQuery.isFunction(value) )
> +                                               value = value.call(elem,i);
> +                                       jQuery.attr( elem, name, value );
>                                }
> -
> -                               jQuery.attr( elem, prop, value );
>                        }
>                }
>
> @@ -258,4 +254,4 @@
>                // Using attr for specific style information is now
> deprecated. Use style insead.
>                return jQuery.style(elem, name, value);
>        }
> -});
> \ No newline at end of file
> +});
>
>

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"jQuery Development" group.
To post to this group, send email to jquery-dev@googlegroups.com
To unsubscribe from this group, send email to 
jquery-dev+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/jquery-dev?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to