Prev: FAQ Entry Proposal: What is (function(){ /*...*/ })() ?
Next: FAQ Topic - What is Ajax? (2010-03-01)
From: Scott Sauyet on 5 Mar 2010 15:27 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 5 Mar 2010 16:10 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 5 Mar 2010 16:47 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 5 Mar 2010 19:23 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 6 Mar 2010 03:48
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 |