Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.javascript > #18026 > unrolled thread
| Started by | "Leonardo Azpurua" <leonardo@exmvps.org> |
|---|---|
| First post | 2013-01-08 22:24 -0430 |
| Last post | 2013-01-10 01:36 +0100 |
| Articles | 11 — 5 participants |
Back to article view | Back to comp.lang.javascript
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
| From | "Leonardo Azpurua" <leonardo@exmvps.org> |
|---|---|
| Date | 2013-01-08 22:24 -0430 |
| Subject | Request 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]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2013-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]
| From | "Leonardo Azpurua" <leonardo@exmvps.org> |
|---|---|
| Date | 2013-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]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2013-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]
| From | Jim T. <x@y.z> |
|---|---|
| Date | 2013-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]
| From | Cezary Tomczyk <cezary.tomczyk@gmail.com> |
|---|---|
| Date | 2013-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]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2013-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]
| From | Jim T. <x@y.z> |
|---|---|
| Date | 2013-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]
| From | Luc Yen <luc@goal.tw> |
|---|---|
| Date | 2013-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]
| From | "Leonardo Azpurua" <leonardo@exmvps.org> |
|---|---|
| Date | 2013-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]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2013-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