From: David Mark on
Andrea Giammarchi wrote:
> On Mar 8, 1:55 pm, David Mark <dmark.cins...(a)gmail.com> wrote:
>> Then why are you checking for null? That's the point.
>
> again, to know if a variable is null or undefined since I threat both
> values as one,

And therein lies the rub.

> I've never had a valid reason for distinguish between
> null and undefined.

Unfortunately, the rest of the JS world, including host objects
disagrees with your assessment of the two values. Therefore, your code
is unintelligible to others.

>
>
>> Your code is
>> ambiguous and the next person reading it can't be expected to read your
>> mind, so will have to investigate to determine exactly what you meant
>> (or did not mean).
>
> since you'll never find a === undefined in my code, I wonder wchih
> part is ambiguous...

The part that is not === undefined, of course. In other words the ==
null parts.

>
>
>> What does that mean?
>
> typo, I meant every time I have to specify via *comment* that I meant
> it ...
>
>
>> That's not the point. I know what it means, but I can't guess what
>> _you_ thought it meant. If I find, after investigation, that you were
>> using == null when === undefined would have sufficed
>
> there we are ...
> === undefined is a disaster prone approach. Nobody should rely in a
> global scope variable as undefined is to understand if a variable is
> undefined.

That's beside the point. Use typeof xyz == 'undefined' if you are
worried about the global undefined being stepped on (or compatibility
issues that can arise in ancient browsers).

> typeof varname === "undefined" is the only safe way, OR we can simply
> test against == null if we are NOT interested into undefined values.

Those two are not equivalent, hence the ambiguity.

>
>
>> You have got the wrong end of the stick (again).
>
> while apparently You have not get what is the problem and why ...
>

[...]

No, I get what the problem is. :)
From: Richard Cornford on
On Mar 5, 1:37 pm, Scott Sauyet wrote:
> Richard Cornford wrote:
>> On Mar 4, 6:02 pm, Scott Sauyet wrote:
>>> On Mar 4, 11:37 am, Richard Cornford wrote:
>>>> On Mar 4, 4:28 pm, Scott Sauyet wrote:
<snip>
>>> Sorry, I didn't realize the it was a members-only group. The
>>> new jQuery forums seem to me a huge step backwards from a
>>> plain mailing list.
>
>> Certainly restricting the reading of the content seems odd
>> (perhaps there is money to be made from the user database so
>> it is advantageous to force as many registrations as possible).
>
> Although I suppose that could make sense, it seems to be the least
> popular areas that require registration.

It appears that this area (so I presume much else besides) is now
public, which seems like a good idea.

<snip>
> I kept wondering if there was something that the author was
> forgetting to include in his write-up, but the more I think about
> it, the less I believe that he had created anything useful, all his
> talk about "This is a pattern I first developed for my own needs,
> and now has found its way into Fortune 500 companies,"
> notwithstanding.
>
>> I am glad that someone questioned this in a context that the
>> author would find hard to dismiss/ignore, but was there any
>> response? I assume that there was not.
>
> Absolutely none. My response was a week ago, and there has
> been no other activity in the thread.

It seems from this:-

<URL:
http://forum.jquery.com/topic/adamovsky-s-new-design-pattern-issues >

- that your response, suggesting that the 'pattern' proposed would not
work as advertised was insufficiently strongly worded, as it has not
proved enough to prevent people from trying it out and finding that it
doesn't work the hard way.

Sometimes there is something to be said for plain talking, even if some
people get offended by it.

<snip>
> I was trying to find a way to do what the author seemed to want,
> and haven't found anything very useful.

That is an entirely understandable goal, in context. However, it is
worth remembering where it is that the motivation comes from. It is a
consequence of method chaining, as generally employed in JQuery. I found
method chaining an appealing idea when I was first made aware of the
possibility. I then tried it out, and abandoned it within a couple of
weeks. There were two reasons for my abandoning it; the first being that
it made debugging considerably harder (precluding the 'simple' debugging
techniques available in web browsers and forcing a shift to full-on
debugger software (which wasn't as widely available as it is now, and
not available for many browsers in any form at the time (while today it
is only not available for (some/many?) smaller 'embedded' browsers))),
and it made keeping track of the types of the objects in use very
difficult, and so rendered code harder to understand.

That second reason, keeping track of the types of objects, becomes a
problems when you start designing many types of objects to use method
chaining, and start to have methods of one type of object return objects
of other types, on which you immediately call (possibly chains of)
methods. Given that OO design applied to any substantial system will
tend to necessitate (or at least indicate) numerous distinct types of
object, I concluded that it would be better to design such systems
without method chaining. And if you can't build big systems using that
strategy I concluded that it would be better to never use it.

Obviously some alternative possibilities exist, and one of those is for
the design not to involve the creation of multiple types of objects but
to instead create one 'super' (not in the normal OO sense) type that has
all of the methods and properties needed by all of possible types that
would be used otherwise. This would be a design where the omitted types
were conceived as interfaces, but instead of having distinct objects
implement those interfaces, each interface was added to that single
type, making it the 'super' type. Then as the methods chain there is no
longer any problem keeping track of the types of the objects being acted
upon, as they are always that one single 'super' type.

This is the approach taken by JQuery and its plugins. You avoid the
possible issues of keeping track of the type of object through the
chains of method calls because all of the objects are of the JQuery
type.

I didn't seriously consider this strategy for myself because it is
pretty obvious that there are practical limits on how big (how many
interfaces) any single object can implement. Sooner or later there are
going to be naming collocations, and to avoid that some pretty
restrictive naming conventions or something equally anti-intuitive is
going to be necessary. Then there was the question of whether the
resulting objects made any sense, and the impact of that on the
understandably of code if they did not. Why should an object that was a
collection of, say, LI elements (or even any arbitrary collection of
elements) have table sorting methods? So given the debugging issue on
top, I decided that method chaining provided nothing that would even
come close to mitigating its cost.

However, once you are using JQuery, and so have the 'super' object, you
are going ot need something approaching 'namespacing' to avoid the
naming collisions, and you are going to want to be preserving the
'super' object through any and all chains of method calls. And thus you
(and presumably numerous others, who get to the level of wanting to
create their own plugins) come to your question.

> Forgetting the specifics
> of JQuery, can anyone suggest 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?

You mean with the - this - value referring to an instance of the type of
object created with the constructor? The problem being that javascript
sets the - this - value based on how a function is called at the moment
of calling it.

> Perhaps that's a little dense. :-)
>
> 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.

That is only going to happen if - widget - and - widget.namespace -
refer to the same object (at least in ES3), which defeats the purpose of
the exercise as then - widget - has the - method1 - method, and no
useful namespacing is going on.

> }
>
> Obviously, it wouldn't be hard to do something that worked like this:
>
> widget.namespace().method1()
<snip>
> But that doesn't feel quite right. I'd really rather have
>
> widget.namespace.method1()

With getters for properties (i.e. ES 5) the latter can behave like the
former. Though that is nothing more than hiding the method call in the
former so isn't much of a step forward.

> But I can't think of a way to do this. Any suggestions?

Avoid trying to stuff everything into a single object type, and so avoid
method chaining so you have some hope of keeping track of the types of
objects you are then using.

Richard.

From: Richard Cornford on
On Mar 5, 3:01 pm, Scott Sauyet wrote:
> Richard Cornford wrote:
>> On Mar 4, 4:28 pm, Scott Sauyet wrote:
>>> Richard Cornford wrote:
>>> It's possible that this is the case. But my take is that
>>> the quality of JS found around the web is better than it
>>> was before the onset of the GP libraries.
>
>> While my impression is that it is about the same.
>
>>> There are still plenty of really poor scripts floating
>>> around (and I'm talking about ones that make jQuery et al
>>> look positively brilliant)
>
>> What about the really poor scripts that use JQuery et al?
>
>>> but they no longer get the exposure they used to, as it's
>>> become so easy to achieve what these sometimes massive
>>> one-off scripts did using only line or two of jQuery-based
>>> code. (Dojo, MooTools, YUI, whatever.)
>
>> The "massive" one-of scripts you refer to (at least the better
>> of them) tended to be designed to be copied into a web page and
>> then given a "line or two" of configuration. There is not that
>> much difference between doing that and using a general purpose
>> library, except that the one-off script likely did not contain
>> much that it did not use, but the general purpose library will
>> contain some that is not used in any equivalent task.
>
> I wish I could remember its name, but I remember having to remove
> a 150K animation script from a site. All it did was animate
> positions and sizes. It was littered with "if (document.layers)"
> and "if (document.all)",

That suggests an old script, and possibly a script pre-dating
the W3C DOM.

> and worse, it required the user to add
> those same guards to sections of their own code.

There were two very distinct browser object models in use in the
version 4 browser era. The degree to which things could be
abstracted/normalised between the two was limited, and while it
was possible with animation (to the extent that animation was
supported at all (as pre-Opera 7 Opera versions were never that
dynamic) there were plenty of people authoring this stuff who
did not think it was worth the effort (to do, or to learn how
to do).

> It was easy
> enough to replace with a small custom script, and it was replaced
> at a time when the client didn't care about the version 4 browsers,
> so the code was reasonably clean. But what I remember most about
> it was that this was a *popular* script.

"Popular" had never been any sort of guarantee of quality. But I
don't think you have spent enough time looking at the internal
details of the current set of 'popular' libraries. There is still
plenty of branching for individual browsers going on, just driven
by different criteria.

For example, form Dojo (version 0.9):-

| dojo.io.iframe = {
| create: function(/*String*/fname,/*String*/onloadstr,/*String?*/uri){
| //summary: Creates a hidden iframe in the page. Used mostly
| // for IO transports.
| // You do not need to call this to start a dojo.io.iframe
| // request. Just call send().
| //fname: String
| // The name of the iframe. Used for the name attribute on
| // the iframe.
| //onloadstr: String
| // A string of JavaScript that will be executed when the
| // content in the iframe loads.
| //uri: String
| // The value of the src attribute on the iframe element.
| // If a value is not
| // given, then dojo/resources/blank.html will be used.
| if(window[fname]){ return window[fname]; }
| if(window.frames[fname]){ return window.frames[fname]; }
| var cframe = null;
| var turi = uri;
| if(!turi){
| if(djConfig["useXDomain"] && !djConfig["dojoBlankHtmlUrl"]){
| console.debug("dojo.io.iframe.create: When using cross-domain "
| +"Dojo builds,"
| + " please save dojo/resources/blank.html to your domain "
| + "and set djConfig.dojoBlankHtmlUrl"
| + " to the path on your domain to blank.html");
| }
| turi = (
| djConfig["dojoBlankHtmlUrl"]||
| dojo.moduleUrl("dojo", "resources/blank.html")
| );
| }
| var ifrstr = dojo.isIE ?
| '<iframe name="'+fname+'" src="'+turi+'" onload="'+onloadstr+'">'
| : 'iframe';
| cframe = dojo.doc.createElement(ifrstr);
| with(cframe){
| name = fname;
| setAttribute("name", fname);
| id = fname;
| }
| dojo.body().appendChild(cframe);
| window[fname] = cframe;
|
| with(cframe.style){
| if(!dojo.isSafari){
| //We can't change the src in Safari 2.0.3 if absolute
| // position. Bizarro.
| position = "absolute";
| }
| left = top = "0px";
| height = width = "1px";
| visibility = "hidden";
| }
|
| if(!dojo.isIE){
| this.setSrc(cframe, turi, true);
| cframe.onload = new Function(onloadstr);
| }
|
| return cframe;
| },
| setSrc:function(/*DOMNode*/iframe,/*String*/src,/*Boolean*/replace){
| //summary:
| // Sets the URL that is loaded in an IFrame. The replace
| // parameter indicates whether
| // location.replace() should be used when changing the
| // location of the iframe.
| try{
| if(!replace){
| if(dojo.isSafari){
| iframe.location = src;
| }else{
| frames[iframe.name].location = src;
| }
| }else{
| // Fun with DOM 0 incompatibilities!
| var idoc;
| if(dojo.isIE){
| idoc = iframe.contentWindow.document;
| }else if(dojo.isSafari){
| idoc = iframe.document;
| }else{ // if(d.isMozilla){
| idoc = iframe.contentWindow;
| }
|
| //For Safari (at least 2.0.3) and Opera, if the iframe
| //has just been created but it doesn't have content
| //yet, then iframe.document may be null. In that case,
| //use iframe.location and return.
| if(!idoc){
| iframe.location = src;
| return;
| }else{
| idoc.location.replace(src);
| }
| }
| }catch(e){
| console.debug("dojo.io.iframe.setSrc: ", e);
| }
| },

There is still plenty of branching for - isIE -, - isSafari -, and
so on. And most of it unnecessary.

> I simply haven't seen that sort of thing with the GP libraries.
> I've seen plenty of new gratuitous use of animations in pages
> because they already include, say, dojo, and it's so easy to
> just add an animation now. But I haven't seen the kind of
> nonsense that requires a new release of the script on every point
> release of a browser.

You have not been watching the introduction of new IE versions then.

> One might not like the APIs provided by these GP libraries, but
> they do usually provide APIs straightforward enough that the code
> that uses them is simple to write and comprehend.

Simple to write perhaps. Comprehension pretty much pre-supposes
familiarity with the library being used as they frequently employ
terse method names that do little to put across the
actions/purposes of those methods. That is, the resulting code is
a long way from being self-documenting.

> In many site,
> the worst problem of code using JQuery is often the relatively
> innocuous failure to cache the JQuery objects created, running
> queries over and over.

A combination of a failure to understand what is actually happening
behind the scenes and a construct that is trivial to write.

> I'm not trying to say there is no bad code written by users of GP
> libraries. There is certainly some horrendous stuff. But I'm
> seeing much less awful code today than five years ago.

While I just see the nature of the bad code changing.

>> I do see libraries such as JQuery superseding the copy-n-paste
>> script collections of the past, but only in that they provide
>> the equivalent; a source of example code that people who don't
>> know what they are doing can copy and paste into their own pages,
>> achieve a 'working' outcome, and elaborate through repletion.
>> Indeed, I see that as the
>
> "elaborate through repletion"?

Yes, this (unfortunately, but necessarily long) example, culled from
the old JQuery Google group, illustrates what I mean:-

| jQuery.noConflict();
| jQuery(document).ready(function(){
| jQuery('#loading').show();
| jQuery('.wrap').slideDown(1000);
| jQuery('#loading'-).fadeOut(1500, setTimeout('showdocs()',1500));
| jQuery("a:contains('Home')").click(function(e){
| e.preventDefault();
| link = jQuery(this).attr('href');
| jQuery('#loading').fadeIn(200);
| jQuery('.wrap').slideUp(600, function(){
| setTimeout('window.location = link',1000);
| });
| });
| jQuery("a:contains('Pages')").click(function(e){
| e.preventDefault();
| link = jQuery(this).attr('href');
| jQuery('#loading').fadeIn(200);
| jQuery('.wrap').slideUp(600, function(){
| setTimeout('window.location = link',1000);
| });
| });
| jQuery("a:contains('Gallery')").click(function(e){
| e.preventDefault();
| link = jQuery(this).attr('href');
| jQuery('#loading').fadeIn(200);
| jQuery('.wrap').slideUp(600, function(){
| setTimeout('window.location = link',1000);
| });
| });
| jQuery("a:contains('Contact')").click(function(e){
| e.preventDefault();
| link = jQuery(this).attr('href');
| jQuery('#loading').fadeIn(200);
| jQuery('.wrap').slideUp(600, function(){
| setTimeout('window.location = link',1000);
| });
| });
| jQuery("a:contains('Website')").click(function(e){
| e.preventDefault();
| link = jQuery(this).attr('href');
| jQuery('#loading').fadeIn(200);
| jQuery('.wrap').slideUp(600, function(){
| setTimeout('window.location = link',1000);
| });
| });
| jQuery("a:contains('Statistics')").click(function(e){
| e.preventDefault();
| link = jQuery(this).attr('href');
| jQuery('#loading').fadeIn(200);
| jQuery('.wrap').slideUp(600, function(){
| setTimeout('window.location = link',1000);
| });
| });
| jQuery("a:contains('Help')").click(function(e){
| e.preventDefault();
| link = jQuery(this).attr('href');
| jQuery('#loading').fadeIn(200);
| jQuery('.wrap').slideUp(600, function(){
| setTimeout('window.location = link',1000);
| });
| });
| jQuery("a:contains('Edit')").click(function(e){
| e.preventDefault();
| link = jQuery(this).attr('href');
| jQuery('#loading').fadeIn(200);
| jQuery('.wrap').slideUp(600, function(){
| setTimeout('window.location = link',1000);
| });
| });
| jQuery("a:contains('Return to')").click(function(e){
| e.preventDefault();
| link = jQuery(this).attr('href');
| jQuery('#loading').fadeIn(200);
| jQuery('.wrap').slideUp(600, function(){
| setTimeout('window.location = link',1000);
| });
| });
| jQuery("a:contains('Add')").click(function(e){
| e.preventDefault();
| link = jQuery(this).attr('href');
| jQuery('#loading').fadeIn(200);
| jQuery('.wrap').slideUp(600, function(){
| setTimeout('window.location = link',1000);
| });
| });
| jQuery('#jqueryform').submit(function(){
| jQuery('#loading').fadeIn(200);
| jQuery('.wrap').slideUp(600);
| });
| });
| function showdocs() {
| jQuery('.docs').fadeIn(1500);
| }

You can see the code of someone who has been shown how to achieve
an effect they wanted (badly, but what is new there), has taken
that starting point and elaborated on it to achieve the same
effect in a number of places, and done so by repeating the
original with minor changes.

This individual has no idea of programming, else we would not see
10 (or is it 20, given the - slideUp - callback) identical
function expression definitions in their code.

>> best (if not the only) way in which any new library will achieve
>> 'popularity'. Technical quality will always be largely irrelevant
>> (so long is it isn't so bad that it is obviously non-functional
>> on common browsers) because the people looking for a 'solution'
>> to their problem cannot judge that aspect, while the (relative)
>> ease of pasting an example into a working context is something
>> that can easily be judged.
>
> I'm trying to figure out what it is about the Web that makes
> this problem so much more severe than in other development
> environments. It certainly seems to be so. Ease of use trumps
> other measure of quality all the time in web development. Any
> thoughts on why?

Yes, lots.

>> [ ... ] I was thinking in terms of
>> people's perceptions of their own abilities. I have observed
>> before that early superficial success (often following earlier
>> frustration) with the language seems to result in a quite
>> unjustified overconfidence in ones own abilities, and that
>> while suffering that overconfidence it becomes difficult to
>> learn/advance [ ... ]
>
> And, as you say, this becomes especially problematic if people
> so stuck become influential.
>
> There is of course a large spectrum of ability in almost any
> field of endeavor.

But not so much in specialised fields. For example; astronauts, are
either pretty good at it or they are not astronauts. Surgeons also
spring to mind. An ex-girlfriend of a friend of mine once
complained to me that it was unreasonable that she had been thrown
out of medical school for failing to achieve the required 95% pass
rate in her assessments. It is less unreasonable from the
patient's point of view, when you realise that apparently it is
acceptable for doctors to be wrong 5% of the time, and they would
not be wanting to see that percentage increase.

> With web technologies, including JS, it does seem that at
> lot more people without particularly advanced skills do see
> themselves as extremely knowledgeable. Perhaps its the
> number of amateurs involved.

That will be a factor. But possibly as much in how those armatures
react to the people who know more than them. You don't have to know
that much to seriously impress those who know less, but having
impressed them you would only be fooling yourself to take their
accolades seriously.

> There aren't that many people
> who aren't professional programmers or academics trying to
> implement a tricky cryptography algorithm in C++. But the
> church's website might well be entirely maintained by
> someone who learned most of their web technologies by
> cutting and pasting from sties they like.
>
> And even those of us who are professional are not
> necessarily as advanced as we might like. I personally
> have become involved with c.l.j.s. because I know that I
> was missing some fundamentals. For my last few positions,
> I've been the go-to-guy on the team for JS issues. In
> some cases, I could come up with working solutions to
> problems even though I didn't understand all of the
> underlying principles thoroughly. I figured that here,
> I would be able to contribute and learn at the same time.
>
> For those people who think they're beyond that, the only
> hope I have is that they'll be jolted out of their
> complacency when they actually do get in over their heads
> and somebody shows how much they still have to learn.

You can hope. People who are in over their heads often resort to just
doing things badly rather than acquiring the extra depth.

>>> Of course [GP library users trying to advance will] have
>>> unlearning to do. But most advancement involves some
>>> degree of unlearning.
>
>> But what if the things that they unlearn include the
>> opinion that starting out using a general purpose
>> liberally was a good idea?
>
> :-)
>
> They might. That's a harsher lesson than they might be
> ready for, but if it really is the case, presumably they'll
> eventually learn it as they advance.
<snip>

Eventually yes. After all, if this position is viable any reasoning and
inquisitive individual will eventually see it. And as we watch the
general purpose libraries change over time we see the paths they take do
lead in this general direction.

Richard.