mirror of
https://github.com/jquery/jquery-ui.git
synced 2025-01-07 20:34:24 +00:00
Widget: Don't modify the prototype passed to $.widget(). Fixes #8876 - Calling _super calls wrong inherited widget.
This commit is contained in:
parent
7312933c88
commit
8b15aaf496
@ -13,18 +13,23 @@ TestHelpers.testJshint( "widget" );
|
|||||||
|
|
||||||
test( "widget creation", function() {
|
test( "widget creation", function() {
|
||||||
expect( 5 );
|
expect( 5 );
|
||||||
var myPrototype = {
|
var method,
|
||||||
_create: function() {},
|
myPrototype = {
|
||||||
creationTest: function() {}
|
_create: function() {
|
||||||
};
|
equal( method, "_create", "create function is copied over" );
|
||||||
|
},
|
||||||
|
creationTest: function() {
|
||||||
|
equal( method, "creationTest", "random function is copied over" );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
$.widget( "ui.testWidget", myPrototype );
|
$.widget( "ui.testWidget", myPrototype );
|
||||||
ok( $.isFunction( $.ui.testWidget ), "constructor was created" );
|
ok( $.isFunction( $.ui.testWidget ), "constructor was created" );
|
||||||
equal( typeof $.ui.testWidget.prototype, "object", "prototype was created" );
|
equal( typeof $.ui.testWidget.prototype, "object", "prototype was created" );
|
||||||
equal( $.ui.testWidget.prototype._create, myPrototype._create,
|
method = "_create";
|
||||||
"create function is copied over" );
|
$.ui.testWidget.prototype._create();
|
||||||
equal( $.ui.testWidget.prototype.creationTest, myPrototype.creationTest,
|
method = "creationTest";
|
||||||
"random function is copied over" );
|
$.ui.testWidget.prototype.creationTest();
|
||||||
equal( $.ui.testWidget.prototype.option, $.Widget.prototype.option,
|
equal( $.ui.testWidget.prototype.option, $.Widget.prototype.option,
|
||||||
"option method copied over from base widget" );
|
"option method copied over from base widget" );
|
||||||
});
|
});
|
||||||
@ -1324,6 +1329,34 @@ test( "redefine - widgetEventPrefix", function() {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test( "mixins", function() {
|
||||||
|
expect( 2 );
|
||||||
|
|
||||||
|
var mixin = {
|
||||||
|
method: function() {
|
||||||
|
return "mixed " + this._super();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$.widget( "ui.testWidget1", {
|
||||||
|
method: function() {
|
||||||
|
return "testWidget1";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$.widget( "ui.testWidget2", {
|
||||||
|
method: function() {
|
||||||
|
return "testWidget2";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$.widget( "ui.testWidget1", $.ui.testWidget1, mixin );
|
||||||
|
$.widget( "ui.testWidget2", $.ui.testWidget2, mixin );
|
||||||
|
|
||||||
|
equal( $( "<div>" ).testWidget1().testWidget1( "method" ),
|
||||||
|
"mixed testWidget1", "testWidget1 mixin successful" );
|
||||||
|
equal( $( "<div>" ).testWidget2().testWidget2( "method" ),
|
||||||
|
"mixed testWidget2", "testWidget2 mixin successful" );
|
||||||
|
});
|
||||||
|
|
||||||
asyncTest( "_delay", function() {
|
asyncTest( "_delay", function() {
|
||||||
expect( 6 );
|
expect( 6 );
|
||||||
var order = 0,
|
var order = 0,
|
||||||
|
55
ui/jquery.ui.widget.js
vendored
55
ui/jquery.ui.widget.js
vendored
@ -25,6 +25,9 @@ $.cleanData = function( elems ) {
|
|||||||
|
|
||||||
$.widget = function( name, base, prototype ) {
|
$.widget = function( name, base, prototype ) {
|
||||||
var fullName, existingConstructor, constructor, basePrototype,
|
var fullName, existingConstructor, constructor, basePrototype,
|
||||||
|
// proxiedPrototype allows the provided prototype to remain unmodified
|
||||||
|
// so that it can be used as a mixin for multiple widgets (#8876)
|
||||||
|
proxiedPrototype = {},
|
||||||
namespace = name.split( "." )[ 0 ];
|
namespace = name.split( "." )[ 0 ];
|
||||||
|
|
||||||
name = name.split( "." )[ 1 ];
|
name = name.split( "." )[ 1 ];
|
||||||
@ -71,38 +74,40 @@ $.widget = function( name, base, prototype ) {
|
|||||||
// inheriting from
|
// inheriting from
|
||||||
basePrototype.options = $.widget.extend( {}, basePrototype.options );
|
basePrototype.options = $.widget.extend( {}, basePrototype.options );
|
||||||
$.each( prototype, function( prop, value ) {
|
$.each( prototype, function( prop, value ) {
|
||||||
if ( $.isFunction( value ) ) {
|
if ( !$.isFunction( value ) ) {
|
||||||
prototype[ prop ] = (function() {
|
proxiedPrototype[ prop ] = value;
|
||||||
var _super = function() {
|
return;
|
||||||
return base.prototype[ prop ].apply( this, arguments );
|
|
||||||
},
|
|
||||||
_superApply = function( args ) {
|
|
||||||
return base.prototype[ prop ].apply( this, args );
|
|
||||||
};
|
|
||||||
return function() {
|
|
||||||
var __super = this._super,
|
|
||||||
__superApply = this._superApply,
|
|
||||||
returnValue;
|
|
||||||
|
|
||||||
this._super = _super;
|
|
||||||
this._superApply = _superApply;
|
|
||||||
|
|
||||||
returnValue = value.apply( this, arguments );
|
|
||||||
|
|
||||||
this._super = __super;
|
|
||||||
this._superApply = __superApply;
|
|
||||||
|
|
||||||
return returnValue;
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
}
|
}
|
||||||
|
proxiedPrototype[ prop ] = (function() {
|
||||||
|
var _super = function() {
|
||||||
|
return base.prototype[ prop ].apply( this, arguments );
|
||||||
|
},
|
||||||
|
_superApply = function( args ) {
|
||||||
|
return base.prototype[ prop ].apply( this, args );
|
||||||
|
};
|
||||||
|
return function() {
|
||||||
|
var __super = this._super,
|
||||||
|
__superApply = this._superApply,
|
||||||
|
returnValue;
|
||||||
|
|
||||||
|
this._super = _super;
|
||||||
|
this._superApply = _superApply;
|
||||||
|
|
||||||
|
returnValue = value.apply( this, arguments );
|
||||||
|
|
||||||
|
this._super = __super;
|
||||||
|
this._superApply = __superApply;
|
||||||
|
|
||||||
|
return returnValue;
|
||||||
|
};
|
||||||
|
})();
|
||||||
});
|
});
|
||||||
constructor.prototype = $.widget.extend( basePrototype, {
|
constructor.prototype = $.widget.extend( basePrototype, {
|
||||||
// TODO: remove support for widgetEventPrefix
|
// TODO: remove support for widgetEventPrefix
|
||||||
// always use the name + a colon as the prefix, e.g., draggable:start
|
// always use the name + a colon as the prefix, e.g., draggable:start
|
||||||
// don't prefix for widgets that aren't DOM-based
|
// don't prefix for widgets that aren't DOM-based
|
||||||
widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name
|
widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name
|
||||||
}, prototype, {
|
}, proxiedPrototype, {
|
||||||
constructor: constructor,
|
constructor: constructor,
|
||||||
namespace: namespace,
|
namespace: namespace,
|
||||||
widgetName: name,
|
widgetName: name,
|
||||||
|
Loading…
Reference in New Issue
Block a user