How to figure out if an input box exists without getting an error

S

Stefan Mueller

I can display the value of the following input box with
alert(parent.MyFrame.document.MyForm.MyInput.value);

But if the frame, the form or the input box doesn't exist I get of course an
error message.
How can I figure out before I display the value if the frame 'MyFrame', the
form 'MyForm' and also the input box 'MyInput' exists without getting an
error message?

Stefan
 
M

Martin Honnen

Stefan said:
I can display the value of the following input box with
alert(parent.MyFrame.document.MyForm.MyInput.value);

But if the frame, the form or the input box doesn't exist I get of course an
error message.

Use object/feature detection:
<http://jibbering.com/faq/#FAQ4_26>
That FAQ is mainly about checking certain features a browser implements
but those property or object checks can also be applied to your problem.
There is an example in there.
 
T

Thomas 'PointedEars' Lahn

Dr said:
Perhaps something similar to this..

Certainly not!
function myFoo()
{
for(;;) {
if(parent.MyFrame)if(parent.MyFrame.document)
if(parent.MyFrame.document.getElementById("MyInput"))
break;

I have seldom seen such a ridiculous piece of source code.

1. Tight loops are the way to the Dark Side.[tm]

2. if(parent.MyFrame)if(parent.MyFrame.document)
if(parent.MyFrame.document.getElementById("MyInput"))

can and should be expressed as

if (parent.frames['MyFrame']
&& parent.MyFrame.document

setTimeout("myFoo()",1000);return;

Seriously think about that for a minute! You set probably thousands of
timeouts here (since it runs in a tight loop) to go off 1000 milliseconds
(1 second) later. The faster the CPU is, the more timeouts will go off at
approximately the _same_ time. And then it is not over because each of
these thousands of timeouts will set even more timeouts _each_ which will
set more timeouts which ... as myFoo() always called again. That will be
probably 1 million timeouts at the least! A sure way to cripple the user's
system beyond repair.

You sir, who calls himself Dr Clue, have no clue at all. Or you have a
clue and deliberately want harm others, who knows. The fact is: You are
dangerous. You should be condemned to have no computer access at all
for a very long time. FOAD!


PointedEars
 
M

Matt Kruse

Thomas said:
can and should be expressed as
if (parent.frames['MyFrame']
&& parent.MyFrame.document

No it shouldn't.

Try:

if (parent.frames['MyFrame'] && parent.frames['MyFrame'].document)
 
T

Thomas 'PointedEars' Lahn

Stefan said:
if (parent.frames['MyFrame']
&& parent.MyFrame.document

That works great.

However, the timeout-in-tight-loop problem remains.

In my UFPDB[1], I am using something similar to the following
to ensure availability of a method in another frame.

function makeBanner()
{
var f;
if (parent
&& (f = parent.frames)
&& (f = f['ufpdb_banner'])
&& typeof f.makeLeftBanner == "function")
{
if (typeof makeBanner.timeout != "undefined")
{
window.clearTimeout(makeBanner.timeout);
delete makeBanner.timeout;
}
f.makeLeftBanner(...);
}
else
{
makeBanner.timeout = window.setTimeout("makeBanner();", 250);
}
}
makeBanner();

Your target of testing availability of a DOM element is not much
different to that.

As you can see, in contrast to the harmful solution provided by
"Dr Clue", I do not not set the timeout in a tight loop and I
set it only if necessary, hence there is only one timeout to
go off and if no longer needed, it is properly cleared.


PointedEars
___________
[1] <http://www.pointedears.de/ufpdb/> (always under construction,
so please don't bother with bug reports until further notice)
 
T

Thomas 'PointedEars' Lahn

Matt said:
Thomas said:
can and should be expressed as
if (parent.frames['MyFrame']
&& parent.MyFrame.document

No it shouldn't.

Try:

if (parent.frames['MyFrame'] && parent.frames['MyFrame'].document)

Yes, yes, I dare forgetting to change one property accessor which bears
almost no meaning in that context regarding any known user agent, if that.

It's your nitpick day today? Then let me nitpick, too: your code as-is is
neither efficient nor does it qualify as a reliable solution regarding the
OP's request as the tests for the host objects, especially the target
element object, are missing. It should read

var o;
if (typeof window != "undefined"
&& (o = window.parent)
&& (o = o.frames)
&& (o = o['MyFrame'])
&& (o = o.document)
&& (o = o.forms)
&& (o = o['MyForm'])
&& (o = o.elements)
&& (o = o['MyInput'])
&& typeof o.value != "undefined")
{
// access `o.value' here
}

Get a life :-b


PointedEars
 
M

Matt Kruse

Thomas said:
Matt said:
Thomas said:
can and should be expressed as
if (parent.frames['MyFrame']
&& parent.MyFrame.document
Try:
if (parent.frames['MyFrame'] && parent.frames['MyFrame'].document)
Yes, yes, I dare forgetting to change one property accessor which
bears almost no meaning in that context regarding any known user
agent, if that.

Your original syntax had a potential name collision with a global variable
named "MyFrame", which very well might be a realistic case, and very well
might cause a problem.

My correction was to that potential problem, and not intended to be a
complete solution for the OP.
 
S

Stefan Mueller

if (parent.frames['MyFrame'] && parent.frames['MyFrame'].document)

I'm doing my tests exactly like you told me and it works perfect.
But I not really understand why to do
if (parent.MyFrame && parent.MyFrame.document &&
parent.MyFrame.document.MyForm && parent.MyFrame.document.MyForm.MyInput) {

Why can't I just do
if (parent.MyFrame.document.MyForm.MyInput) {
?

I know it doesn't work but I really don't understand that because I think
that in both cases if the MyInput text box doesn't exist
(parent.MyFrame.document.MyForm.MyInput) returns false.
Stefan
 
R

Rob Williscroft

Thomas 'PointedEars' Lahn wrote in in comp.lang.javascript:
Seriously think about that for a minute! You set probably thousands of
timeouts here (since it runs in a tight loop) to go off 1000 milliseconds
(1 second) later.

You appear to have missed the return statment.

Rob.
 
M

Martin Honnen

Stefan Mueller wrote:

But I not really understand why to do
if (parent.MyFrame && parent.MyFrame.document &&
parent.MyFrame.document.MyForm && parent.MyFrame.document.MyForm.MyInput) {

The && operator (|| as well but not used here) does some lazy evaluation
of operand expressions which allows you to write such step by step
checks without causing errors.
If you only tried to check
if (parent.MyFrame.document.MyForm.MyInput)
then in various cases e.g. if
parent.MyFrame
is undefined or null or if
parent.MyFrame.document
is undefined or null or if
parent.MyFrame.document.MyForm
is undefined or null the expression will give an error (e.g.
... is null or not an object in IE
or
... has no properties in Mozilla
).

As
expression1 && expression2
evaluates expression1, converts to a boolean and if that is false simply
returns the result of expression1 for the whole "and expression" however
you can safely do the step by step checks and need to do them if you
want to handle all possible cases (e.g. no parent.MyFrame frame or no
document loaded in parent.MyFrame or no MyForm form in the document in
parent.MyFrame frame).
 
R

Richard Cornford

Rob said:
You appear to have missed the return statment.

Ah yes. I missed that too. One of the manifestations of DrClue's poor
coding is poor code formatting. The results are hard to read and
comprehend (with the inevitable consequences for code maintenance and
increased chance of erroneous or foolish coding). He wrote:-

| function myFoo()
| {
| for(;;) {
| if(parent.MyFrame)if(parent.MyFrame.document)
| if(parent.MyFrame.document.getElementById("MyInput"))
| break;
|
| setTimeout("myFoo()",1000);return;
| }// End forever
| alert(parent.MyFrame.document.MyForm.MyInput.value);
| }

(and failed to use spaces to indent the code so that the formatting
would be preserved for all readers)

It is commonly recommended that if statements that only have a single
statement following them still use a block statement, with the single
statement within that block. This avoids confusion as to the logic of
the if statement and avoids mistakes when adding lines of code. If I was
formatting that function I would have formatted it as:-

function myFoo(){
for(;;){
if(parent.MyFrame){
if(parent.MyFrame.document){
if(parent.MyFrame.document.getElementById("MyInput")){
break;
}
}
}
setTimeout("myFoo()",1000);
return;
}
alert(parent.MyFrame.document.MyForm.MyInput.value);
}

- as that better exposes the logic of the if statements and makes the
return more obvious. And in doing that it becomes self-evident that the
code was written by a fool. The - for - statement may loop forever,
unless broken, but it cannot loop more than once because it cannot
escape the return stamen it contains, unless it is broken. There is
simply no need to have a - for - statement here at all:-

function myFoo(){
if(
(parent.MyFrame)&&
(parent.MyFrame.document)&&
(parent.MyFrame.document.getElementById("MyInput"))
){
alert(parent.MyFrame.document.MyForm.MyInput.value);
}else{
setTimeout("myFoo()",1000);
}
}

- is a simpler and much more rational approach to the same outcome.

Richard.
 
R

Richard Cornford

Stefan said:
if (parent.frames['MyFrame'] && parent.frames['MyFrame'].document)

I'm doing my tests exactly like you told me and it works perfect.
But I not really understand why to do
if (parent.MyFrame && parent.MyFrame.document &&
parent.MyFrame.document.MyForm &&
parent.MyFrame.document.MyForm.MyInput) {

Why can't I just do
if (parent.MyFrame.document.MyForm.MyInput) {
?

I know it doesn't work but I really don't understand that
because I think that in both cases if the MyInput text box
doesn't exist (parent.MyFrame.document.MyForm.MyInput)
returns false.

The issue is that to resolve:-

parent.MyFrame.document.MyForm.MyInput

The language must first resolve:-

parent.MyFrame.document.MyForm

- and before that:-

parent.MyFrame.document

- and before that:-

parent.MyFrame

- and before that:-

parent

Or, more precisely, it resolves - parent - aginast the scope chain and
then atempts to get the value of a 'MyFrame' property of whatever -
parent - resolves as, and then attempts to get the value of a 'document'
property of that second value, then a 'MyForm' of the third value, and
then a 'MyInput' property of the fourth value.

If at any point one of these evaluates to the values of undefined or
null the subsequent attempt to read a property name from the value will
produce a run-time error and the test will never complete.

You may be fairly confident that - parent - refers to an object in a web
browser environment but 'MyFrame' will not be defined until the HTML
parser has seen the FRAME element (and not necessarily immediately upon
that happening (or at all)). MyFrame may not have a 'document' property
until it starts downloading to contents of the frame, its document will
not have a 'MyForm' property before the opening FORM tag is encountered
by the HTML parser, and 'MyInput will not be a property before the INPUT
element is encountered.

The browser object model is built up progressively so if the existence
of anything is an issue the existence of all the intermediate objects
would also be an issue.

Richard.
 
T

Tony

It is commonly recommended that if statements that only have a single
statement following them still use a block statement, with the single
statement within that block. This avoids confusion as to the logic of
the if statement and avoids mistakes when adding lines of code.

Hah - that's funny.

I was told about a week or so ago in alt.www.webmaster that people who
did that were "unskilled" programmers, and shouldn't be programming.
 
M

Matt Kruse

Tony said:
Hah - that's funny.
I was told about a week or so ago in alt.www.webmaster that people who
did that were "unskilled" programmers, and shouldn't be programming.

It's a question of style, not a hard rule.

I agree than even if there is only one statement inside a condition, it
should be a block bounded by { }.

There is simply no reason _not_ to, but several good reasons in favor of it.

Those advising you in the other newsgroup are in error, IMO.
 
R

RobG

Matt said:
It's a question of style, not a hard rule.

I agree than even if there is only one statement inside a condition, it
should be a block bounded by { }.

There is simply no reason _not_ to, but several good reasons in favor of it.

Those advising you in the other newsgroup are in error, IMO.

Interesting to note that Douglas Crockford in his article /Private
Members in JavaScript/ includes this:


function dec() {
if (secret > 0) {
secret -= 1;
return true;
} else {
return false;
}
}


which could be reduced to:

function dec() {return secret && secret--};


For instruction purposes the longer version is much simpler to
understand, even though it may not be used in practice. The longer code
is about 15% slower in Firefox (about 800ms vs 920ms), with no
measurable difference in IE (about 2100ms) when measured over 50,000 loops.

The entire difference in speed results from the way secret is
decremented - 'secret -= 1' versus 'secret--'.


1. An immensely helpful article:
<URL:http://www.crockford.com/javascript/private.html>
 
R

Randy Webb

Tony said the following on 11/21/2005 8:09 PM:
Hah - that's funny.

Funny - maybe. True - without a doubt.
I was told about a week or so ago in alt.www.webmaster that people who
did that were "unskilled" programmers, and shouldn't be programming.

Sounds like a.w.w has a few "unskilled programmers" in the midst.
 
M

Matt Kruse

RobG said:
function dec() {
if (secret > 0) {
secret -= 1;
return true;
} else {
return false;
}
}
which could be reduced to:
function dec() {return secret && secret--};

No it couldn't.
Your function returns the original value of 'secret' rather than a boolean.
In the cases where 'secret' is negative, the negative number evaluates to
true, rather than false, which is different behavior than the original.

Test case:

function dec1(secret) {
if (secret > 0) {
secret -= 1;
return true;
} else {
return false;
}
}
function dec2(secret) {return secret && secret--};
for (var i=-2; i<=2; i++) {
alert(i + "|" + dec1(i) + "|" + dec2(i) + "/" +
(dec2(i)?"true":"false") );
}

A shorter function which does match the original functionality is:

function dec() { return (secret-- > 0); }
For instruction purposes the longer version is much simpler to
understand, even though it may not be used in practice. The longer
code is about 15% slower in Firefox (about 800ms vs 920ms), with no
measurable difference in IE (about 2100ms) when measured over 50,000
loops.

A 120ms difference over 50,000 loops is meaningless.
Over a single iteration, in a single browser, that means a .0000024 second
difference, which is insignificant.
Since the original is simpler to understand, I think it is the better choice
overall if the code is to be used or understood by a general audience. If
the code is meant to be dense and used by a limited audience, my revised
dec() might be a better choice.
 
M

Matt Kruse

RobG said:
function dec() {
if (secret > 0) {
secret -= 1;
return true;
} else {
return false;
}
}
which could be reduced to:
function dec() {return secret && secret--};

No it couldn't.
Your function returns the original value of 'secret' rather than a boolean.
In the cases where 'secret' is negative, the negative number evaluates to
true, rather than false, which is different behavior than the original.

Test case:

function dec1(secret) {
if (secret > 0) {
secret -= 1;
return true;
} else {
return false;
}
}
function dec2(secret) {return secret && secret--};
for (var i=-2; i<=2; i++) {
alert(i + "|" + dec1(i) + "|" + dec2(i) + "/" +
(dec2(i)?"true":"false") );
}

A shorter function which does match the original functionality is:

function dec() { return (secret-- > 0); }
For instruction purposes the longer version is much simpler to
understand, even though it may not be used in practice. The longer
code is about 15% slower in Firefox (about 800ms vs 920ms), with no
measurable difference in IE (about 2100ms) when measured over 50,000
loops.

A 120ms difference over 50,000 loops is meaningless.
Over a single iteration, in a single browser, that means a .0000024 second
difference, which is insignificant.
Since the original is simpler to understand, I think it is the better choice
overall if the code is to be used or understood by a general audience. If
the code is meant to be dense and used by a limited audience, my revised
dec() might be a better choice.
 
M

Matt Kruse

Matt said:
A shorter function which does match the original functionality is:
function dec() { return (secret-- > 0); }

Uh, that's not right either, since a value of 0 would be decremented.
What you probably would need is:

function dec(){ return (secret>0 && secret-- && true); }

However, that's even less clear than the original, IMO.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,528
Members
45,000
Latest member
MurrayKeync

Latest Threads

Top