mirror of
https://github.com/jquery/jquery-ui.git
synced 2025-01-07 20:34:24 +00:00
Widget: Fixed super methods with deep inheritance chains.
This commit is contained in:
parent
fb35d4e5c5
commit
6096aed0a3
@ -24,8 +24,6 @@ function testWidgetDefaults( widget, defaults ) {
|
||||
|
||||
var privateMethods = [
|
||||
"_createWidget",
|
||||
"_super",
|
||||
"_superApply",
|
||||
"destroy",
|
||||
"option",
|
||||
"enable",
|
||||
|
@ -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 ) {
|
||||
same( this, instance, "this is correct in widget" );
|
||||
same( a, 5, "parameter passed to widget" );
|
||||
var ret = this._super( "method", a, a*2 );
|
||||
same( ret, 15, "super returned value" );
|
||||
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 );
|
||||
}
|
||||
});
|
||||
|
||||
instance = $( "<div>" ).testWidget2().data( "testWidget2" );
|
||||
$.widget( "ui.testWidget3", $.ui.testWidget2, {
|
||||
method: function( a ) {
|
||||
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, 25, "super returned value" );
|
||||
}
|
||||
});
|
||||
|
||||
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 ) );
|
||||
|
29
ui/jquery.ui.widget.js
vendored
29
ui/jquery.ui.widget.js
vendored
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user