]> source.dussan.org Git - jquery-ui.git/commitdiff
Widget: Don't modify the prototype passed to $.widget(). Fixes #8876 - Calling _super...
authorScott González <scott.gonzalez@gmail.com>
Mon, 3 Dec 2012 19:18:24 +0000 (14:18 -0500)
committerScott González <scott.gonzalez@gmail.com>
Mon, 3 Dec 2012 19:18:24 +0000 (14:18 -0500)
tests/unit/widget/widget_core.js
ui/jquery.ui.widget.js

index 961e2ff62fe38ed0399bda31ae2945c896851e41..8102b1f4fa84d8ffda6ded4c5d9daf8005b091b4 100644 (file)
@@ -13,18 +13,23 @@ TestHelpers.testJshint( "widget" );
 
 test( "widget creation", function() {
        expect( 5 );
-       var myPrototype = {
-               _create: function() {},
-               creationTest: function() {}
-       };
+       var method,
+               myPrototype = {
+                       _create: function() {
+                               equal( method, "_create", "create function is copied over" );
+                       },
+                       creationTest: function() {
+                               equal( method, "creationTest", "random function is copied over" );
+                       }
+               };
 
        $.widget( "ui.testWidget", myPrototype );
        ok( $.isFunction( $.ui.testWidget ), "constructor was created" );
        equal( typeof $.ui.testWidget.prototype, "object", "prototype was created" );
-       equal( $.ui.testWidget.prototype._create, myPrototype._create,
-               "create function is copied over" );
-       equal( $.ui.testWidget.prototype.creationTest, myPrototype.creationTest,
-               "random function is copied over" );
+       method = "_create";
+       $.ui.testWidget.prototype._create();
+       method = "creationTest";
+       $.ui.testWidget.prototype.creationTest();
        equal( $.ui.testWidget.prototype.option, $.Widget.prototype.option,
                "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() {
        expect( 6 );
        var order = 0,
index 06f25576afeadc6e0512ef29168d763b81059d23..2394929924195a77901a1b82e50a75efb180e193 100644 (file)
@@ -25,6 +25,9 @@ $.cleanData = function( elems ) {
 
 $.widget = function( name, base, prototype ) {
        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 ];
 
        name = name.split( "." )[ 1 ];
@@ -71,38 +74,40 @@ $.widget = function( name, base, prototype ) {
        // inheriting from
        basePrototype.options = $.widget.extend( {}, basePrototype.options );
        $.each( prototype, function( prop, value ) {
-               if ( $.isFunction( value ) ) {
-                       prototype[ 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;
-                               };
-                       })();
+               if ( !$.isFunction( value ) ) {
+                       proxiedPrototype[ prop ] = value;
+                       return;
                }
+               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, {
                // TODO: remove support for widgetEventPrefix
                // always use the name + a colon as the prefix, e.g., draggable:start
                // don't prefix for widgets that aren't DOM-based
                widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name
-       }, prototype, {
+       }, proxiedPrototype, {
                constructor: constructor,
                namespace: namespace,
                widgetName: name,