From: Antony Scriven on
On Mar 5, 1:37pm, Scott Sauyet wrote:

> [...]
>
> If I have a constructor,
>
> function MyWidget() { /* ... */}
>
> and a simple plugin architecture:
>
> MyWidget.prototype.myPlugin = function() {
> // here "this" is the object created by 'new MyWidget()'
> }
>
> Is there a straightforward way to create a plug-in
> namespace for some related functionality so that the
> object constructed is the context object for calls to the
> namespaced methods?
>
> // MyWidget.prototype.namespace = ???
>
> var widget = new MyWidget();
> widget.namespace.method1() {
> // "this" should be a reference to the widget created.
> }
>
> Obviously, it wouldn't be hard to do something that worked like
this:
>
> widget.namespace().method1()
>
> that had a similar property. In fact, I think it's simple:
>
> MyWidget.prototype.namespace = function() {
> var self = this,
> method1 = function() {/* ... */},
> method2 = function() {/* ... */};
> return {
> method1: function(){method1.apply(self);},
> method2: function(){method2.apply(self);}
> };
> };
>
> But that doesn't feel quite right. I'd really rather have
>
> widget.namespace.method1()
>
> But I can't think of a way to do this. Any suggestions?

var addnamespace = function(obj, namespace, methods){
var m;
obj[namespace] = {};
for(m in methods){
obj[namespace][m] = function(){
return methods[m].apply(obj, arguments);
};
}
};

methods = {
method1: function(){
return this.x
}
};

var MyWidget = function(){
this.x = 1;
addnamespace(this, 'namespace', methods);
};

var w = new MyWidget();
w.x; // -> 1
w.x = 2;
w.namespace.method1(); // -> 2

Of course, there's an easier way to accomplish this:

w.namespace_method1();

--Antony
From: Scott Sauyet on
Antony Scriven wrote:
> Scott Sauyet wrote:

[related to my request for t a useful way of defining a namespace for
additional functions on the prototype of a constructor function so
that those additional functions will be called in the context of the
object created by the constructor]

>     var addnamespace = function(obj, namespace, methods){
>         var m;
>         obj[namespace] = {};
>         for(m in methods){
>             obj[namespace][m] = function(){
>                 return methods[m].apply(obj, arguments);
>             };
>         }
>     };
>
>     methods = {
>         method1: function(){
>             return this.x
>         }
>     };
>
>     var MyWidget = function(){
>         this.x = 1;
>         addnamespace(this, 'namespace', methods);
>     };

Thank you. This does add the namespace, but it does something that I
was trying to avoid, which is making a copy of the namespace and its
methods for each object created. I suppose if there is a solution, it
will probably have some wrapper functions in the namespace the way
your example and my earlier one with a namespace function did, but I'd
rather not have the namespace tied to each instance if at all
possible.


> Of course, there's an easier way to accomplish this:
>
>     w.namespace_method1();

The intent, though, is that the prototype of the widget function
serves as the way to attach various collections of new behaviors, each
of which should get its own unique namespace. Although a naming
convention might be the only realistic mechanism, I was hoping for
something a bit more elegant.

Thanks for the reply,

-- Scott
From: Antony Scriven on
On Mar 5, 4:26pm, Scott Sauyet wrote:

> Antony Scriven wrote:
> > Scott Sauyet wrote:
>
> [related to my request for t a useful way of defining
> a namespace for additional functions on the prototype of
> a constructor function so that those additional functions
> will be called in the context of the object created by the
> constructor]
>
> > var addnamespace = function(obj, namespace, methods){
> > var m;
> > obj[namespace] = {};
> > for(m in methods){
> > obj[namespace][m] = function(){
> > return methods[m].apply(obj, arguments);
> > };
> > }
> > };
> >
> > methods = {
> > method1: function(){
> > return this.x
> > }
> > };
> >
> > var MyWidget = function(){
> > this.x = 1;
> > addnamespace(this, 'namespace', methods);
> > };
>
> Thank you. This does add the namespace, but it does
> something that I was trying to avoid, which is making
> a copy of the namespace and its methods for each object
> created.

Well, it only makes a copy of the proxy object containing
the wrapper functions, not the methods object. Is that
really so bad?

> I suppose if there is a solution, it will probably have
> some wrapper functions in the namespace the way your
> example and my earlier one with a namespace function did,
> but I'd rather not have the namespace tied to each
> instance if at all possible.
>
> > Of course, there's an easier way to accomplish this:
>
> > w.namespace_method1();
>
> The intent, though, is that the prototype of the widget
> function serves as the way to attach various collections
> of new behaviors, each of which should get its own unique
> namespace.

I don't see how you might get a reference to your new object
before you've executed the constructor.

> Although a naming convention might be the only realistic
> mechanism, I was hoping for something a bit more elegant.

Are naming conventions so bad? And with regard to the
wrapper functions, elegance in language x doesn't
necessarily translate into elegance in Javascript. And then
you have to weigh up the issue of elegance against that of
additional code complexity in your library and any extra
semantic burden that you might be placing upon developers
using your code.

Do you have a pressing need for the kind of namespaces that
you describe? The speed and memory overhead of the first
method I described might not be an issue in practice. You'd
have to profile it in action. --Antony
From: Scott Sauyet on
Antony Scriven wrote:
> Scott Sauyet wrote:
>> Antony Scriven wrote:
>> Thank you.  This does add the namespace, but it does
>> something that I was trying to avoid, which is making
>> a copy of the namespace and its methods for each object
>> created.
>
> Well, it only makes a copy of the proxy object containing
> the wrapper functions, not the methods object. Is that
> really so bad?

Perhaps not. I may not have made it clear at the outset that this is
more an academic exercise, not a practical need. I'll discuss at the
bottom a little more of the motivation.

>>> Of course, there's an easier way to accomplish this:
>>
>>>     w.namespace_method1();
>>
>> The intent, though, is that the prototype of the widget
>> function serves as the way to attach various collections
>> of new behaviors, each of which should get its own unique
>> namespace.
>
> I don't see how you might get a reference to your new object
> before you've executed the constructor.

That's not a problem for methods:

var MyWidget = function() { /* ... */ }
MyWidget.prototype.method3 = function() {
// "this" refers to the widget that was constructed.
}

I was wondering if there was some way to gain this behavior with a
namespace object. I couldn't come up with one, and thought it quite
likely there wasn't one, but I thought I'd see if anyone had a
suggestion.


>> Although a naming convention might be the only realistic
>> mechanism, I was hoping for something a bit more elegant.
>
> Are naming conventions so bad? And with regard to the
> wrapper functions, elegance in language x doesn't
> necessarily translate into elegance in Javascript. And then
> you have to weigh up the issue of elegance against that of
> additional code complexity in your library and any extra
> semantic burden that you might be placing upon developers
> using your code.

Three's nothing wrong with naming conventions. My notion of elegance
is probably quirky, but very clear to me. But the goal is definitely
to lighten the burden of developers using the code. My hope was that
if there was a way of doing this, it might be possible to wrap it in a
pattern or even a function call that grouped their functions into a
namespaced plug-in.


> Do you have a pressing need for the kind of namespaces that
> you describe? The speed and memory overhead of the first
> method I described might not be an issue in practice. You'd
> have to profile it in action. --Antony

There is no pressing need. It grows out of a dissatisfaction with the
way JQuery UI plug-ins are written. They may have the best, or even
the only, realistic solution. But I've never liked it. JQuery's '$'
function is a constructor that creates an object wrapping a number of
DOM elements. (This is an oversimplification, but never mind.) Plug-
ins are attached to the prototype of that constructor. For simple
plug-ins, that's fine. But widgets might need additional behavior,
and the technique adopted for this is to pass a string as the first
argument to the plug-in function to list the method you want to
call.

var picker = $(selector).datepicker(opts);
// ...
picker.datepicker("disable");
// ...
var date = $(selector).datepicker("getDate");

I'm simply not fond of that style API and was wondering if there was a
way to make the API more like:

var picker = $(selector).datepicker(opts);
// or var picker = $(selector).datepicker.create(opts);
// ...
picker.datepicker.disable();
// ...
var date = $(selector).datepicker.getDate();

That was the initial motivation. Even if I found a positive answer,
I'm not sure what I'd do with it. I'm mostly just curious if it's
possible.

-- Scott
From: Antony Scriven on
On Mar 5, 6:34 pm, Scott Sauyet wrote:

> Antony Scriven wrote:
> > Scott Sauyet wrote:
> > > Antony Scriven wrote:
>
> [... on wanting to add a namespace to the prototype of an
> object, such that anObject.namespace.aMethod() sets
> the this value of doMethods's execution context to
> anObject, and not namespace ... ]
>
> > I don't see how you might get a reference to your new object
> > before you've executed the constructor.
>
> That's not a problem for methods: [...]

Sorry, I wasn't clear, I meant I didn't see how you might
get a reference to your new MyWidget object from within
MyWidget.prototype.namespace before you've executed the
constructor, which is exactly what you went on to describe.

> > Do you have a pressing need for the kind of namespaces that
> > you describe? [...]
>
> There is no pressing need.  It grows out of
> a dissatisfaction with the way JQuery UI plug-ins are
> written. [...] But widgets might need additional
> behavior, and the technique adopted for this is to pass
> a string as the first argument to the plug-in function to
> list the method you want to call.
>
>     var picker = $(selector).datepicker(opts);
>     // ...
>     picker.datepicker("disable");
>     // ...
>     var date = $(selector).datepicker("getDate");
>
>
> I'm simply not fond of that style API and was wondering if there
was a
> way to make the API more like:
>
>     var picker = $(selector).datepicker(opts);
>     // or var picker = $(selector).datepicker.create(opts);
>     // ...
>     picker.datepicker.disable();
>     // ...
>     var date = $(selector).datepicker.getDate();
>
> That was the initial motivation.  Even if I found
> a positive answer, I'm not sure what I'd do with it.  I'm
> mostly just curious if it's possible.

I agree, the first code snippet looks somewhat ugly to me.
It also looks more complicated than I feel it needs to be.
Do JQuery's authors have no choice given the model they've
settled on?

But your second example looks odd to me too. Why isn't that
written as the following?

var picker = $(selector).datepicker(opts);
  picker.disable();
  var date = picker.getDate();

--Antony