._super()

29 views
Skip to first unread message

Justin Meyer

unread,
Jan 23, 2010, 2:32:55 PM1/23/10
to JavaScriptMVC
There's been a lot of feedback on keeping Class and especially _super
in JavaScriptMVC.

I just brought _super and traditional controllers back. However, now
I am reconsidering that.

Here's an app made with out controller and super but still uses
inheritance. I just updated it to use traditional controllers.

http://cdn.javascriptmvc.com/videos/3_0/toolbar/toolbar.html

The functionality is 3 parts -> a toolbar, positionable, and menu
controller.

Toolbars basically open menus. Menus can open other menus. Menu
inherits from Positionable to get the ability to put itself elsewhere
in the DOM and to open / close. Toolbars call an "open" method on
menus, and menu's call "_super" to position themselves correctly using
positionable code..

But inheritance is a bad idea compared to modules. It's basically
"is_a" vs "has_a" relationships. I want to encourage people to build
widgets as collections of other widgets. Similar to "acts_as" in
rails. This idea is inspired by by the great Yehuda Katz:
http://gist.github.com/278694. In this article, he also makes use of
triggering events instead of calling methods.

Lets take a look at the shortcomings of the "is_a" approach ....

First, menu's are inexorably linked to positionable. What if you
wanted a menu that didn't use positionable. Maybe you just needed to
hide / show. How could you do that?

Second, what if you wanted something else to happen on open / hide ?
You would have to inherit from menu controller, make your own menu
controller, and make Toolbar controller use that. UGGGGG!

Now, lets think about how "has_a" solves these problems.

First, A 'position-less' menu is easy. It's just a menu w/o
positionable on it. Just don't add positionable to your element.

Second, To make something else happen on open, you just have to make
that element "has_a" your other plugin.

Importantly, all communication has to happen through events. You
should trigger and listen for events. This is the API.


But, there are some problems .....


To make a toolbar with the old system, I just have to do $
('#toolbar').toolbar();
This is b/c toolbar knows which plugins to create.

With the new system, I'd have to do something more like:

$("#toolbar").toolbar().find('ul').menu().positionable()

Gross! I shouldn't have to do this to make a working toolbar. I
should just say 'TOOLBAR'!!!

So, somehow I've got to figure out how to distinguish is_a and has_a
type things in JMVC. I want to encourage people to make and share
many has_a widgets.

Only your 'application-level' components should be 'is_a'. These are
things extremely specific to your functional requirements and the DOM
they operate on.

I'd like some type of "acts_as" class of plugins.

$.controller("my.toolbar",
{
acts_as_jupiter_toolbar : { menuTypes: [jupiter.menu,
jupiter.positionable],
menuSelector : "ul"
itemSelector: "li" },
acts_as_sortable : {sortOn: ".sortable"},
},
{
menu-open : function(el, ev, menu){
if(el.text() == "bad choice") while(1) alert("bad choice");
}
})


$("#toolbar").myToolbar();


Acts as could be almost just like controllers:

$.actsAs('jupiter.menu',
{
triggers: ["menu-open"] //allows actions named "menu-open" to be
wired up on Controllers that act_as jupiter.menu
},
{
init : function(el, options){ //options passed from acts_as
arguments
... configure ...
}
})

Alexandre Gomes

unread,
Jan 25, 2010, 6:33:49 AM1/25/10
to javasc...@googlegroups.com
Justin,

Is it possible to keep ineritance with controller and super and in addition add some aspect oriented like tools that enable easy widget creation?

This is what I'm thinking for the aspect oriented part of the controllers:

$.controller("jupiterit.menu",
{
    $Positionable: JupiterIT.Positionable({menuSel: "ul", itemSel: "li"}),
    $Sortable: JupiterIT.Sortable({sortOn: '.sortable'}),
   //more custom static code
},
{
    init: function(el, options){
    ...
    },
    $Positionable.menu-open: function(el, ev){
        //custom open handling code
        $Positionable.default("menu-open");
    },
    $Sortable.menu-sort: function(el, ev){
        //custom sort handling code
        $Sortable.default("menu-sort");        
    },
    // more custom prototype code
   ...
}

This way we could override the sub-widget events or defer to default behaviour.

To customize a menu we would do this:

$.controller("my.menu",
{
    $Positionable: My.Positionable({menuSel: "ul", itemSel: "li"}),
    $Sortable: My.Sortable({sortOn: '.sortable'}),
   //more custom static code
},
{
    init: function(el, options){
    ...
    },
    $Positionable.menu-open: function(el, ev){
        //custom open handling code
        $Positionable.default("menu-open");
    },
    $Sortable.menu-sort: function(el, ev){
        //custom sort handling code
        $Sortable.default("menu-sort");        
    },
    // more custom prototype code
   ...
}

So basically, the sub-widgets would be declares in the static part of a controller as:

 $SomeWidget: JupiterIT.SomeWidget(...)

and the sub-widget event would be overrided in the container widget as this:

  $SomeWidget.some-event: function(el, ev){
      //custom overriding code
      $SomeWidget.default("some-event");        
  }

I hope I'm making any sense with this :)

Thanks for reading my email.

Alex











--
You received this message because you are subscribed to the Google Groups "JavaScriptMVC" group.
To post to this group, send email to javasc...@googlegroups.com.
To unsubscribe from this group, send email to javascriptmv...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/javascriptmvc?hl=en.


Alexandre Gomes

unread,
Jan 25, 2010, 6:58:02 AM1/25/10
to javasc...@googlegroups.com
Please let me just to make my example a bit more clear:

$.controller("jupiterit.toolbar",
{
    $Menu: JuspiterIT.Menu({menuSel: 'ul', itemSel: 'li'}),
    $Sortable: JupiterIT.Sortable({sortOn: '.sortable'}),
   //more custom static code
},
{
    init: function(el, options){
    ...
    },
    $Menu.menu-open: function(el, ev){
        //custom menu-open behaviour
        $Menu.default("menu-open");
    },
    $Sortable.menu-sort: function(el, ev){
        //custom sort handling code
        $Sortable.default("menu-sort");        
    },
    // more custom prototype code
   ...
}

And for the Menu widget:

$.controller("jupiterit.menu",
{
    $Positionable: JupiterIT.Positionable(),
   //more custom static code
},
{
    init: function(el, options){
    ...
    },
    $Positionable.show: function(el, ev){
        //custom show handling code
        $Positionable.default("show");
    },
    $Positionable.hide: function(el, ev){
        //custom hide handling code
        $Positionable.default("hide");
    },
    'li click': function(el, ev){
        //menu-open custom code
        this.publish("menu-open");
    }
    // more custom prototype code
   ...
}


And for customizing the Toolbar widget:

$.controller("custom.toolbar",
{
    $Menu: Custom.Menu({menuSel: "ul", itemSel: "li"}),
    $Sortable: Custom.Sortable({sortOn: '.sortable'}),
   //more custom static code
},
{
    init: function(el, options){
    ...
    },
    $Menu.menu-open: function(el, ev){
        //custom open handling code
        $Positionable.default("menu-open");
    },
    $Sortable.menu-sort: function(el, ev){
        //custom sort handling code
        $Sortable.default("menu-sort");        
    },
    // more custom prototype code
   ...
}

Alex

Alexandre Gomes

unread,
Jan 25, 2010, 7:00:35 AM1/25/10
to javasc...@googlegroups.com
Sorry for the typos of my previous email. 

Here's the correcton:

        //menu-open DEFAULT code
        this.publish("menu-open");
    }
    // more custom prototype code
   ...
}


And for customizing the Toolbar widget:

$.controller("custom.toolbar",
{
    $Menu: Custom.Menu({menuSel: "ul", itemSel: "li"}),
    $Sortable: Custom.Sortable({sortOn: '.sortable'}),
   //more custom static code
},
{
    init: function(el, options){
    ...
    },
    $Menu.menu-open: function(el, ev){
        //custom open handling code
        $Menu.default("menu-open");
    },
    $Sortable.menu-sort: function(el, ev){
        //custom sort handling code
        $Sortable.default("menu-sort");        
    },
    // more custom prototype code
   ...
}

Justin Meyer

unread,
Jan 26, 2010, 8:27:32 PM1/26/10
to JavaScriptMVC
Alex, I am not sure how those events would be attached. Also, the
namespacing makes things seem a little heavy.

> <alexandre.r...@gmail.com>wrote:

> ...
>
> read more »

Reply all
Reply to author
Forward
0 new messages