From: Scott González Date: Fri, 11 Feb 2011 02:25:50 +0000 (-0500) Subject: Widget: Fixed super methods with deep inheritance chains. X-Git-Tag: 1.9m4~17 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=6096aed0a38948fe02a697d0f5349c6903c90e47;p=jquery-ui.git Widget: Fixed super methods with deep inheritance chains. --- diff --git a/tests/unit/testsuite.js b/tests/unit/testsuite.js index 3e4ac5bbf..b3748d8ee 100644 --- a/tests/unit/testsuite.js +++ b/tests/unit/testsuite.js @@ -24,8 +24,6 @@ function testWidgetDefaults( widget, defaults ) { var privateMethods = [ "_createWidget", - "_super", - "_superApply", "destroy", "option", "enable", diff --git a/tests/unit/widget/widget_core.js b/tests/unit/widget/widget_core.js index 186c407ed..b92885fd9 100644 --- a/tests/unit/widget/widget_core.js +++ b/tests/unit/widget/widget_core.js @@ -34,7 +34,7 @@ test( "element normalization", function() { }; $.ui.testWidget(); - $.ui.testWidget.prototype.defaultElement = ""; + $.ui.testWidget.prototype.defaultElement = ""; $.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 = $( "
" ).testWidget2().data( "testWidget2" ); + instance = $( "
" ).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 = $( "
" ).testWidget2().data( "testWidget2" ); + instance = $( "
" ).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 ) ); diff --git a/ui/jquery.ui.widget.js b/ui/jquery.ui.widget.js index 6b84f7a9c..27a7cd1b0 100644 --- a/ui/jquery.ui.widget.js +++ b/ui/jquery.ui.widget.js @@ -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