Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.javascript > #18026 > unrolled thread

Request for opinions on my newbie approach

Started by"Leonardo Azpurua" <leonardo@exmvps.org>
First post2013-01-08 22:24 -0430
Last post2013-01-10 01:36 +0100
Articles 11 — 5 participants

Back to article view | Back to comp.lang.javascript


Contents

  Request for opinions on my newbie approach "Leonardo Azpurua" <leonardo@exmvps.org> - 2013-01-08 22:24 -0430
    Re: Request for opinions on my newbie approach Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2013-01-09 04:31 +0100
      Re: Request for opinions on my newbie approach "Leonardo Azpurua" <leonardo@exmvps.org> - 2013-01-08 23:34 -0430
        Re: Request for opinions on my newbie approach Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2013-01-09 05:14 +0100
      Re: Request for opinions on my newbie approach Jim T. <x@y.z> - 2013-01-09 14:32 -0500
        Re: Request for opinions on my newbie approach Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2013-01-09 20:41 +0100
          Re: Request for opinions on my newbie approach Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2013-01-09 21:03 +0100
          Re: Request for opinions on my newbie approach Jim T. <x@y.z> - 2013-01-09 15:11 -0500
          Re: Request for opinions on my newbie approach Luc Yen <luc@goal.tw> - 2013-01-09 14:38 -0800
        Re: Request for opinions on my newbie approach "Leonardo Azpurua" <leonardo@exmvps.org> - 2013-01-09 18:10 -0430
          Re: Request for opinions on my newbie approach Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2013-01-10 01:36 +0100

#18026 — Request for opinions on my newbie approach

From"Leonardo Azpurua" <leonardo@exmvps.org>
Date2013-01-08 22:24 -0430
SubjectRequest for opinions on my newbie approach
Message-ID<kcilrc$vt8$1@dont-email.me>
Hi,

Years ago I used to be a professional programmer, then I got totally spoiled 
by VB6 (which I totally love, since it's the best tool so far to do what I 
do), which I used to write a fairly large business management application 
that has been paying my bills for over twelve years.

But now the time has come to move over, and after toying with several other 
development tools and platforms, I decided to adopt HTML + ECMASCRIPT + CSS 
on the client side and PHP for the server for any further development.

In order to simplify my work, I must simplify all the handling of DOM. And I 
am in the process of writing libraries (for usage just by myself) that allow 
me to preserve the blissful innocence won after twelve years using VB6.

Business apps are very much about transcribing and validating data. So there 
are a lot of forms to be written, and I don't want to struggle with that 
ugly DOM thing everytime.

The way to go seems to be to "encapsulate" as much as possible the DOM in 
order to be able to get it out of my "operative" code.

Today I wrote my first attempt at a Form class, that will encapsulate an 
HTML form and allow me to simplify the rest opf the code.

So far, this is all that I have done:

<file forma.js>
 function Form(f) {
    this.name = f.name;

    for (var i = 0; i < f.elements.length; i++)
    {
       var e = f.elements[i];
       this[e.id] = e;
       this.addEventHandler(e, "blur");
       this.addEventHandler(e, "focus");
    }
 }

  Form.prototype.addEventHandler = function (dest, eventName) {
       try {
          dest.addEventListener(eventName, eval(dest.id + "_" + eventName), 
false);
       }
       catch (e) {}
  };
<file/>

And this is a possible use for it (the HTML file contains a form with two 
TEXT HTMLinputElements; function initDocument is called by body.onload):

   var laForma;

   function initDocument()  {
      laForma = new Form(document.forms[0]);
   }

   function Text1_onblur()
   {
      laForma.Text2.value = laForma.Text1.value;
   }

   function Text2_onblur()
   {
      laForma.Text2.value = laForma.Text2.value.toUpperCase();
   }

It "works", in the sense that when I leave Text1, its contents is copied 
into Text2, and when I leave Text2, its contents is rendered in upper case, 
and when any of the methods is undefined, nothing bad happens (not even an 
error on FF JS console).

Of course this is going to "grow": depending of the type of the 
HTMLformElements it is likely that different events will need to be handled 
and browser compatibility issues will have to be solved. I just hope it 
won't grow to be as bloated as most of the generally used libraries.

I am a rather "lonely" coder. So I decided to ask for your opinions to this 
approach before going too much further.

TIA for any comments.

--

[toc] | [next] | [standalone]


#18027

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2013-01-09 04:31 +0100
Message-ID<10136443.OnBuAidq6I@PointedEars.de>
In reply to#18026
Leonardo Azpurua wrote:

> But now the time has come to move over, and after toying with several
> other development tools and platforms, I decided to adopt HTML +
> ECMASCRIPT + CSS on the client side and PHP for the server for any further
> development.

By contrast to HTML and CSS, ECMAScript is _not_ (no longer even partially) 
an acronym; do not write it all-uppercase.  Also know that you are for the 
most part not using ECMAScript, but various implementations of ECMAScript, 
including JavaScript.  [And the DOM is not part of any programming language 
(since more than a decade); it is a language-independent API.]

> The way to go seems to be to "encapsulate" as much as possible the DOM in
> order to be able to get it out of my "operative" code.

You are on the right track.  By encapsulating references to target DOM 
objects in native user-defined wrapper objects you are avoiding to augment 
host objects and all the problems that come with that.  Compare 
JSX:widgets.js.

> Today I wrote my first attempt at a Form class,

These languages (on the client-side) so far use prototype-based inheritance 
only.  There are no classes.  “Object type” appears to be the term that fits 
best as it is used in the ECMAScript Specification.

> that will encapsulate an HTML form and allow me to simplify the rest opf
> the code.
> 
> So far, this is all that I have done:
> 
> <file forma.js>
>  function Form(f) {
>     this.name = f.name;
> 
>     for (var i = 0; i < f.elements.length; i++)

      for (var i = 0, len = f.elements.length; i < len; ++i)

>     {
>        var e = f.elements[i];
>        this[e.id] = e;

Not a good idea.  Keep in mind that

  1. not all form controls (need to) have an ID;
  2. your wrapper object has other properties at that level that could be
     overwritten if a form control has the same 

Unless you also wrap the child controls, you do not need this loop.

>        this.addEventHandler(e, "blur");
>        this.addEventHandler(e, "focus");

This does not make sense as it is.  You will not always have listeners for 
those events.

>     }
>  }
> 
>   Form.prototype.addEventHandler = function (dest, eventName) {
>        try {
>           dest.addEventListener(eventName, eval(dest.id + "_" +
>           eventName),
> false);

Avoid eval() – see the FAQ – and avoid globals.  Your wrapper object can 
have properties for event listeners if necessary (see JSX:widgets.js).

Also, addEventListener() does _not_ (always) throw exceptions if the event 
listener cannot be added.  (A fundamental API design flaw if you ask me.)  
It only throws an exception in some implementations on some environments 
with some event types if the event type is not supported; but that is non-
standard behavior (which is due to another fundamental API design flaw).

<http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventTarget-
addEventListener>
<http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-
Events.html#events-EventTarget-addEventListener>

>        }
>        catch (e) {}
>   };
> <file/>
> […]
> I am a rather "lonely" coder.

Are we not all (at first)? :)

> So I decided to ask for your opinions to this approach before going too
> much further.
> 
> TIA for any comments.

HTH

> --

Signatures are to be delimited with a line containing only ”-- ”.  Thanks to 
the outdated version of Outlook Express that you are using, the trailing 
space is trimmed as you send the message.  See <http://insideoe.com/> for 
details and workarounds.

-- 
PointedEars

Twitter: @PointedEars2
Please do not Cc: me. / Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#18029

From"Leonardo Azpurua" <leonardo@exmvps.org>
Date2013-01-08 23:34 -0430
Message-ID<kcipvf$ifh$1@dont-email.me>
In reply to#18027
"Thomas 'PointedEars' Lahn" <PointedEars@web.de> escribió en el mensaje 
news:10136443.OnBuAidq6I@PointedEars.de...
> Leonardo Azpurua wrote:
>
> These languages (on the client-side) so far use prototype-based 
> inheritance
> only.  There are no classes.  "Object type" appears to be the term that 
> fits
> best as it is used in the ECMAScript Specification.
>

Thanks... I was in doubt as to how to name these things.

>>     for (var i = 0; i < f.elements.length; i++)
>
>      for (var i = 0, len = f.elements.length; i < len; ++i)

Yup...

>
>>     {
>>        var e = f.elements[i];
>>        this[e.id] = e;
>
> Not a good idea.  Keep in mind that
>
>  1. not all form controls (need to) have an ID;
>  2. your wrapper object has other properties at that level that could be
>     overwritten if a form control has the same

Since that library is basically for my own use, and my "standard" requires 
that every meaningful HTML element has an id, and that every id is unique 
within the file, it doesn't sem to be a problem.

> Unless you also wrap the child controls, you do not need this loop.
>
>>        this.addEventHandler(e, "blur");
>>        this.addEventHandler(e, "focus");

Wrapping the controls is the next step. This was just to practically 
validate the approach.

> This does not make sense as it is.  You will not always have listeners for
> those events.
>
> Also, addEventListener() does _not_ (always) throw exceptions if the event
> listener cannot be added.  (A fundamental API design flaw if you ask me.)
> It only throws an exception in some implementations on some environments
> with some event types if the event type is not supported; but that is non-
> standard behavior (which is due to another fundamental API design flaw).

Ok. I have to test the code with different browsers.

I'll try to take a look at JSX in order to get a better grasp on the 
subject.

Thanks!

--

[toc] | [prev] | [next] | [standalone]


#18030

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2013-01-09 05:14 +0100
Message-ID<1630347.0OQEqAhc4z@PointedEars.de>
In reply to#18029
Leonardo Azpurua wrote:

> 
> "Thomas 'PointedEars' Lahn" <PointedEars@web.de> escribi� en el mensaje
> news:10136443.OnBuAidq6I@PointedEars.de...
>> Leonardo Azpurua wrote:
>>
>> These languages (on the client-side) so far use prototype-based
>> inheritance
>> only.  There are no classes.  "Object type" appears to be the term that
>> fits
>> best as it is used in the ECMAScript Specification.

This is unacceptable.  Either fix OE as suggested or use something 
considerably better (such as Thunderbird: <http://getthunderbird.com/>).  
You would do everyone a favor, yourself in double sense.

>>>     {
>>>        var e = f.elements[i];
>>>        this[e.id] = e;
>>
>> Not a good idea.  Keep in mind that
>>
>>  1. not all form controls (need to) have an ID;
>>  2. your wrapper object has other properties at that level that could be
>>     overwritten if a form control has the same

… ID as a property name of your wrapper object (I meant to say then).

> Since that library is basically for my own use, and my "standard" requires
> that every meaningful HTML element has an id, and that every id is unique
> within the file, it doesn't sem to be a problem.

Consider what would happen with

  <form … name="foo">
    <label for="name">Name:</label> <input id="name" name="name">
  </form>

> Thanks!

You're welcome.

> --

See above.

-- 
PointedEars

Twitter: @PointedEars2
Please do not Cc: me. / Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#18035

FromJim T. <x@y.z>
Date2013-01-09 14:32 -0500
Message-ID<a2hre85m1aojpu1l2a46uqbklvnhq7ih3h@4ax.com>
In reply to#18027
On Wed, 09 Jan 2013 04:31:58 +0100, Thomas 'PointedEars' Lahn
<PointedEars@web.de> wrote:

>Leonardo Azpurua wrote:
>
>> But now the time has come to move over, and after toying with several
>> other development tools and platforms, I decided to adopt HTML +
>> ECMASCRIPT + CSS on the client side and PHP for the server for any further
>> development.
>
>By contrast to HTML and CSS, ECMAScript is _not_ (no longer even partially) 
>an acronym; do not write it all-uppercase.  Also know that you are for the 
>most part not using ECMAScript, but various implementations of ECMAScript, 
>including JavaScript.  [And the DOM is not part of any programming language 
>(since more than a decade); it is a language-independent API.]
>
>> The way to go seems to be to "encapsulate" as much as possible the DOM in
>> order to be able to get it out of my "operative" code.
>
>You are on the right track.  By encapsulating references to target DOM 
>objects in native user-defined wrapper objects you are avoiding to augment 
>host objects and all the problems that come with that.  Compare 
>JSX:widgets.js.
>
>> Today I wrote my first attempt at a Form class,
>
>These languages (on the client-side) so far use prototype-based inheritance 
>only.  There are no classes.  “Object type” appears to be the term that fits 
>best as it is used in the ECMAScript Specification.
>
>> that will encapsulate an HTML form and allow me to simplify the rest opf
>> the code.
>> 
>> So far, this is all that I have done:
>> 
>> <file forma.js>
>>  function Form(f) {
>>     this.name = f.name;
>> 
>>     for (var i = 0; i < f.elements.length; i++)
>
>      for (var i = 0, len = f.elements.length; i < len; ++i)

Why? Because it's faster? First, modern JS interpreters will probably
already do this optimization. Second, unless the form has a million
elements it will make no noticeable difference. Cleaner code is better
than pointless "optimization".

[toc] | [prev] | [next] | [standalone]


#18036

FromCezary Tomczyk <cezary.tomczyk@gmail.com>
Date2013-01-09 20:41 +0100
Message-ID<kckh5m$d5l$1@speranza.aioe.org>
In reply to#18035
W dniu 2013-01-09 20:32, Jim T. pisze:
> On Wed, 09 Jan 2013 04:31:58 +0100, Thomas 'PointedEars' Lahn
> <PointedEars@web.de> wrote:
>
>> Leonardo Azpurua wrote:
[...]
>>>      for (var i = 0; i < f.elements.length; i++)
>>
>>       for (var i = 0, len = f.elements.length; i < len; ++i)
>
> Why? Because it's faster? First, modern JS interpreters will probably
> already do this optimization. Second, unless the form has a million
> elements it will make no noticeable difference. Cleaner code is better
> than pointless "optimization".

I wonder: what is not clean in this code?

for (var i = 0, len = f.elements.length; i < len; ++i)

Maybe you can write it as (as you want):

for (var i = 0, len = f.elements.length; i < len; i += 1)

Still can not see what can be confused here for developer. It's just a 
simple, one line begin of loop.

-- 
Cezary Tomczyk
http://www.ctomczyk.pl/

[toc] | [prev] | [next] | [standalone]


#18037

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2013-01-09 21:03 +0100
Message-ID<2135847.KEoUBZbHTU@PointedEars.de>
In reply to#18036
Cezary Tomczyk wrote:

> Jim T. pisze:
>> Thomas 'PointedEars' Lahn wrote:
>>> Leonardo Azpurua wrote:
> [...]
>>>>      for (var i = 0; i < f.elements.length; i++)
>>>
>>>       for (var i = 0, len = f.elements.length; i < len; ++i)
>>
>> Why? Because it's faster? First, modern JS interpreters will probably
>> already do this optimization. Second, unless the form has a million
>> elements it will make no noticeable difference. Cleaner code is better
>> than pointless "optimization".
> 
> I wonder: what is not clean in this code?
> 
> for (var i = 0, len = f.elements.length; i < len; ++i)
> 
> Maybe you can write it as (as you want):
> 
> for (var i = 0, len = f.elements.length; i < len; i += 1)
> 
> Still can not see what can be confused here for developer. It's just a
> simple, one line begin of loop.

Probably they are under the illusion that they have a shadow of a clue what 
they are talking about (which was “modern JS interpreters” – OMG), and that
I would care very much about the humble opinion of address-munging nobodys.  
Or they are just a troll.  Do not feed.

-- 
PointedEars

Twitter: @PointedEars2
Please do not Cc: me. / Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#18038

FromJim T. <x@y.z>
Date2013-01-09 15:11 -0500
Message-ID<tijre8dt30m0a4m46ghejo7hla8bpdtivc@4ax.com>
In reply to#18036
On Wed, 09 Jan 2013 20:41:47 +0100, Cezary Tomczyk
<cezary.tomczyk@gmail.com> wrote:

>W dniu 2013-01-09 20:32, Jim T. pisze:
>> On Wed, 09 Jan 2013 04:31:58 +0100, Thomas 'PointedEars' Lahn
>> <PointedEars@web.de> wrote:
>>
>>> Leonardo Azpurua wrote:
>[...]
>>>>      for (var i = 0; i < f.elements.length; i++)
>>>
>>>       for (var i = 0, len = f.elements.length; i < len; ++i)
>>
>> Why? Because it's faster? First, modern JS interpreters will probably
>> already do this optimization. Second, unless the form has a million
>> elements it will make no noticeable difference. Cleaner code is better
>> than pointless "optimization".
>
>I wonder: what is not clean in this code?
>
>for (var i = 0, len = f.elements.length; i < len; ++i)
>
>Maybe you can write it as (as you want):
>
>for (var i = 0, len = f.elements.length; i < len; i += 1)
>
>Still can not see what can be confused here for developer. It's just a 
>simple, one line begin of loop.

I meant using the additional variable "len". It's not necessary. This
is pretty trivial example, but pointless optimizations are a bit of a
pet peeve of mine.

[toc] | [prev] | [next] | [standalone]


#18044

FromLuc Yen <luc@goal.tw>
Date2013-01-09 14:38 -0800
Message-ID<8031d397-9d58-4b3d-8123-408d4be1d0ff@googlegroups.com>
In reply to#18036
Cezary Tomczyk於 2013年1月10日星期四UTC+8上午3時41分47秒寫道:
> W dniu 2013-01-09 20:32, Jim T. pisze:
> > On Wed, 09 Jan 2013 04:31:58 +0100, Thomas 'PointedEars' Lahn
> > <PointedEars@web.de> wrote:
> >> Leonardo Azpurua wrote:
> [...]
> >>>      for (var i = 0; i < f.elements.length; i++)
> >>       for (var i = 0, len = f.elements.length; i < len; ++i)
> > Why? Because it's faster? First, modern JS interpreters will probably
> > already do this optimization. Second, unless the form has a million
> > elements it will make no noticeable difference. Cleaner code is better
> > than pointless "optimization".
> I wonder: what is not clean in this code?
> for (var i = 0, len = f.elements.length; i < len; ++i)
> Maybe you can write it as (as you want):
> for (var i = 0, len = f.elements.length; i < len; i += 1)
> Still can not see what can be confused here for developer. It's just a 
> simple, one line begin of loop.
YES. it's simple and clear. 
I run a simple test on FF and Chrome over 10K form elements.
The 'len' version is 3x-4x faster. On Safari, it's 2x faster.

[toc] | [prev] | [next] | [standalone]


#18043

From"Leonardo Azpurua" <leonardo@exmvps.org>
Date2013-01-09 18:10 -0430
Message-ID<kckrav$41u$1@dont-email.me>
In reply to#18035
"Jim T." <x@y.z> escribió en el mensaje 
news:a2hre85m1aojpu1l2a46uqbklvnhq7ih3h@4ax.com...
> On Wed, 09 Jan 2013 04:31:58 +0100, Thomas 'PointedEars' Lahn
>>>     for (var i = 0; i < f.elements.length; i++)
>>
>>      for (var i = 0, len = f.elements.length; i < len; ++i)
>
> Why? Because it's faster? First, modern JS interpreters will probably
> already do this optimization. Second, unless the form has a million
> elements it will make no noticeable difference. Cleaner code is better
> than pointless "optimization".

Hi,

In this particular case, Thomas is absolutely right.

Good style -hence good code- comes from good habits.

And good habits come from the strict observance of best coding rules: unless 
a function value may change during the loop execution, avoid using the 
function as a limit for the loop.

Thomas suggestion is an improvement independently of the context. My 
original code may be fine in the given context, but is bad code.

And bad code must be corrected.

It is not a trivial optimization, but an important correction of the style.

--

[toc] | [prev] | [next] | [standalone]


#18047

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2013-01-10 01:36 +0100
Message-ID<2382244.sAQUXPKQoY@PointedEars.de>
In reply to#18043
Leonardo Azpurua wrote:

> "Jim T." […]:
>> On Wed, 09 Jan 2013 04:31:58 +0100, Thomas 'PointedEars' Lahn
>>>>     for (var i = 0; i < f.elements.length; i++)
>>>
>>>      for (var i = 0, len = f.elements.length; i < len; ++i)
>>
>> Why? Because it's faster? First, modern JS interpreters will probably
>> already do this optimization. Second, unless the form has a million
>> elements it will make no noticeable difference. Cleaner code is better
>> than pointless "optimization".
> 
> In this particular case, Thomas is absolutely right.
> 
> Good style -hence good code- comes from good habits.
> 
> And good habits come from the strict observance of best coding rules:
> unless a function value may change during the loop execution, avoid using
> the function as a limit for the loop.
> 
> Thomas suggestion is an improvement independently of the context. My
> original code may be fine in the given context, but is bad code.
                                                         ^^^^^^^^
> And bad code must be corrected.
> 
> It is not a trivial optimization, but an important correction of the
> style.

Not so fast :)

This discussion, and the direction it is taking, reminds me that it is 
actually very important to ask the question “Why?”; to understand, to be 
conscious of, *why* one does things, and continuously question one's 
(design) decisions (and that of others).  Never assume that you know 
everything, or cannot improve anymore.  For that matter, never think in 
black-and-white categories like “good” and “bad”.  For example, “best coding 
rules” can easily turn out to be just bad habits other people had because 
you did not allow yourself to think out of the box.

The reason *why* this style is preferred (by me) is that it is more runtime-
efficient (as demonstrated often before to be just coincidence).  As you 
observed correctly (but perhaps unconsciously), the reason *why* it is 
actually more runtime-efficient here is (beyond any possibly dubious 
benchmark results) that the “length” property *here* yields (through a 
getter *function*) the number of items in an *DOM* (*host*) object¹ 
implementing the HTMLCollection interface (which is probably implemented as 
a linked list and a hash table; see below why):

<http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-40002357>

That value can *not* be cached by the script engine because those host 
objects are “live” (ibid.): the number of items may change during the loop.  
So each property access must invoke said getter.  For example, consider this 
(not the most efficient way to do it, I know, but it proves my point 
nicely²):

  while (node.childNodes.length > 0)
  {
    node.removeChild(node.lastChild);
  }

(BTW: This is a standards-compliant equivalent of “node.innerHTML = "";”)


Insofar there *is* a CAVEAT attached to this optimization:  One must be sure 
that the number of items does not change while the loop is executed.  That 
is usually either true, or unimportant if false.

Otherwise too few or to many items of the NodeList or Collection will be 
attempted to be accessed, whereas the latter, if unchecked, can lead to a 
runtime error.³

_______
¹  Like all host objects, it is _not_ part of any programming language it is
   accessed with.

²  For those interested,

     while (node.lastChild)
     {
       node.removeChild(node.lastChild)
     }

   is probably among the most efficient implementations.

³  Because “undefined has no properties” or, IOW, cannot be converted from
   the primitive Undefined type to the Object type.
-- 
PointedEars

Twitter: @PointedEars2
Please do not Cc: me. / Bitte keine Kopien per E-Mail.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.javascript


csiph-web