]> source.dussan.org Git - jquery-ui.git/commitdiff
Widget: Fixed super methods with deep inheritance chains.
authorScott González <scott.gonzalez@gmail.com>
Fri, 11 Feb 2011 02:25:50 +0000 (21:25 -0500)
committerScott González <scott.gonzalez@gmail.com>
Fri, 11 Feb 2011 02:25:50 +0000 (21:25 -0500)
tests/unit/testsuite.js
tests/unit/widget/widget_core.js
ui/jquery.ui.widget.js

index 3e4ac5bbfa3c95bcf56aec09d2a72e3e0dfc4093..b3748d8eed0ce84169370a4bc18c5e02eeec7fd5 100644 (file)
@@ -24,8 +24,6 @@ function testWidgetDefaults( widget, defaults ) {
 
 var privateMethods = [
        "_createWidget",
-       "_super",
-       "_superApply",
        "destroy",
        "option",
        "enable",
index 186c407ed51c84a8c65e3906683fccff116480a0..b92885fd955ae747a132e43adf21e5d1b5812aee 100644 (file)
@@ -34,7 +34,7 @@ test( "element normalization", function() {
        };
        $.ui.testWidget();
 
-       $.ui.testWidget.prototype.defaultElement = "<span data-test='pass'>";
+       $.ui.testWidget.prototype.defaultElement = "<span data-test='pass'></span>";
        $.ui.testWidget.prototype._create = function() {
                ok( this.element.is( "span[data-test=pass]" ), "generated span with properties" );
                same( this.element.data( "testWidget" ), this, "instace stored in .data()" );
@@ -224,12 +224,12 @@ test( "._getCreateOptions()", function() {
                options: {
                        option1: "valuex",
                        option2: "valuex",
-                       option3: "value3",
+                       option3: "value3"
                },
                _getCreateOptions: function() {
                        return {
                                option1: "override1",
-                               option2: "overideX",
+                               option2: "overideX"
                        };
                },
                _create: function() {
@@ -274,55 +274,75 @@ test( "re-init", function() {
 });
 
 test( "._super()", function() {
-       expect( 6 );
+       expect( 9 );
        var instance;
        $.widget( "ui.testWidget", {
                method: function( a, b ) {
-                       same( this, instance, "this is correct in super widget" );
-                       same( a, 5, "parameter passed to super widget" );
-                       same( b, 10, "second parameter passed to super widget" );
+                       same( this, instance, "this is correct in testWidget" );
+                       same( a, 5, "parameter passed to testWidget" );
+                       same( b, 20, "second parameter passed to testWidget" );
                        return a + b;
                }
        });
 
        $.widget( "ui.testWidget2", $.ui.testWidget, {
+               method: function( a, b ) {
+                       same( this, instance, "this is correct in testWidget2" );
+                       same( a, 5, "parameter passed to testWidget2" );
+                       same( b, 10, "parameter passed to testWidget2" );
+                       return this._super( "method", a, b*2 );
+               }
+       });
+
+       $.widget( "ui.testWidget3", $.ui.testWidget2, {
                method: function( a ) {
-                       same( this, instance, "this is correct in widget" );
-                       same( a, 5, "parameter passed to widget" );
+                       same( this, instance, "this is correct in testWidget3" );
+                       same( a, 5, "parameter passed to testWidget3" );
                        var ret = this._super( "method", a, a*2 );
-                       same( ret, 15, "super returned value" );
+                       same( ret, 25, "super returned value" );
                }
        });
 
-       instance = $( "<div>" ).testWidget2().data( "testWidget2" );
+       instance = $( "<div>" ).testWidget3().data( "testWidget3" );
        instance.method( 5 );
+       delete $.ui.testWidget3;
        delete $.ui.testWidget2;
 });
 
 test( "._superApply()", function() {
-       expect( 7 );
+       expect( 10 );
        var instance;
        $.widget( "ui.testWidget", {
                method: function( a, b ) {
-                       same( this, instance, "this is correct in super widget" );
-                       same( a, 5, "parameter passed to super widget" );
-                       same( b, 10, "second parameter passed to super widget" );
+                       same( this, instance, "this is correct in testWidget" );
+                       same( a, 5, "parameter passed to testWidget" );
+                       same( b, 10, "second parameter passed to testWidget" );
                        return a + b;
                }
        });
 
        $.widget( "ui.testWidget2", $.ui.testWidget, {
                method: function( a, b ) {
-                       same( this, instance, "this is correct in widget" );
-                       same( a, 5, "parameter passed to widget" );
-                       same( b, 10, "second parameter passed to widget" );
+                       same( this, instance, "this is correct in testWidget2" );
+                       same( a, 5, "parameter passed to testWidget2" );
+                       same( b, 10, "second parameter passed to testWidget2" );
+                       return this._superApply( "method", arguments );
+               }
+       });
+
+       $.widget( "ui.testWidget3", $.ui.testWidget2, {
+               method: function( a, b ) {
+                       same( this, instance, "this is correct in testWidget3" );
+                       same( a, 5, "parameter passed to testWidget3" );
+                       same( b, 10, "second parameter passed to testWidget3" );
                        var ret = this._superApply( "method", arguments );
                        same( ret, 15, "super returned value" );
                }
        });
 
-       instance = $( "<div>" ).testWidget2().data( "testWidget2" );
+       instance = $( "<div>" ).testWidget3().data( "testWidget3" );
        instance.method( 5, 10 );
+       delete $.ui.testWidget3;
        delete $.ui.testWidget2;
 });
 
@@ -829,7 +849,7 @@ test( "redefine", function() {
                        equal( str, "bar", "original invoked with correct parameter" );
                }
        });
-       var ctor = $.ui.testWidget;
+       $.ui.testWidget.foo = "bar";
        $.widget( "ui.testWidget", $.ui.testWidget, {
                method: function( str ) {
                        equal( str, "foo", "new invoked with correct parameter" );
@@ -839,7 +859,7 @@ test( "redefine", function() {
 
        var instance = new $.ui.testWidget();
        instance.method( "foo" );
-       equal( $.ui.testWidget, ctor, "constructor did not change" );
+       equal( $.ui.testWidget.foo, "bar", "static properties remain" );
 });
 
 }( jQuery ) );
index 6b84f7a9cf8f98b0ec26ced3e6784a184f6ab925..27a7cd1b09b81a96a14ad6840b73258914b9c3b4 100644 (file)
@@ -36,7 +36,9 @@ $.widget = function( name, base, prototype ) {
        };
 
        $[ namespace ] = $[ namespace ] || {};
-       $[ namespace ][ name ] = $[ namespace ][ name ] || function( options, element ) {
+       // create the constructor using $.extend() so we can carry over any
+       // static properties stored on the existing constructor (if there is one)
+       $[ namespace ][ name ] = $.extend( function( options, element ) {
                // allow instantiation without "new" keyword
                if ( !this._createWidget ) {
                        return new $[ namespace ][ name ]( options, element );
@@ -47,19 +49,31 @@ $.widget = function( name, base, prototype ) {
                if ( arguments.length ) {
                        this._createWidget( options, element );
                }
-       };
+       }, $[ namespace ][ name ] );
 
        var basePrototype = new base();
        // we need to make the options hash a property directly on the new instance
        // otherwise we'll modify the options hash on the prototype that we're
        // inheriting from
        basePrototype.options = $.extend( true, {}, basePrototype.options );
+       $.each( prototype, function( prop, value ) {
+               if ( $.isFunction( value ) ) {
+                       prototype[ prop ] = function() {
+                               this._super = function( method ) {
+                                       return base.prototype[ method ].apply( this, slice.call( arguments, 1 ) );
+                               };
+                               this._superApply = function( method, args ) {
+                                       return base.prototype[ method ].apply( this, args );
+                               };
+                               return value.apply( this, arguments );
+                       };
+               }
+       });
        $[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
                namespace: namespace,
                widgetName: name,
                widgetEventPrefix: name,
-               widgetBaseClass: fullName,
-               base: base.prototype
+               widgetBaseClass: fullName
        }, prototype );
 
        $.widget.bridge( name, $[ namespace ][ name ] );
@@ -159,13 +173,6 @@ $.Widget.prototype = {
        _create: $.noop,
        _init: $.noop,
 
-       _super: function( method ) {
-               return this.base[ method ].apply( this, slice.call( arguments, 1 ) );
-       },
-       _superApply: function( method, args ) {
-               return this.base[ method ].apply( this, args );
-       },
-
        destroy: function() {
                this._destroy();
                // we can probably remove the unbind calls in 2.0