468,117 Members | 2,204 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,117 developers. It's quick & easy.

hiding divs

Hi Gurus

I have a page, which looks a bit like this:

....
<body>
<div ID=id1>................</DIV>
<div ID=gsd>................</DIV>
<div ID=ewd>................</DIV>
<div ID=fac>................</DIV>
<div ID=act>................</DIV>
</body>

I would like id1 to be visible at all times, but the other ids only to be
visible one if the time, using something like

<A HREF="#esf" onclick="showdiv('act')">

What would be the best way of doing this?

- TIA

Nicolaas
PS I am looking for a real solid solution, as I am looking at using it on
500 pages and it also definitely need to work for people without javascript
(in which case everything is shown...)
Jul 23 '05 #1
39 3315
The best approach would be to write a JS class, which would handle all
of these divs, given that you need it for 500 pages. The advantage is
that if you need to change anything, you would do it only in 1 class.
Here's what I'm talking about:

var handler = new JSScriptHandler ();
handler.addItem (document.getElementById ('id1'));
handler.addItem (document.getElementById ('gsg'));

handler.Start (); // This method would actually define all event
handlers, etc.

This is just an idea, not implementation. If you need more technical
info, ask this question in our forum at www.worcsnet.com. There is
actually an example of a similar control right on the home page ().

I do not think there's a real solution without JS. Just make sure that
your code works in all browsers.

Hope this helps,
GregS
IAB Studio developer
www.worcsnet.com
www.iabstudio.com
WindAndWaves wrote:
Hi Gurus

I have a page, which looks a bit like this:

...
<body>
<div ID=id1>................</DIV>
<div ID=gsd>................</DIV>
<div ID=ewd>................</DIV>
<div ID=fac>................</DIV>
<div ID=act>................</DIV>
</body>

I would like id1 to be visible at all times, but the other ids only to be visible one if the time, using something like

<A HREF="#esf" onclick="showdiv('act')">

What would be the best way of doing this?

- TIA

Nicolaas
PS I am looking for a real solid solution, as I am looking at using it on 500 pages and it also definitely need to work for people without javascript (in which case everything is shown...)


Jul 23 '05 #2
WindAndWaves wrote:
I would like id1 to be visible at all times, but the other ids only to be
visible one if the time, using something like

<A HREF="#esf" onclick="showdiv('act')">
This seems to be a pretty standard requirement, however your exemple is
a bit unclear, mixing a "esf" anchor with an "act" id (meaning, is there
a need for an internal hash?).
PS I am looking for a real solid solution, as I am looking at using it on
500 pages and it also definitely need to work for people without javascript
(in which case everything is shown...)


The script part in the code below can be used as a js include,
preferably written before the end of the body tag. It is independent
from the page structure (doesn't require any special setting in the
page), and should not prevent existing scripts from running correctly.
<style type="text/css">
a {margin:0 1em;}
div[id] {background-color:yellow; color:orange;}
</style>

<div>
<a href="#foo1">Foo1</a>
<a href="#foo2">Foo2</a>
<a href="#foo3">Foo3</a>
</div>
<div id="foo1">Foo1</div>
<div id="foo2">Foo2</div>
<div id="foo3">Foo3</div>
<script type="text/javascript">
// --- add "call" support ---
if(!Function.prototype.call){
Function.prototype.call=function(obj, arg){
var fn="call", ret;
while(typeof obj[fn]!="undefined") fn+=fn;
obj[fn]=this;
ret=obj[fn](arg);
obj[fn]=null;
return ret;
}
}

// --- add generic addEventListener ---
if(typeof _e!="function") {
_e=function(obj, evt, func) {
if(obj[evt]) {
obj[evt]=(function(f) {
return function(evt) {
func.call(this, evt);
return f.call(this, evt);
}
})(obj[evt]);
} else {
obj[evt]=func;
}
}
}

// --- add the toggling mechanism ---
_e(window, "onload",
function(evt) {
if(document.getElementById &&
document.getElementsByTagName &&
document.body &&
document.body.style &&
typeof document.body.style.display=="string"
){

// --- core ---
var activeDiv, handler, show, hide, getId, map;

map = {};
hide = function(el) { el.style.display="none"; }
show = function(el) { el.style.display="block"; }
getId = function(s) { return s.substr(s.lastIndexOf("#")+1); }
handler = function(evt) {
if(activeDiv!=this) {
if(activeDiv) hide(activeDiv);
show(activeDiv=map[this.href]);
}
return true;
}

// --- conditional init ---
var ii, dv, a;

for(ii=0,a=document.getElementsByTagName("a");ii<a .length;ii++){
if(a[ii].href.indexOf("#")!=-1) {
dv=document.getElementById(getId(a[ii].href));
if(dv) {
map[a[ii].href]=dv;
_e(a[ii], "onclick", handler);
hide(dv);
}
}
}

}
}
);
</script>
Jul 23 '05 #3
WindAndWaves wrote:
[...]
Nicolaas
PS I am looking for a real solid solution, as I am looking at using it on
500 pages and it also definitely need to work for people without javascript
(in which case everything is shown...)


I can't vouch for browsers other than Firefox and IE 6, so please test
the document.all stuff thoroughly.

If the user doesn't have JS enabled, all the divs are shown and the
links become anchors so clicking on them will navigate to the
appropriate div. Adding names & ids should account for some older
browsers, but again I can't test it at the moment so up to you.

If a browser doesn't understand any part of the script, the divs aren't
hidden in the first place. You may want to dynamically change the
"return false" so that if the script does not complete (i.e. the divs
are not hidden), the link to the div is followed. Sorry, I don't have
the browsers to test it in here.

Code below, cheers, Rob.

*In the <head>:*

<script type="text/javascript">
function showDiv(b,el){
var bRef = null;
if (document.getElementById) {
bRef = document.getElementById(b);
} else {
bRef = document.all[b];
}
if(bRef.childNodes){
var z = bRef.childNodes;
for (var i=0;i<z.length; i++) {

// This will hide just the divs
// and show the one clicked on
if (z[i].nodeName =='DIV' && z[i].style) {
z[i].style.display = 'none';
if (z[i].id == el) z[i].style.display = '';
}
}
}
}
</script>
<style type="text/css">
.demo {width: 200px; height: 300px;}
</style>
*Add onload to body tag:*

<body onload="showDiv('base','');">
*Some play HTML to test it out on (love the colours!!)*
<div id="d00">This is div 00<br>
<a href="#sdf" onclick="
showDiv('base','sdf');this.blur();return false;">sdf</a>
<a href="#abc" onclick="
showDiv('base','abc');this.blur();
return false;">&nbsp;|&nbsp;abc</a>
<a href="#def" onclick="
showDiv('base','def');this.blur();
return false;">&nbsp;|&nbsp;def</a>
<a href="#ghi" onclick="
showDiv('base','ghi');this.blur();
return false;">&nbsp;|&nbsp;ghi</a>
</div>
<div id="base">
<div name="sdf" id="sdf" class="demo"
style="background-color: blue;">div sdf</div>
<div name="abc" id="abc" class="demo"
style="background-color: red;">div abc</div>
<div name="def" id="def" class="demo"
style="background-color: green;">div def</div>
<div name="ghi" id="ghi" class="demo"
style="background-color: pink;">div ghi</div>
</div>

Jul 23 '05 #4
sw**********@yahoo.com wrote:
The best approach would be to write a JS class, which would handle all
of these divs, given that you need it for 500 pages. The advantage is
that if you need to change anything, you would do it only in 1 class.
Here's what I'm talking about:

var handler = new JSScriptHandler ();
handler.addItem (document.getElementById ('id1'));
handler.addItem (document.getElementById ('gsg'));

handler.Start (); // This method would actually define all event
handlers, etc.

This is just an idea, not implementation. If you need more technical
info, ask this question in our forum at www.worcsnet.com. There is
actually an example of a similar control right on the home page ().


If the script and HTML code on the main page is indicative of the
answers given there, its a site better left alone.

But, is it the policy of worcsnet.com to solicit questions for its
forums from Usenet?
--
Randy
comp.lang.javascript FAQ - http://jibbering.com/faq
Jul 23 '05 #5
An example you might wish to play with:

<HTML>
<HEAD>
<TITLE>Test</TITLE>
<script type="text/javascript">
<!--
if(!document.getElementById) {
document.getElementById = document.all ? function(i) {return
document.all[i];} : function() {return null;};
}

function mySetStyleDisplay (myDiv, myStyle){
var obj = document.getElementById(myDiv);
if(obj && obj.style) {obj.style.display = myStyle;}
}

function myShow(myDiv){
mySetStyleDisplay (myDiv,'');
}

function myHide(myDiv){
mySetStyleDisplay (myDiv,'none');
}

function HideAllNotFirst (){
var obj = document.getElementById('uberDIV');
var i = 0;
for (var o in obj.childNodes){
if (obj.childNodes[o].nodeName == 'DIV') {
if (i==1){obj.childNodes[o].style.display = 'none';} else {i=1;};
}
}
}
-->
</script>

</HEAD>
<BODY>
<A HREF="#" onMouseOver="myShow('item_id1');"
onMouseOut="myHide('item_id1');">id1</a>
<A HREF="#" onMouseOver="myShow('item_gsd');"
onMouseOut="myHide('item_gsd');">gsd</a>
<A HREF="#" onMouseOver="myShow('item_ewd');"
onMouseOut="myHide('item_ewd');">ewd</a>
<A HREF="#" onMouseOver="myShow('item_fac');"
onMouseOut="myHide('item_fac');">fac</a>
<A HREF="#" onMouseOver="myShow('item_act');"
onMouseOut="myHide('item_act');">act</a>

<div ID=uberDIV>
<div ID=item_id1>id1</DIV>
<div ID=item_gsd>gsd</DIV>
<div ID=item_ewd>ewd</DIV>
<div ID=item_fac>fac</DIV>
<div ID=item_act>act</DIV>
</div>

<script type="text/javascript">
HideAllNotFirst ();
</script>
</BODY>
</HTML>
Jul 23 '05 #6
SimonFx wrote:
An example you might wish to play with:

[...]

Or not.

Your suggesed code does not do what the OP asked, which is that the
div is hidden until its link is clicked on, whereupon it stays
displayed until another is clicked on.

It is also quite unreliable in Safari: HideAllNotFirst() does not
work at all.

And you could have added links to the div's in your <a> tags to make
the sans-JS version a little better.

Cheers, Fred.
Jul 23 '05 #7
SimonFx wrote:
An example you might wish to play with:

Fred Oz wrote: Or not.


Or so.

Maybe he can "play" with the example, because most of the material is
there. I'm sorry I did not write a complete, robust and fully tested
version on my time, unpaid.

Feel free to make additions or alterations.

I guess bitching about it is OK too, flameboy, this is usenet after all.
Jul 23 '05 #8
SimonFx wrote:
[...]
Maybe he can "play" with the example, because most of the material is
there. I'm sorry I did not write a complete, robust and fully tested
version on my time, unpaid.
I just don't see the point in offering a solution that doesn't do what
is asked when a serviceable one has already been offered.
Feel free to make additions or alterations.
There is a solution below that is based on a similar algorithm to
yours. It was actually written completely independently.

It could be improved by being added dynamically on each href that has a
matching div id when the page loads, but I think that's unnecessarily
complex though not too hard to add if required. It's been tested in
IE 6, Safari and Firefox, I don't have an environment to test
document.all or alternatives to document.getElementById().
I guess bitching about it is OK too, flameboy, this is usenet after all.


Hardly a flame, the OP is somewhat of a novice and I think it's
reasonable to offer advice that you weren't prepared to include.
Have fun, Fred.

<script type="text/javascript">
function showDiv(b,el){
var bRef = null;
if (document.getElementById) {
bRef = document.getElementById(b);
} else {
// Use the following if you can test it
// otherwise substitute something else
// bRef = document.all[b];
}
if(bRef.childNodes){
var z = bRef.childNodes;
for (var i=0;i<z.length; i++) {

// This will hide just the divs
// and show the one clicked on
if (z[i].nodeName =='DIV' && z[i].style) {
z[i].style.display = 'none';
if (z[i].id == el) z[i].style.display = '';
}
}
}
}
</script>
<style type="text/css">
..demo {width: 200px; height: 300px;}
</style>

<div id="d00">This is div 00<br>
<a href="#sdf" onclick="
showDiv('base','sdf');this.blur();return false;">sdf</a>
<a href="#abc" onclick="
showDiv('base','abc');this.blur();return false;">&nbsp;|&nbsp;abc</a>
<a href="#def" onclick="
showDiv('base','def');this.blur();return false;">&nbsp;|&nbsp;def</a>
<a href="#ghi" onclick="
showDiv('base','ghi');this.blur();return false;">&nbsp;|&nbsp;ghi</a>
</div>
<div id="base">
<div name="sdf" id="sdf" class="demo"
style="background-color: blue;">div sdf</div>
<div name="abc" id="abc" class="demo"
style="background-color: red;">div abc</div>
<div name="def" id="def" class="demo"
style="background-color: green;">div def</div>
<div name="ghi" id="ghi" class="demo"
style="background-color: pink;">div ghi</div>
</div>
<script type="text/javascript">
// This could be included in a body onload tag
showDiv('base','');
</script>
Jul 23 '05 #9
Randy, the approach I just described (the one of using object oriented
JS classes) is very effective from developer's point of view. If
someone wants to
learn more about this technique, they are welcome to our forums. I'm
sorry that you got the wrong impression; I do not see anything wrong
in inviting people to our forums. You do not have to go there if you
do not want to.

As far as HTML/script on the main page is concerned, I do not see
anything wrong with it. This site was created in IAB Studio, and pages
are created in its WYSIWYG editors; what you actually see in the
browser is HTML generated on the fly. Our approach is different what
the usual web site would use, but it's more productive in many ways.
We also use a lot of advanced JS techniques, if you are interested to
learn more about it, you are welcome to visit our site.

GregS
IAB Studio developer
www.worcsnet.com
www.iabstudio.com

Randy Webb <Hi************@aol.com> wrote in message news:<I_********************@comcast.com>...
sw**********@yahoo.com wrote:
The best approach would be to write a JS class, which would handle all
of these divs, given that you need it for 500 pages. The advantage is
that if you need to change anything, you would do it only in 1 class.
Here's what I'm talking about:

var handler = new JSScriptHandler ();
handler.addItem (document.getElementById ('id1'));
handler.addItem (document.getElementById ('gsg'));

handler.Start (); // This method would actually define all event
handlers, etc.

This is just an idea, not implementation. If you need more technical
info, ask this question in our forum at www.worcsnet.com. There is
actually an example of a similar control right on the home page ().


If the script and HTML code on the main page is indicative of the
answers given there, its a site better left alone.

But, is it the policy of worcsnet.com to solicit questions for its
forums from Usenet?

Jul 23 '05 #10
rf
GregS wrote:
As far as HTML/script on the main page is concerned, I do not see
anything wrong with it.


http://users.bigpond.net.au/rf/temp/worcsnet.jpg

--
Cheers
Richard.
Jul 23 '05 #11
GregS wrote:
Randy, the approach I just described (the one of using object oriented
JS classes) is very effective from developer's point of view. If
someone wants to learn more about this technique, they are welcome
to our forums. I'm sorry that you got the wrong impression; I do not
see anything wrong in inviting people to our forums. You do not have
to go there if you do not want to.

Fair enough. And I totally agree that object oriented classes are an
advantage. But when the document that they are presented in isn't valid
HTML, it makes trying to script it that much more difficult. That was my
only point.

As far as HTML/script on the main page is concerned, I do not see
anything wrong with it.


Load it in Mozilla, watch the loading bar. It hangs. Also, view the
screenshot that rf posted.

http://validator.w3.org/check?uri=ht...m%2FmainLayout

lists 20 errors to start with.

And please don't top-post.

--
Randy
comp.lang.javascript FAQ - http://jibbering.com/faq
Jul 23 '05 #12

"WindAndWaves" <ac****@ngaru.com> wrote in message
news:Hk******************@news.xtra.co.nz...
Hi Gurus

I have a page, which looks a bit like this:

The results can be view at http://www.sunnysideup.co.nz/clients...s/listing.html

Thank you all very, very much for your help
- Nicolaas
Jul 23 '05 #13
On Mon, 22 Nov 2004 23:43:16 -0500, Randy Webb wrote:
GregS wrote:
...If
someone wants to learn more about this technique, they are welcome
to our forums.

Thanks no. [1]
..when the document that they are presented in isn't valid
HTML, it makes trying to script it that much more difficult. That was my
only point.
As far as HTML/script on the main page is concerned, I do not see
anything wrong with it.

Were you looking at the responses to this?
<http://groups.google.com/gr*****************************************@postin g.google.com>

Or more generally, that the only time that IAB Studio got responses
to announcements, the replies were words to the effect of
'breaks my browser'.
<http://groups.google.com/groups?as_q=IAB%20Studio&as_ugroup=comp.lang.java* >
Load it in Mozilla, watch the loading bar. It hangs. Also, view the
screenshot that rf posted.

http://validator.w3.org/check?uri=ht...m%2FmainLayout

lists 20 errors to start with.


[1] I think the developers of IAB Studio need to spend a lot more
time *lurking* and *asking questions* on c.l.js, c.i.w.a.html,
c.i.w.a.stylesheets and c.i.w.a.site-design before they go offering
advice to others, especially since their software is churning out pages.

--
Andrew Thompson
http://www.PhySci.org/codes/ Web & IT Help
http://www.PhySci.org/ Open-source software suite
http://www.1point1C.org/ Science & Technology
http://www.LensEscapes.com/ Images that escape the mundane
Jul 23 '05 #14
Ah! So looking at your code, what you are saying is that Safari treats
childNodes strictly as an array - the "for (foo in childNodes)" doesn't
work.

Tested Safari, and this is indeed the case. How interesting.

You said "don't have an environment to test document.all" but you also
said you tested with IE 6 - isn't that the document.all dom

Yeah, so now I am sitting about relaxed, you have made me feel guilty so
I have updated the damed thing. Even tho "WindAndWaves" has completed
his page :)

===

<HTML>
<HEAD>
<TITLE>Test</TITLE>
<script type="text/javascript">
<!--
if(!document.getElementById) {
document.getElementById = document.all ? function(i) {return
document.all[i];} : function() {return null;};
}

function HideAllExcept (thisDiv){
var obj = document.getElementById('uberDIV');
for (var o=0; o<obj.childNodes.length; o++){
if (obj.childNodes[o].nodeName == 'DIV' && obj.childNodes[o].style) {
if (obj.childNodes[o].id == thisDiv)
{obj.childNodes[o].style.display = '';}
else {obj.childNodes[o].style.display = 'none';}
}
}
return false;
}

-->
</script>

</HEAD>
<BODY onLoad="HideAllExcept('item_id1');">
<A HREF="#id1" onClick="return HideAllExcept('item_id1');">id1</a>
<A HREF="#gsd" onClick="return HideAllExcept('item_gsd');">gsd</a>
<A HREF="#ewd" onClick="return HideAllExcept('item_ewd');">ewd</a>
<A HREF="#fac" onClick="return HideAllExcept('item_fac');">fac</a>
<A HREF="#act" onClick="return HideAllExcept('item_act');">act</a>

<div ID="uberDIV">
<div ID="item_id1">By my stuff</DIV>
<div ID="item_gsd">It's really good</DIV>
<div ID="item_ewd">It has features</DIV>
<div ID="item_fac">Alternatives suck</DIV>
<div ID="item_act">Send money now</DIV>
</div>

</BODY>
</HTML>
Jul 23 '05 #15
On Tue, 23 Nov 2004 11:18:31 +0000, SimonFx <ne**********@sapm.yahoo.com>
wrote:
Ah! So looking at your code, what you are saying is that Safari treats
childNodes strictly as an array - the "for (foo in childNodes)" doesn't
work.
I don't see any reason why it should, really. The DOM Specification states
how an ECMAScript program can access the contents of a NodeList object:

Object NodeList

The NodeList object has the following properties:
length
This read-only property is of type Number.

The NodeList object has the following methods:
item(index)
This method returns a Node object.
The index parameter is of type Number.

Note: This object can also be dereferenced using square bracket
notation (e.g. obj[1]). Dereferencing with an integer index
is equivalent to invoking the item method with that index.

Using those features is guaranteed to work[1], whereas using for..in
relies on the host making each element in the collection enumerable, which
it is under no obligation to do.

[snip]
You said "don't have an environment to test document.all" but you also
said you tested with IE 6 - isn't that the document.all dom
Yes, but IE would take the getElementById code path if that is presented
first (and it should be). Of course, you could force the document.all
route for testing purposes if you were so inclined. Normally, I do that by
changing

if(document.getElementById) {

(or something similar) to

if(/*document.getElementById*/ false) {

That is, temporarily comment out the gEBI test and replace it with
something will always fail. It's quick and easy to restore.

[snip]
function HideAllExcept (thisDiv){
var obj = document.getElementById('uberDIV');
for (var o=0; o<obj.childNodes.length; o++){
if (obj.childNodes[o].nodeName == 'DIV'
&& obj.childNodes[o].style) {
if (obj.childNodes[o].id == thisDiv)
{obj.childNodes[o].style.display = '';}
else {obj.childNodes[o].style.display = 'none';}
}
}
return false;
}


You could simplify that somewhat by making the user agent find the DIVs
for you:

function setStyle(obj, prop, value) {
if(obj && (obj = obj.style) {obj[prop] = value;}
return !!obj;
}

function hideAllExcept(thisDiv) {
var obj = document.getElementById('uberDIV'), divs;
if(obj && obj.getElementsByTagName) {
divs = obj.getElementsByTagName('DIV');
for(var i = 0, n = divs.length; i < n; ++i) {
setStyle(
divs[i],
'display',
(thisDiv == divs[i].id) ? '' : 'none'
);
}
}
}

Like document.getElementById, Element.getElementsByTagName can be
simulated for old IE versions[2]:

var getElementsByTagName = function(o, n) {
return (getElementsByTagName = o.getElementsByTagName ?
function(o, n) {return o.getElementsByTagName(n);}
: (o.all && o.all.tags) ?
function(o, n) {
o = o.all; return (('*' == n) ? o : o.tags(n)) || [];
}
: function() {return [];})(o, n);
};

This has a slightly different signature from the DOM-specified version.
The first argument is the element getElementsByTagName should be called
from. The second argument is the tag name to match (or an asterisk (*) for
all elements).

The hideAllExcept function above would be changed to

function hideAllExcept(thisDiv) {
var obj = document.getElementById('uberDIV'), divs;
/* Change starts here. */
if(obj) {
divs = getElementsByTagName(obj, 'DIV');
/* Change ends here. */
for(var i = 0, n = divs.length; i < n; ++i) {
setStyle(
divs[i],
'display',
(thisDiv == divs[i].id) ? '' : 'none'
);
}
}
}

with this addition.

Enjoy,
Mike
[1] Personally, I'd use square brackets. I'm sure that a browser I was
testing with once (I think an earlier Opera version) didn't provide an
item method for collections.

[2] This code assumes that getElementsByTagName would be implemented on
all elements, and there are no special cases, such as the method existing
on the document object, but no others. If special cases are possible, I've
included a safer, but less-than-optimal, implementation below:

function getElementsByTagName(o, n) {
var r = [];
if(o.getElementsByTagName) {
r = o.getElementsByTagName(n);
} else if((o = o.all) && o.tags) {
r = (('*' == n) ? o : o.tags(n)) || [];
}
return r;
}

If the special cases are specific, it may be possible to modify the
previous version to perform preliminary tests, rather than assuming gEBTN
on one element means gEBTN on all elements.

--
Michael Winter
Replace ".invalid" with ".uk" to reply by e-mail.
Jul 23 '05 #16
Michael Winter wrote:
On Tue, 23 Nov 2004 11:18:31 +0000, SimonFx
<ne**********@sapm.yahoo.com> wrote:
Ah!

[...]

Our contrary hearts, having driven us into a coding frenzy, are
quenched forthwith. For Winter stands astride us all like a colossus,
sweeping the earth with the depth and breadth of his posts so that none
may remain in ignorance.

I am blown away ...again...

Hail Mike - Fred.
Jul 23 '05 #17
On Wed, 24 Nov 2004 06:46:50 +1000, Fred Oz <oz****@iinet.net.auau> wrote:

[snip]
Our contrary hearts, having driven us into a coding frenzy, are
quenched forthwith. For Winter stands astride us all like a
colossus, sweeping the earth with the depth and breadth of his
posts so that none may remain in ignorance.
LMFAO!
I am blown away ...again...
I doubt that, somehow. :P
Hail Mike - Fred.


Stop taking the piss! Save praise for the truly gifted around here. :)

Mike

--
Michael Winter
Replace ".invalid" with ".uk" to reply by e-mail.
Jul 23 '05 #18
GregS wrote:
Randy, the approach I just described (the one of using object
oriented JS classes) is very effective from developer's point
of view.
It certainly can be, though it can also be over the top if the context
of its application is sufficiently simple.
If someone wants to learn more about this technique,
they are welcome to our forums.
Maybe they are, but anyone reading the suggestion has already discovered
comp.lang.javascript, where they may get the attention of quite a number
of contributors, some of whom specialise in OO javascript.
I'm sorry that you got the wrong impression; I do
not see anything wrong in inviting people to our forums.
You do not have to go there if you do not want to.
That question is probably best addressed by considering what would be
best for the OP. A small private forum with maybe a couple of (more or
less) knowledgeable contributors or a public newsgroup where any
responses given will be subject to critical peer-review, and a diversity
of opinions expressed and debated? If the OP is happy to comply with
Usenet conventions the latter is likely to be the more productive
activity.
As far as HTML/script on the main page is concerned,
I do not see anything wrong with it.
You don't? You have mark-up like:-

| <P> </P>
| <P> </P>
| <P> </P>
| <P> </P>
| <P> </P>
| <BLOCKQUOTE dir=ltr style="MARGIN-RIGHT: 0px">
| <BLOCKQUOTE dir=ltr style="MARGIN-RIGHT: 0px">
| <BLOCKQUOTE dir=ltr style="MARGIN-RIGHT: 0px">
| <BLOCKQUOTE dir=ltr style="MARGIN-RIGHT: 0px">
| <BLOCKQUOTE dir=ltr style="MARGIN-RIGHT: 0px">
| <P align=left> </P></BLOCKQUOTE></BLOCKQUOTE>
| </BLOCKQUOTE></BLOCKQUOTE></BLOCKQUOTE>
| <P> </P>
| <P> </P>
| <P> </P>
| <P> </P>

- and you don't see anything wrong with that? And why does a page that
imports no less than 14 stylesheets need so many inline style
attributes?
This site was created in IAB Studio, and pages
are created in its WYSIWYG editors; what you actually
see in the browser is HTML generated on the fly.
And doesn't it take an age to load? (Not surprising given the mark-up
bloat, but it also feels like the image optimisation leaves a lot to be
desired.)
Our approach is different what the usual web site would
use, but it's more productive in many ways.
We also use a lot of advanced JS techniques, if you are interested
to learn more about it, you are welcome to visit our site.
"advanced JS techniques"; not an easy claim to quantify. One person's
advanced technique is old-hat to another, and a bad idea to a third. A
few months ago I looked at a javascript book that featured the work
"advanced" in its title, and found a collection of techniques so bad
that many would qualify as dangerous. I recall Jim Ley suggesting that
the most advanced javascript in the world was to be found in posts to
comp.lang.javascript, and I find that a reasonable assertion when I
monitor javascript blogs and find individuals enthusing about 'new'
techniques that have been being posted to this group on and off for a
couple of years. That is just a consequence of the group having a
reasonable core of enthusiastic contributors interested in trying out
new ideas (newly invented or just new to them) and doing so under the
critical scrutiny of their fellows. (the bad ideas, and the poor
implementations, get pointed out very quickly)

Still, without getting into how advance any particular technique may be,
the code on <URL: http://www.worcsnet.com > is not without relevance in
this context. Taking just one file at random:-

| <SCRIPT LANGUAGE="JavaScript1.2"
| SRC="/js/Common/HttpRequest.js"></SCRIPT>

-, and disregarding the invalid HTML 4.01 markup with its deprecated
(and inadvisable) language attribute, We find the script:-

<quote>
var QueryType = { SqlQuery:0};
var DataRequestType = {
SQL : 0,
/*Regular SQL Query*/
Search : 1,
/*Search query; SearchClass tells the Java class name, the rest
is search-specific*/
Lookup : 2,
Update : 3,
Validate:4,
UDCLayout : 5,
FormUpdate : 6,
DewUpdate:7,
PageUpdate : 8,
PageContentUpdate : 9,
ReloadLookup : 10
};

function HttpRequest (id, docObj) {
this.id = id;
this.docObj=docObj;
if(typeof (this.constructor.prototype.PrototypeFinishedHttpR equest)
== 'undefined'){
this.constructor.prototype.prepareDataRequest=prep areDataRequest;
this.constructor.prototype.PrototypeFinishedHttpRe quest=true;
};
function prepareFormDOM(targetFrameId, docObj, id, action,
method, params){
var formObj = docObj.document.createElement ("FORM");
docObj.document.body.appendChild (formObj);
formObj.id = id;
formObj.action = action;
formObj.method = method;
formObj.target = "_self";
for (var i = 0; i < params.length; i ++){
for (j in params [i]){
var paramName = j;
var paramValue = params [i][j];
var inputDef = "INPUT";
var inputHidden = docObj.document.createElement(inputDef);
inputHidden.setAttribute ("name", paramName);
inputHidden.setAttribute ("type", "hidden");
inputHidden.setAttribute ("value", paramValue);
formObj.appendChild (inputHidden);
}
}
return formObj;
};
function prepareDataRequest(targetFrameId, queryType,
requestType, params){
var returnObj = null;
switch (queryType){
case QueryType.SqlQuery:
params.push ({QT:"SQL"});
break;
}
var requestHost = GetIABBaseURL() + '/DataRequestHandler';
switch (requestType){
case DataRequestType.SQL:
params.push ({RT:"SQL"});
break;
case DataRequestType.Search:
params.push ({RT:"Search"});
break;
case DataRequestType.Lookup:
params.push ({RT:"Lookup"});
break;
case DataRequestType.Update:
params.push ({RT:"Update"});
break;
case DataRequestType.Validate:
params.push ({RT:"Validate"});
break;
case DataRequestType.UDCLayout:
params.push ({RT:"UDCLayout"});
break;
case DataRequestType.FormUpdate:
params.push ({RT:"FormUpdate"});
break;
case DataRequestType.DewUpdate:
params.push ({RT:"DewUpdate"});
break;
case DataRequestType.PageUpdate:
params.push ({RT:"PageUpdate"});
break;
case DataRequestType.PageContentUpdate:
params.push ({RT:"PageContentUpdate"});
break;
case DataRequestType.ReloadLookup:
params.push ({RT:"reloadLookup"});
break;
}
returnObj = prepareFormDOM (targetFrameId, this.docObj, this.id,
requestHost, "POST", params);
return returnObj;
};
}
</quote>

Where apparent misconceptions about the nature of javascript, its OO
application, and a disregard for OO general principles, has resulted in
an implementation that is approaching being perverse.

The mistake of making the - j - variable in - prepareFormDOM - global is
obvious and easily rectified. The main faults lie in the design of the -
HttpRequest - 'class'. First the data objects - QueryType - and -
DataRequestType - are clearly bound with the 'class' in their
employment, but both are created as global variables. OO design would
have suggested both be contained by the 'class'; so static, preferably
private static as they should not be needed outside of the 'class' and
its instances, but public static would have been satisfactory (and
simpler to implement with javascript).

The - HttpRequest - constructor features two inner function definitions
(both followed by empty statements for some unknown reason), neither
make any use of the fact that they are inner functions, and indeed only
the function object instances created during the instantiation of the
first - HttpRequest - object are ever used. The function objects created
during subsequent executions of the - HttpRequest - do no more than
consume clock cycles being created and memory space while they are
awaiting garbage collection.

The first instance of the - prepareDataRequest - function created will
be assigned to the prototype of the - HttpRequest - function, but the
test for that assignment is repeated on all subsequent executions of -
HttpRequest -. This is certainly a case where the normal practice of
assigning a function reference to a property of the function's prototype
would be simpler, and more efficient.

Of course it is the closure formed with the instantiation of the first -
HttpRequest -, by assigning the - prepareDataRequest - function to the
constructor's prototype, that allows the - prepareDataRequest - function
to access the first instance of the - prepareFormDOM -, but that
particular closure (with its consequential needless overheads on
subsequent - HttpRequest - object instantiations) is not the only means
of making that function available. Indeed it is questionable whether it
makes any sense for - prepareFormDOM - to be a separate function as it
is always called form - prepareDataRequest - and unavailable to any
other code. But the fact that - prepareFormDOM - is only interested in
its parameters (has no interest in - HttpRequest - object instances,
even the first instance with which it is bound by the closure formed)
suggest that - prepareFormDOM - should be static in addition to the two
data structures (or at least more explicitly static).

So one implementation pattern that provides all of the encapsulation
called for the OO, and avoids the inefficiencies in the original might
go:-

var HttpRequest = (fucntion(){
var QueryType = { SqlQuery:0};
var DataRequestType = {
SQL : 0,
... //etc.
ReloadLookup : 10
};
function prepareFormDOM(targetFrameId, docObj, id, action,
method, params){
var formObj = docObj.document.createElement ("FORM");
... //etc.
return formObj;
}
function constr(id, docObj){
this.id = id;
this.docObj=docObj;
}
constr.prototype.prepareDataRequest = function(targetFrameId,
queryType, requestType, params){
switch (queryType){
case QueryType.SqlQuery:
params.push ({QT:"SQL"});
break;
}
... //etc.
return prepareFormDOM(targetFrameId, this.docObj, this.id,
requestHost, "POST", params);
};
return constr;
})();

So where would be the best place to go if you wanted to understand how
and why that formulation works?

<snip> Randy Webb <Hi************@aol.com> wrote in message

<snip>

Please do not top-post to comp.lang.javascript.

Richard.
Jul 23 '05 #19
Andrew Thompson <Se********@www.invalid> wrote in message news:<1w******************************@40tude.net> ...
On Mon, 22 Nov 2004 23:43:16 -0500, Randy Webb wrote:
GregS wrote:
...If
someone wants to learn more about this technique, they are welcome
to our forums.


Thanks no. [1]
..when the document that they are presented in isn't valid
HTML, it makes trying to script it that much more difficult. That was my
only point.
As far as HTML/script on the main page is concerned, I do not see
anything wrong with it.


Were you looking at the responses to this?
<http://groups.google.com/gr*****************************************@postin g.google.com>

Or more generally, that the only time that IAB Studio got responses
to announcements, the replies were words to the effect of
'breaks my browser'.
<http://groups.google.com/groups?as_q=IAB%20Studio&as_ugroup=comp.lang.java* >
Load it in Mozilla, watch the loading bar. It hangs. Also, view the
screenshot that rf posted.

http://validator.w3.org/check?uri=ht...m%2FmainLayout

lists 20 errors to start with.


[1] I think the developers of IAB Studio need to spend a lot more
time *lurking* and *asking questions* on c.l.js, c.i.w.a.html,
c.i.w.a.stylesheets and c.i.w.a.site-design before they go offering
advice to others, especially since their software is churning out pages.

Andrew Thompson, I'm one of the developers of IAB Studio. I do not
think you ever used IAB Studio, and your remarks seem to be quite
rude, offending and pointless; I do not see any reason for that. It's
quite strange to me that you post such comments without even knowing
what IAB Studio is. Given this, your advice is just not credible.

GregS
IAB Studio Developer
www.worcsnet.com
www.iabstudio.com
Jul 23 '05 #20
Randy Webb <Hi************@aol.com> wrote in message news:<wv********************@comcast.com>...
GregS wrote:
Randy, the approach I just described (the one of using object oriented
JS classes) is very effective from developer's point of view. If
someone wants to learn more about this technique, they are welcome
to our forums. I'm sorry that you got the wrong impression; I do not
see anything wrong in inviting people to our forums. You do not have
to go there if you do not want to.

Fair enough. And I totally agree that object oriented classes are an
advantage. But when the document that they are presented in isn't valid
HTML, it makes trying to script it that much more difficult. That was my
only point.

As far as HTML/script on the main page is concerned, I do not see
anything wrong with it.


Load it in Mozilla, watch the loading bar. It hangs. Also, view the
screenshot that rf posted.

http://validator.w3.org/check?uri=ht...m%2FmainLayout

lists 20 errors to start with.

And please don't top-post.


Randy, thanks you for your comments.

I think that not always "incorrect" HTML is incorrect. For example,
this parser of yours seems to find error even if there are no errors.
For example:

Line 10, column 62: general entity "pageNum" not defined and no
default entity

....lling="auto" src="main?AC=showPage&pageNum=10003"

This is a perfectly correct URL. If you look at the source, you will
see that it is a simple frameset. I think this parser is not the most
trustworthy.

I'm sure that you know that sometimes developers do things like that:

<DIV myattr1="blablabal" myattr2="blablabla" >, which makes perfect
sense in the context of your web application, but is not "perfect"
HTML. Or you can use custom tags, which are not "perfect" HTML, but it
still does not make it wrong - again, in the context of your
application.

The loading bar is actually a FF/NN/Mozilla bug. If you create many
dynamic iframes, then sometimes FF does not stop 'loading' the page,
although it's already been loaded. IE handles this situation a lot
better.

And as for the picture rf posted - yes, if you change default font
sizes in FireFox (like, setting the minimum font size), that's exactly
how the page will look. But half of all web sites will look the same;
I'm not sure what point RF was trying to make. It may be more of a
design issue - if I say style="font-size:12", it means I want it this
way.

And I'd like to mention that developing web applications (actually RIA
apps) in IAB Studio is a bit different than in other HTML editors; it
has very little to do with scripting HTML (or HTML in general). HTML
in IAB pages serves more like data for the runtime engine, which
creates actual controls... So while I understand your concern about
invalid HTML, it is not really applicable to IAB Studio. Anyway,
thanks for your remarks.

GregS
IAB Studio developer
www.worcsnet.com
www.iabstudio.com
Jul 23 '05 #21
GregS wrote:
Andrew Thompson <Se********@www.invalid> wrote in message news:<1w******************************@40tude.net> ...
On Mon, 22 Nov 2004 23:43:16 -0500, Randy Webb wrote:
<--snip-->
Load it in Mozilla, watch the loading bar. It hangs. Also, view the
screenshot that rf posted.

http://validator.w3.org/check?uri=ht...m%2FmainLayout

lists 20 errors to start with.


[1] I think the developers of IAB Studio need to spend a lot more
time *lurking* and *asking questions* on c.l.js, c.i.w.a.html,
c.i.w.a.stylesheets and c.i.w.a.site-design before they go offering
advice to others, especially since their software is churning out pages.


Andrew Thompson, I'm one of the developers of IAB Studio. I do not
think you ever used IAB Studio, and your remarks seem to be quite
rude, offending and pointless; I do not see any reason for that. It's
quite strange to me that you post such comments without even knowing
what IAB Studio is. Given this, your advice is just not credible.


One does not have to use a product to see the outcome of that product.

I have never used DreamWeaver nor Frontpage but I can tell you, from
experience of seeing its code, that it does *not* produce good, quality
code. It may well be easy to use for the developer but for creating
quality code, they both suck.

But given that you are defending your own product without any more than
a rant at one who posts contradictions to you, your advice/comments are
just not credible.
--
Randy
comp.lang.javascript FAQ - http://jibbering.com/faq
Jul 23 '05 #22
GregS wrote:
Randy Webb <Hi************@aol.com> wrote in message news:<wv********************@comcast.com>...
GregS wrote:
<--snip-->
As far as HTML/script on the main page is concerned, I do not see
anything wrong with it.
Load it in Mozilla, watch the loading bar. It hangs. Also, view the
screenshot that rf posted.

http://validator.w3.org/check?uri=ht...m%2FmainLayout

lists 20 errors to start with.

And please don't top-post.

Randy, thanks you for your comments.

I think that not always "incorrect" HTML is incorrect. For example,
this parser of yours seems to find error even if there are no errors.
For example:

Line 10, column 62: general entity "pageNum" not defined and no
default entity

....lling="auto" src="main?AC=showPage&pageNum=10003"


The problem comes from error 1, which is always the first error to fix.
The lack of a DTD causes the validator to guess. It guessed HTML4.01
Transitional, when if they Frameset DTD had been present, it would have
parsed it differently.
This is a perfectly correct URL. If you look at the source, you will
see that it is a simple frameset. I think this parser is not the most
trustworthy.
See Above.
I'm sure that you know that sometimes developers do things like that:

<DIV myattr1="blablabal" myattr2="blablabla" >, which makes perfect
sense in the context of your web application, but is not "perfect"
HTML. Or you can use custom tags, which are not "perfect" HTML, but it
still does not make it wrong - again, in the context of your
application.
If I want my own custom tags, I don't use HTML. But, I do use my own
tags, and my own attributes in PHP code. But I also have it remove them
before its sent to the browser. They are there for my own search/replace
routines so I have them removed so that what is sent to the browser is
valid HTML. Then, if it doesn't render properly in the browser, then I
know its not my code so I know where to look next.
The loading bar is actually a FF/NN/Mozilla bug. If you create many
dynamic iframes, then sometimes FF does not stop 'loading' the page,
although it's already been loaded. IE handles this situation a lot
better.
Personally, I wouldn't use IE as a base reference for quality of a page.

Internet Explorer is the most lax environment on the web to try to
script in. Just because something "works" in IE doesn't make it good
code, it just means a crappy browser will execute it:

myID.property

IE handles that a lot better than any other browser. But, to make it
work in any browser that supports it, use
document.getElementById('myID').property and it works in any of them.

I also turn a bad eye to any site that tells me:

"Inet Application Builder requires Internet Explorer 5.5+ or Netscape
v6.2+."

That alone indicates browser detection based on userAgent strings and
they are about as predictable as predicting the farts on an island of
bean eaters.
And as for the picture rf posted - yes, if you change default font
sizes in FireFox (like, setting the minimum font size), that's exactly
how the page will look. But half of all web sites will look the same;
I'm not sure what point RF was trying to make. It may be more of a
design issue - if I say style="font-size:12", it means I want it this
way.
And if I tell my browser "I want larger text", then thats the way I want
it. In the end, its the user who is in control of the browser, not the
page author.

In my IE6, with my chosen settings, I get much the same image/page that
rf got. Except that I don't have colors. I have the font sizes disabled
because I sit about 3 feet from the monitor and want larger font sizes.

http://allmyfaqs.com/faq.pl?AnySizeDesign

And I'd like to mention that developing web applications (actually RIA
apps) in IAB Studio is a bit different than in other HTML editors; it
has very little to do with scripting HTML (or HTML in general). HTML
in IAB pages serves more like data for the runtime engine, which
creates actual controls... So while I understand your concern about
invalid HTML, it is not really applicable to IAB Studio. Anyway,
thanks for your remarks.


Welcome.

--
Randy
comp.lang.javascript FAQ - http://jibbering.com/faq
Jul 23 '05 #23
On Tue, 23 Nov 2004 23:12:17 -0500, Randy Webb <Hi************@aol.com>
wrote:
GregS wrote:


[snip]
Line 10, column 62: general entity "pageNum" not defined and no
default entity
....lling="auto" src="main?AC=showPage&pageNum=10003"


The problem comes from error 1, which is always the first error to fix.
The lack of a DTD causes the validator to guess. It guessed HTML4.01
Transitional, when if they Frameset DTD had been present, it would have
parsed it differently.


The error would still remain. The ampersand (&), as you know, begins a
character reference. The validator complains because &pageNum; [1] is not
a valid reference in any DTD (unless you wrote your own).

As character references can occur in attribute values, literal ampersands
should be encoded with the &amp; character reference.

This is explained in the previous error, in both the error message itself
and the link, "Ampersands in URLs".

Mike
[1] The terminating semicolon isn't actually necessary according to SGML
parsing rules. I'm not sure what the specifics of those rules are, but I
expect that non-alphanumeric characters can't be part of a reference.

--
Michael Winter
Replace ".invalid" with ".uk" to reply by e-mail.
Jul 23 '05 #24
Randy Webb <Hi************@aol.com> wrote in message news:<5P********************@comcast.com>...


In my IE6, with my chosen settings, I get much the same image/page that
rf got. Except that I don't have colors. I have the font sizes disabled
because I sit about 3 feet from the monitor and want larger font sizes.


you are right and the site should honor this kind of setup
Jul 23 '05 #25
"Richard Cornford" <Ri*****@litotes.demon.co.uk> wrote in message news:<co*******************@news.demon.co.uk>...
"advanced JS techniques"; not an easy claim to quantify. One person's
advanced technique is old-hat to another, and a bad idea to a third. A Agree. I guess the same goes for OO design.
HttpRequest - 'class'. First the data objects - QueryType - and -
DataRequestType - are clearly bound with the 'class' in their
employment, but both are created as global variables. OO design would Wrong assumtion.These objects are used as enumerations.They have
nothing to do with classes. Yes they have to be global because they
are used in multiple pages.

In fact, this wrong assumtion makes your code not usable at all.
So one implementation pattern that provides all of the encapsulation
called for the OO, and avoids the inefficiencies in the original might
go:-
var HttpRequest = (fucntion(){
var QueryType = { SqlQuery:0};
var DataRequestType = {
SQL : 0,
... //etc. Wrong again. QueryType and DataRequestType are supposed
to be global. See Above.

neither make any use of the fact that they are inner functions, a
They do. It is a lot more readable to me than
using constr.prototype.prepareDataRequest = function(targetFrameId

except that imho the original code seems to be simpler to read and
understand.
Apart from that, it does the same thing as your suggestion, and it can
in fact be made abit more efficient than yours (see below)
Indeed it is questionable whether it makes any sensefor - prepareFormDOM - to > be a separate function as it
is always called form - prepareDataRequest - and unavailable to any other code.


Yes it does. This function does one thing - creates a
dynamic form, and it makes a lot of sense to have it
as a separate function.

Overall, I do not really see any significant changes
from the original code except for a couple very
minor changes. Also your changes are just incorrect given that you
assumed things, which are not true in this particular web application.
The original code can be optimized a bit, provided that, instead of

if(typeof
(this.constructor.prototype.PrototypeFinishedHttpR equest)

== 'undefined'){

this.constructor.prototype.prepareDataRequest=prep areDataRequest;

this.constructor.prototype.PrototypeFinishedHttpRe quest=true;
};

function prepareDataRequest

I can have

if(typeof
(this.constructor.prototype.PrototypeFinishedHttpR equest)

== 'undefined'){

this.constructor.prototype.prepareDataRequest=prep areDataRequest;

this.constructor.prototype.PrototypeFinishedHttpRe quest=true;

function prepareDataRequest (){
}

};

So that indeed the function object will be created
only once, no matter how many objects you create.
Jul 23 '05 #26
GregS wrote:
Richard Cornford wrote: <snip>
HttpRequest - 'class'. First the data objects - QueryType -
and - DataRequestType - are clearly bound with the 'class'
in their employment, but both are created as global variables.
OO design would

Wrong assumtion.These objects are used as enumerations.They
have nothing to do with classes. Yes they have to be global
because they are used in multiple pages.


Fair enough, if you are using them in multiple classes then they will
need to be global.
In fact, this wrong assumtion makes your code not usable
at all.
You don't see how to correct that then?
So one implementation pattern that provides all of the encapsulation
called for the OO, and avoids the inefficiencies in the original
might
go:-
var HttpRequest = (fucntion(){
var QueryType = { SqlQuery:0};
var DataRequestType = {
SQL : 0,
... //etc.

Wrong again.


Surly not 'again', as these are the same objects as mentioned above.
QueryType and DataRequestType are supposed
to be global. See Above.
So bump them up a scope, nothing else needs to change.
neither make any use of the fact that they are inner
functions, a


They do.


No they don't.
It is a lot more readable to me than
using constr.prototype.prepareDataRequest =
function(targetFrameId

except that imho the original code seems to be
simpler to read and understand.
Maybe, code is certainly easier to understand when you are familiar with
javascript as a language.
Apart from that, it does the same thing as your suggestion,
and it can in fact be made abit more efficient than yours
(see below)
I think you will find that it cannot be more efficient, you might find
an alternative with equivalent efficiency but your original was very
poor in that regard, and the following suggestion is not going to help
that.

<snip> The original code can be optimized a bit, provided that,
instead of

if(typeof
(this.constructor.prototype.PrototypeFinishedHttpR equest)
== 'undefined'){

this.constructor.prototype.prepareDataRequest=prep areDataRequest;

this.constructor.prototype.PrototypeFinishedHttpRe quest=true;
};

function prepareDataRequest

I can have

if(typeof
(this.constructor.prototype.PrototypeFinishedHttpR equest)
== 'undefined'){

this.constructor.prototype.prepareDataRequest=prep areDataRequest;

this.constructor.prototype.PrototypeFinishedHttpRe quest=true;

function prepareDataRequest (){
}

};

So that indeed the function object will be created
only once, no matter how many objects you create.


So what do you imagine that will do? A conditional function declaration?
There is no such thing in javascript. Indeed the ECMA 262 (3rd edition)
production rules forbid a function declaration from appearing within a
block statement, which leaves the only possible interpretation of the
code as a function expression with the optional identifier, and that
expression would be evaluated after the assignment so even if ECMA 262
allowed the optional identifier to appear in the containing scope (which
it does not [1]) the preceding assignment would still not have assigned
a reference to a function object.

There are numerous faulty implementations that disregard the syntax
error of placing a function declaration within a block statement, but
they still follow the normal variable instantiation procedure upon
entering an execution context so the declarations are not conditional
and so the corresponding function objects are still going to be created
with each and every object instantiation when only the first created
will ever be used.

Richard.

[1] The Gecko bug of leaking the identifiers of function expressions
with optional identifiers into the containing scope can give the
illusion of conditional function declarations, but that is not what is
really happening, and relying on an implementation bug in one
environment is not a route to cross-browser code.
Jul 23 '05 #27
"Richard Cornford" <Ri*****@litotes.demon.co.uk> wrote in message news:<co*******************@news.demon.co.uk>...
GregS wrote:
Richard Cornford wrote: <snip>
There is no such thing in javascript. Indeed the ECMA 262 (3rd edition)
production rules forbid a function declaration from appearing within a
block statement,

Probably you are referring to this document:
http://www.ecma-international.org/pu...T/Ecma-262.pdf
Could you point out which paragraph prohibits that?
[1] The Gecko bug of leaking the identifiers of function expressions
with optional identifiers into the containing scope can give the
illusion of conditional function declarations, but that is not what is
really happening, and relying on an implementation bug in one
environment is not a route to cross-browser code.

Well, the following code works fine in IE, Netscape, Mozilla, FireFox
and Opera.
Do they all have the same bug? I've read that Opera/FF/etc developers
said they follow the standards. So if this code works fine in all
these browsers - does it make it valid JS code? I guess so.
<SCRIPT>

function Customer (id, startValue){

this.id=id;
this.startValue=startValue || 1000;

if(typeof (this.constructor.prototype.a1) =='undefined'){

//get customer id
function getId (){
return this.id;
};

//calculate something
function calc (){
return this.startValue * 100;
};

this.constructor.prototype.getId=getId;
this.constructor.prototype.calc=calc;
this.constructor.prototype.a1=true;

//change the id for the first object being created
this.id = "Generated ID. Will it change for all objects or
for the first only?"

alert ('We will only see this alert once.');

};
};

var aa = new Customer ('Customer 1', 100);
alert ('First Customer Created');

var aa1 = new Customer ('Customer 2', 200);
alert ('Second Customer Created');

var aa2 = new Customer ('Customer 3');
alert ('Third Customer Created');

alert ('id for object aa:' + aa.getId () + " Calc:" + aa.calc ());
alert ('id for object aa1:' + aa1.getId () + " Calc:" + aa1.calc ());
alert ('id for object aa2:' + aa2.getId () + " Calc:" + aa2.calc ());

</SCRIPT>


Granted, your approach may (or may not be) faster. But I guess the
only way to compare which code is more efficient is to actually run
it.
So can you post your own version of the Customer class (complete
implementation, so that I can just copy and paste it), let's say
Customer1? Then we can run a simple test script, something like that
(simply create 100000 Customer objects):

var t1 = new Date ().getTime ();
for (var i = 0; i < 100000; i ++){
new Customer (); //my version
// or new Customer1 (); //your version
};
var t2 = new Date ().getTime ();

alert (t2 - t1)


And it should tell, which approach is more efficient.
Greg
Jul 23 '05 #28
GregS wrote:
Richard Cornford wrote: <snip>
There is no such thing in javascript. Indeed the ECMA 262
(3rd edition) production rules forbid a function declaration
from appearing within a block statement,

Probably you are referring to this document:
... /Ecma-262.pdf
Could you point out which paragraph prohibits that?


Section 14: the production rules for SourceElement, Section 13: the
production rules for FunctionDeclaration and FunctionBody, and Section
12.1: Block statements and StatementList; seem most pertinent.
[1] The Gecko bug of leaking the identifiers of function
expressions with optional identifiers into the containing
scope can give the illusion of conditional function
declarations, but that is not what is really happening, and
relying on an implementation bug in one environment is
not a route to cross-browser code.

Well, the following code works fine in IE, Netscape,
Mozilla, FireFox and Opera.
More functions rather than works. But their behaviour is neither
identical nor consistent, and none of them are actually doing what you
seem to be assuming them to be doing.
Do they all have the same bug?
The three execution environments named all have bugs in this area, but
they don't have the same bug.
I've read that Opera/FF/etc developers said they follow
the standards. So if this code works fine in all these
browsers - does it make it valid JS code? I guess so.
Mozilla/Gecko is often cited as the most standards compliant browser,
but that doesn't mean that what Mozilla/Gecko does defines the standards
it attempts to implement; that type of thinking is the wrong way around.
<SCRIPT>

function Customer (id, startValue){

this.id=id;
this.startValue=startValue || 1000;

if(typeof (this.constructor.prototype.a1) =='undefined'){

//get customer id
function getId (){
return this.id;
};

//calculate something
function calc (){
return this.startValue * 100;
};

this.constructor.prototype.getId=getId;
this.constructor.prototype.calc=calc;
this.constructor.prototype.a1=true;

//change the id for the first object being created
this.id = "Generated ID. Will it change for all"+
" objects or for the first only?"

alert ('We will only see this alert once.');
};
If you want to see Opera and IE not doing what you seem think they are
doing try adding this alert at this point:-

alert ('typeof calc = '+(typeof calc));

- and while Mozilla/Firefox may seem to be doing conditional function
declarations it is in fact exhibiting its bug in the handling of the
optional identifiers on FunctionExpressions.
}; <snip> Granted, your approach may (or may not be) faster.
But I guess the only way to compare which code is more
efficient is to actually run it.
Not creating unneeded function objects with each object instantiation is
bound to be faster than doing so, there is no need to time the code to
see that, it is self-evident.
So can you post your own version of the Customer class
(complete implementation, so that I can just copy and
paste it), let's say Customer1? Then we can run a simple
test script, something like that (simply create 100000
Customer objects): <snip> And it should tell, which approach is more efficient.


Superfluous, but if it will discourage you from burying your head in the
sand:-

function Customer1(id, startValue){
this.id = id;
this.startValue = (startValue || 1000);
}
Customer1.prototype.getId = function(){
return this.id;
};
Customer1.prototype.calc = function(){
return (this.startValue * 100);
};

Commenting out the - this.id - assignment and the alert within the if
statement in your version, mine appears to be better than two to four
times faster under your test procedure (depending on the execution
environment).

Richard.
Jul 23 '05 #29
On 25 Nov 2004 09:48:19 -0800, GregS <sw**********@yahoo.com> wrote:
Richard Cornford wrote:
[snip]
Indeed the ECMA 262 (3rd edition) production rules forbid a function
declaration from appearing within a block statement,


[snip]
Could you point out which paragraph prohibits that?
It's not in the prose, but it's clearly specified in the grammar (well,
assuming formal grammar is "clear" to you). Here are probably the most
relevant parts, rewritten in a BNF style for brevity and clarity:

Program :
SourceElement+

SourceElement :
Statement
FunctionDeclaration

Block :
{ Statement* }

Notice the clear distinction between a statement and a function
declaration, and that blocks may only contain the former (if anything).
Well, the following code works fine in IE, Netscape, Mozilla, FireFox
and Opera.
I could only be bothered to experiment briefly in Opera, but your code
"works" because it seems to be treated as

function Customer(...) {
function getId() {...}
function calc() {...}

if(...) {
...
}
}

You can see that by placing alert(calc + '\n' + getId); after the if
statement.
Do they all have the same bug?
I would venture that they're trying to cope with invalid code just like
they do with malformed HTML. However in both cases, don't take advantage
of the leniency: write valid code.
I've read that Opera/FF/etc developers said they follow the standards.
They do, but they can only suffer so many complaints that boil down to:
"Why won't your browser properly interpret this poorly written crap?"
That, and the odd bug here and there, will result in some deviation from
the standards, usually in the form a more lax interpretation.

In any case, it is the standard that you should follow, not a particular
implementation of it.
So if this code works fine in all these browsers - does it make it valid
JS code?


Not in the least.

[snip]

Mike

--
Michael Winter
Replace ".invalid" with ".uk" to reply by e-mail.
Jul 23 '05 #30
"Michael Winter" <M.******@blueyonder.co.invalid> wrote in message news:<opsh1k3lhnx13kvk@atlantis>...
On 25 Nov 2004 09:48:19 -0800, GregS <sw**********@yahoo.com> wrote:
<skip> You can see that by placing alert(calc + '\n' + getId); after the if
statement. Yes, that appears to be the case.

That, and the odd bug here and there, will result in some deviation from
the standards, usually in the form a more lax interpretation.
In any case, it is the standard that you should follow, not a particular
implementation of it.

I agree. But how come this code works (not "works") in ie, gecko
borwsers and opera? Does that mean that they do not really support the
standard? I do not care if it's a bug, more lax interpretation, or
whatever. If it's the standard, should not the browser treat this code
as an error?

Greg

PS This particular code was not meant to discuss 'dynamic' functions.
It was meant to discuss whether or not a function can be declared in a
block.
Jul 23 '05 #31
"Richard Cornford" <Ri*****@litotes.demon.co.uk> wrote in message news:<co*******************@news.demon.co.uk>...
GregS wrote:
Richard Cornford wrote:

<snip> times faster under your test procedure (depending on the execution
environment).


Sure this code will. One can come up with a lot of different ways to
achieve the same.

What I meant, in your first post you offered another implementation of
the original code, which looked something like that and included
function constr:

var HttpRequest = (fucntion(){
....
function constr(id, docObj){
this.id = id;
this.docObj=docObj;
}

constr.prototype.prepareDataRequest = function(targetFrameId,
queryType, requestType, params){
.... whatever
}

I'd like to see your version of the Customer class written in this
fashion.
Greg
Jul 23 '05 #32
On 26 Nov 2004 10:32:06 -0800, GregS <sw**********@yahoo.com> wrote:

[snip]
But how come this code works (not "works") in ie, gecko borwsers and
opera? Does that mean that they do not really support the standard?
Of course they do. It would be classed as an "extension" of the language:

"A conforming implementation of ECMAScript must provide and support
all the types, values, objects, properties, functions, and program
syntax and semantics described in this specification.
...
A conforming implementation of ECMAScript is permitted to support
program and regular expression syntax not described in this
specification. [...]" (Section 2 - Conformance, ECMA-262)

Still, don't do it.
I do not care if it's a bug, more lax interpretation, or whatever. If
it's the standard, should not the browser treat this code as an error?
In my opinion, yes, but I said in my last post that browser vendors are
bombarded by requests for dubious "features" because a user has
encountered a badly-authored document.

You should see some of the Mozilla support forums or Bugzilla. Rather than
placing the blame squarely with the author, users think that the browser
is at fault and demand stupid additions.
PS This particular code was not meant to discuss 'dynamic' functions. It
was meant to discuss whether or not a function can be declared in a
block.


No. If you're attempting to improve efficiency by evaluating a function
only when necessary, use a function expression. I haven't looked at the
original source, but there are probably plenty of other ways, too.

Mike

--
Michael Winter
Replace ".invalid" with ".uk" to reply by e-mail.
Jul 23 '05 #33
"Michael Winter" <M.******@blueyonder.co.invalid> wrote in message news:<opsh4jpdt8x13kvk@atlantis>...
On 26 Nov 2004 10:32:06 -0800, GregS <sw**********@yahoo.com> wrote:

No. If you're attempting to improve efficiency by evaluating a function
only when necessary, use a function expression. I haven't looked at the


Fair enough. What do you think of using eval function, something like
<SCRIPT>

function cc (id){

this.id = id;

if (id == 1){
eval ("function bb () {alert (this.id);};
this.constructor.prototype.func=bb;");
}

if (typeof bb == 'function')
alert (id + ":" + bb)

}

new cc (2); //alert will not pop up. bb not there?
new cc (1).func (); //alert will pop up. bb is there?
</SCRIPT>

It appears to conditionally declare function bb (I checked this code
in ie/gecko/opera). Does this violate the standard? I do not think I'd
use it anyway, I think it makes code harder to understand/maintain.

Greg
Jul 23 '05 #34
GregS wrote:
Richard Cornford wrote:
times faster under your test procedure (depending on
the execution environment).


Sure this code will. One can come up with a lot of
different ways to achieve the same.

What I meant, in your first post you offered another
implementation of the original code, which looked
something like that and included function constr:

var HttpRequest = (fucntion(){
....
function constr(id, docObj){
this.id = id;
this.docObj=docObj;
}

constr.prototype.prepareDataRequest =
function(targetFrameId, queryType, requestType, params){
.... whatever
}

I'd like to see your version of the Customer class written
in this fashion.


Your - Customer - object does not warrant that style of implementation.
Wrapping the creation of the constructor, and the assignment of method
to the prototype, in an inline function expression can serve no purpose
with such an object. Though as your test method is only interested in
the time taken for the creation of an object instance you would not see
any different results if the constructor was created within a function
expression executed inline. (The overhead with that technique is a
one-time cost when the function expression is executed, but that
one-time cost justifies not using the technique when it is not providing
any benefit in return for that cost.)

The factor that suggested that style of implementation with the
original - HttpRequest - was the fact that the - prepareFormDOM -
seemed conceptually private static, and the closure produced by creating
(and configuring) the constructor with the inline execution of a
function expression allows that function to be both private (in the
sense of not being accessible to code outside of the function
expression) and available to all instances of the 'class'.

Richard.
Jul 23 '05 #35
On 27 Nov 2004 14:25:52 -0800, GregS <sw**********@yahoo.com> wrote:

[snip]
What do you think of using eval function, something like
[snip]
eval ("function bb () {alert (this.id);};"
+ "this.constructor.prototype.func=bb;");
I'm quite speechless, and not in a good way.

[snip]
It appears to conditionally declare function bb (I checked this code in
ie/gecko/opera).
But so would

this.constructor.prototype.func = function() {alert(this.id);};
Does this violate the standard?


No, just common sense.

[snip]

I must say I'm still not sure why this is all necessary. Why wouldn't a
Customer object have getId and calc methods initially?

Mike

--
Michael Winter
Replace ".invalid" with ".uk" to reply by e-mail.
Jul 23 '05 #36
"Michael Winter" <M.******@blueyonder.co.invalid> wrote in message news:<opsh5deva5x13kvk@atlantis>...
I must say I'm still not sure why this is all necessary. Why wouldn't a
Customer object have getId and calc methods initially?


You are right. I was just trying to see how this kind of code can be
optimized a bit;

function Customer(...) {

function getId() {...}

if(typeof this.constructor.prototype.done == 'undefined') {
this.constructor.prototype.getId=getID;
this.constructor.prototype.done=1;
}
}
}

as Richard pointed out, upon each Customer object creation, a function
object will be created for getId function declaration; I guess
realistically it may not a problem when only one or just a few are
created; so I tried to see if it can be created dynamically (I mean
using function declarations, not function expressions) and if there
will be any advantages.

It appears though that the 'fastest' approach is this -|

function Customer(...) {

this.constructor.prototype.getId=function () {};

}
}
Greg
Jul 23 '05 #37
On 27 Nov 2004 20:29:26 -0800, GregS <sw**********@yahoo.com> wrote:

[snip]
It appears though that the 'fastest' approach is this -|
function Customer(...) {

this.constructor.prototype.getId=function () {};

}
}


Assuming the data members are public, the fastest would be

function Customer(id, ...) {
this.id = id;
}
Customer.prototype.getId = function() {return this.id;};

as creation of the function is a one-time-only cost. If you want to make
the members private, then

function Customer(id, ...) {
this.getId = function() {return id;};
}

would be. The function would be created anew with every new object, but
it's the only realistic choice.

Mike

--
Michael Winter
Replace ".invalid" with ".uk" to reply by e-mail.
Jul 23 '05 #38
GregS wrote:
Michael Winter wrote:
I must say I'm still not sure why this is all necessary.
Why wouldn't a Customer object have getId and calc methods
initially?

You might also question the need to have a - getId - method at all, when
the - id - property it returns (unaltered) is already public and can be
read (and set) directly from the object.
You are right. I was just trying to see how this kind of
code can be optimized a bit;

function Customer(...) {

function getId() {...}

if(typeof this.constructor.prototype.done == 'undefined') {
this.constructor.prototype.getId=getID;
this.constructor.prototype.done=1;
}
}
}
There is plenty of potential for optimising the test in addition to the
actions following from the passing of the test. The evaluation of the -
if - expression currently involves; resolving a property accessor,
applying the unary - typeof - operator to the result, comparing the
result of that with a string literal and finally type-converting that
result to boolean to make the - if - decision (the last being a trivial
operation as the result of the comparison is already boolean). Given
that the property accessor resolves to a value that is either undefined
or (in this example) numeric one, applying the NOT operator to the
property accessor as the - if - expression:-

if(!this.constructor.prototype.done){
...
}

- produce identical results, as the unary NOT operator will type-convert
the value to boolean and invert it, resulting in false for numeric 1 and
true for undefined, without the need for any other operations. The
overall result will be considerably faster (string comparison being
quite an involved operation when the strings being tested actually do
match, and the typeof algorithm specifying an additional safety check
that NOT does not use (and is irrelevant in this context).

Additionally, the property accessor - this.constructor.prototype.done -
will take longer to resolve than - this.done -, and in the context of
its use in the opening lines of a constructor the two will be reporting
the same value (- this - having inherited its - done - value (if any)
from the constructor's prototype).

But it is questionable whether the - done - flag is required at all as
applying a type-converting test (or even the less efficient - typeof -
test) to any of the methods assigned will produce equivalent result, and
avoid the need to assign a - done - value:

if(!this.getId){
this.constructor.prototype.getId = getId;
}

Repeatedly resolving - this.constructor.prototype - during the
assignments will also become burdensome if it needs to be done more than
a couple of times. The prototype object reference could be cached to a
local variable to reduce that overhead.

However, overall it has got to be fastest and simplest to configure the
constructor's prototype unconditionally outside of the constructor.
Other object designs, those implementing Douglas Crockford's private
instance members technique, attempting multiple inheritance or
implementing common interfaces shared by many classes/subclasses, might
necessitate alternative inheritance patterns (mostly forms of object
augmentation) but the simple javascript objects benefit most from
following the standard javascript prototype inheritance pattern.
as Richard pointed out, upon each Customer object creation,
a function object will be created for getId function
declaration;
Didn't I also mention the overhead in repeating the tests on each object
instantiation?
I guess realistically it may not a problem when only
one or just a few are created; so I tried to see if it
can be created dynamically (I mean using function declarations,
not function expressions) and if there will be any advantages.

It appears though that the 'fastest' approach is this -|

function Customer(...) {

this.constructor.prototype.getId=function () {};

}
}


'fastest'?

Richard.
Jul 23 '05 #39
On Sun, 28 Nov 2004 11:18:30 -0000, Richard Cornford
<Ri*****@litotes.demon.co.uk> wrote:

[snip]
You might also question the need to have a - getId - method at all, when
the - id - property it returns (unaltered) is already public and can be
read (and set) directly from the object.


That hadn't escaped my attention. It was just a minor point in the face of
the eval call.

[snip]

Mike

--
Michael Winter
Replace ".invalid" with ".uk" to reply by e-mail.
Jul 23 '05 #40

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

3 posts views Thread by Chris Hughes | last post: by
8 posts views Thread by Rob McLennan - ZETLAND | last post: by
9 posts views Thread by middletree | last post: by
5 posts views Thread by gregmercer | last post: by
24 posts views Thread by Kourosh | last post: by
1 post views Thread by roland-d | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.