From: Scott Sauyet on
Antony Scriven wrote:
> Scott Sauyet wrote:
>
>> [W]idgets 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?

Well, that's what I'm trying to determine. But yes, there is one more
major constraint that I forgot to mention. JQuery places heavy
emphasis on method chaining. Unless there is some compelling reason
not to do so, plug-in methods return the JQuery wrapper object. Thus
they can be used like this:

$
("input.date").highlight("yellow").datepicker().hide().fadeIn("slow");

The simple datepicker() method returns the JQuery wrapper object for
the elements matching the selector "input.date", just as do the
highlight, hide, and fadeIn methods; the getDate method of course
would not. In the existing architecture, there might be at some other
point in the code

$("#end_date").disable().datepicker("disable");

which would disable the element with the id "end_date" and then
disable the datepicker attached to it.


> 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();

I think the above also explains the reason that wouldn't work. I
would expect the methods in the namespace to whenever possible return
the JQuery wrapper object. But the first line above would definitely
return a JQuery wrapper.

-- Scott
From: Antony Scriven on
On Mar 5, 8:27 pm, Scott Sauyet wrote:

> Antony Scriven wrote:
> > Scott Sauyet wrote:
>
> [...]  But yes, there is one more major constraint that
> I forgot to mention.  JQuery places heavy emphasis on
> method chaining.  Unless there is some compelling reason
> not to do so, plug-in methods return the JQuery wrapper
> object.  Thus they can be used like this:
>
>     $("input.date").highlight("yellow")
> .datepicker().hide().fadeIn("slow");
>
> The simple datepicker() method returns the JQuery wrapper
> object for the elements matching the selector
> "input.date", just as do the highlight, hide, and fadeIn
> methods; the getDate method of course would not.

Huh? Then you might as well write

$("input.date").highlight("yellow").hide().fadeIn("slow");

> In the existing architecture, there might be at some
> other point in the code
>
>     $("#end_date").disable().datepicker("disable");
>
> which would disable the element with the id "end_date"
> and then disable the datepicker attached to it.

What's the difference? Why not 'enddate.disable();'?

> > 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();
>
> I think the above also explains the reason that wouldn't
> work.  I would expect the methods in the namespace to
> whenever possible return the JQuery wrapper object.  But
> the first line above would definitely return a JQuery
> wrapper.

So? You don't need a dollar to do method chaining. As long
as your datepicker object augments the JQuery wrapper
I don't see a problem. Admittedly my knowledge of JQuery is
limited so I'm quite open to correction on this point. --Antony
From: Scott Sauyet on
Antony Scriven wrote:
> Scott Sauyet wrote:
>> Antony Scriven wrote:
>>     $("input.date").highlight("yellow")
>>         .datepicker().hide().fadeIn("slow");
>>
>> The simple datepicker() method returns the JQuery wrapper
>> object for the elements matching the selector
>> "input.date", just as do the highlight, hide, and fadeIn
>> methods; the getDate method of course would not.
>
> Huh? Then you might as well write
>
>     $("input.date").highlight("yellow").hide().fadeIn("slow");

Well, I didn't mention what it did before it returns the wrapper
object! :-) Datepicker() attaches a click handler to a text field.
On click, it pops up a DIV holding a calendar control. When you
choose a date on the calendar, the text field is populated and the div
disappears.

>  > In the existing architecture, there might be at some
>  > other point in the code
>  >
>  >     $("#end_date").disable().datepicker("disable");
>  >
>  > which would disable the element with the id "end_date"
>  > and then disable the datepicker attached to it.
>
> What's the difference? Why not 'enddate.disable();'?

Unhooking the event listener is the main thing, I guess.

>>> 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();
>>
>> I think the above also explains the reason that wouldn't
>> work.  I would expect the methods in the namespace to
>> whenever possible return the JQuery wrapper object.  But
>> the first line above would definitely return a JQuery
>> wrapper.
>
> So? You don't need a dollar to do method chaining. As long
> as your datepicker object augments the JQuery wrapper
> I don't see a problem. Admittedly my knowledge of JQuery is
> limited so I'm quite open to correction on this point. --Antony

The problem is that other plug-ins might also want to expose a
getDate() method, having nothing to do with datepicker's version.
That's what all this namespacing is about. We want datepicker to be
able to somehow expose a getDate method, but it shouldn't add more
than the "datepicker" property to the wrapper object.

I'm sorry, this is taking more iterations than I expected. Obviously
I didn't explain the idea very well up front.

-- Scott
From: Garrett Smith on
Scott Sauyet wrote:
> 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.
>

I would probably create a separate object so that it is clear what is
what. Depending on the circumstance, that might be done as:-

function MyWidget(){}
function MyAnother(){}
function AnotherWidget(){}

AnotherWidget.prototype mixin(AnotherWidget.prototype,
MyWidget.prototype);

I migut use another approach. What the program wants do do dictates the
abstractions and how they relate.


>
> 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-

The actual constructor is jQuery.prototype.init.

> 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");
>


what do you want the code to look like?

$(sel).getDatepicker().slideFade();
Datepicker.fromSelector(sel).slideFade();
Datepicker.fromElement(sel).slideFade();
Datepicker.getById(id).slideFade();

?

A selector seems a bit off, there. The Datepicker is probably going to
be about just one Datepicker. not a collection of Datepicker instances.
Imagine having a page that has a bunch of Datepickers and wanting to
show them all at the same time -- that's unrealistic.

So I would go with either ID or Element. I would promote the Datepicker
as being the principle thing to be acted upon; not the Element. Based on
that, my API design looks like:

var aDp = Datepicker.getById(id);

If you want to namespace that, you can, say:-

thethickness.Datepicker.getById("ohb");

But I am probably missing something else that you wanted out of it.
--
Garrett
comp.lang.javascript FAQ: http://jibbering.com/faq/
From: Andrea Giammarchi on
On Mar 5, 4:08 pm, Antony Scriven <adscri...(a)gmail.com> wrote:
> == can cause type coercion even if it doesn't in all cases.
> And type coercion to boolean wouldn't change the the
> semantics of null == undefined. I think you are dwelling too much
> on the wording here. It might be worth noting that searching
> for the word 'coercion' in the standard brings back Number(null)
> matches (and not Number(undefined) matches).

undefined >> 0 is 0 tho
parseFloat(null) and parseInt(null) is NaN

what's the point?

Numbers are a different matter and if you don't expect a default, e.g.
Number(myvar || 0) it must return NaN if myvar is undefined since
there is something wrong around that operation or its logic, unless we
did not mean it and checked via isNaN()


> Yes but these are different things. One possible problem
> could be thinking that a variable holds the value null when
> really you forgot to initialise it.

As I have already said, I consider a bad design to mixin two different
states such null and undefined.

Of course there are cases and cases, e.g. JSON.stringify, but again,
if I rely or need that property and I want to check if it has been
defined or not, where undefined for me means == null since null to me
as a state is considered "unassigned" as undefined is, I simply do ==
null

(x === null || typeof x === "undefined")
(x == null)

which one is shorter, faster, maintaining exactly the same meaning?
How many times you repeat that redundant first line check to perform
just x == null ?

> But they do have different meanings. There is a problem of
> intent here. If I'm reading your code and I see
> 'if(x==null)', then I don't know if you really did mean
> 'if(x === null || typeof x == "undefined")' or if you made
> a mistake. It might be more convenient for you to write, but
> not for anyone who has to read it.

Dude, you don't have to convince me undefined !== from null, you
should consider how useful is an undefined variable/property compared
with a null variable/property.
Moreover, you could decide to have default "not assigned yet"
properties in an instance

Point.prototype.x = null;
Point.prototype.y = null;

now, how convenient is above declaration? Totally useless, if p.x ==
null I know its x property has not been set. Do I need to know
anything else?
is it about "for in"s ?

p.z = p.z; and "for in" with undefined z is there ... does it change
anything for my application? I don't think so!

null is a special case that should be better described/understood and
I don't think a flag able to tell JSLint "ignore ==null" is such
problematic issue since cases where we need === null are 99% of the
time followed by || x === undefined, which IS an issue, or || typeof x
=== "undefined", which is just boring if all we wanna know is if it is
null OR undefined.

Regards