FAQ Topic - I get an error when trying to access an element by getElementById but I know it is in th


F

FAQ server

-----------------------------------------------------------------------
FAQ Topic - I get an error when trying to access an
element by getElementById but I know it is in the document.
What is wrong?
-----------------------------------------------------------------------

You cannot access elements that appear in the document after you try
to read them with a DOM method like ` document.getElementById `.
You can either:

A) include your script after the HTML element it refers to, or
B) use the "load" event to trigger your script.

Example A:

<div id="snurgle">here</div>
<script type="text/javascript">
(function(){
var snurgle = document.getElementById('snurgle');
})();
</script>

Example B:

<script type="text/javascript">
window.onload = findElement;
function findElement(){
var snurgle = document.getElementById('snurgle');
};
</script>
</head>


The complete comp.lang.javascript FAQ is at
http://jibbering.com/faq/
 
Ad

Advertisements

D

Dr J R Stockton

In comp.lang.javascript message <[email protected]
-----------------------------------------------------------------------
FAQ Topic - I get an error when trying to access an
element by getElementById but I know it is in the document.
What is wrong?
-----------------------------------------------------------------------
Subject is too long.
"Why can getElementById fail to find an element?"
You cannot access elements that appear in the document after you try
to read them with a DOM method like ` document.getElementById `.


That can be read to give the intended meaning. But its more natural
interpretation, to one accustomed to reading good English, is that the
act of attempting doc.gEBI disables subsequent access. Omit.
You can either:
^ It may not yet have been created.
A) include your script after the HTML element it refers to, or that
B) use the "load" event to trigger your script.

C) have the access triggered manually, so that it naturally occurs after
the element (but not necessarily the whole page) is loaded.

Example A:

<div id="snurgle">here</div>
<script type="text/javascript">
(function(){
var snurgle = document.getElementById('snurgle');
})();
</script>

Example B:

<script type="text/javascript">
window.onload = findElement;
function findElement(){
var snurgle = document.getElementById('snurgle');
};
</script>
</head>

Probably worth including <head>. And AFAICS snurgle cannot be accessed
outside findElement and is not accessed within it, which makes the
example confusing.
 
J

Jorge

(...)
<script type="text/javascript">
window.onload = findElement;
function findElement(){
var snurgle = document.getElementById('snurgle');};
^^^

This last semicolon should not be there. And, there's no need to
pollute the global context, so, why not :

window.onload= function () {
var snurgle = document.getElementById('snurgle');
...
};

?
 
G

Garrett Smith

Jorge said:
ACK.
^^^

This last semicolon should not be there. And, there's no need to
pollute the global context, so, why not :

window.onload= function () {
var snurgle = document.getElementById('snurgle');
...
};

That works.
 
D

Dr J R Stockton

Sat said:
ACK.

Lets move this to a new "Errors" section:

"Reported Errors".
"X is null or undefined"

The FAQ should not, and should not appear to, express error messages
literally, since they generally vary from browser to browser, and
probably more so when non-browsers are included.

ACK.

The wording is totally confusing. Please, can you write something up
for that?


* An element can only be accessed after it has been created
* JavaScript is case-sensitive
* IDs must be unique; the access may find a duplicate ID
* The element reference may be incorrectly expressed

I doubt whether it is necessary to include any of those, or any
examples; once the problem is understood, the cure should be easy but
will depend on circumstances.
That means "<title>" is necessary (to be valid) and, omitting a doctype
might be taken as a recommendation, so it would then require a doctype,
too, but then we would still have an incomplete document, with no body
tag.

The example is best preceded by, and followed with "...".

In such cases, one can put
<script type="text/javascript"> // in the Head
which seems better than putting a closer without its opener.
 
D

Danny Wilkerson

3 suggestions

1) make sure no other code is redefining your window.onload like auto
inserted ads on free hosts or other included javascript files.

2) move window.onload = findElement; to somewhere after the
findElement function. You might be assigning the event to a function
that does not exists yet. I am not going to go to the trouble of
running your code to check this but either way it makes sense to
assign onload to a function which is already created.

3) check the page for multiple elements with the same id. Id's should
only be used once per page. You most likely will not find the element
if it's named twice.

If neither of the 2 above work, then try window.document.getElementById
(). someone might have tried creating a variable/object "document"
before your code and thereby overriding the inferred window.document.
It's also possible that someone changed the
window.document.getElementById object but it's extremely unlikely.
 
Ad

Advertisements

G

Garrett Smith

Dr said:
"Reported Errors".


The FAQ should not, and should not appear to, express error messages
literally, since they generally vary from browser to browser, and
probably more so when non-browsers are included.

Probably. Understanding what those error messages mean and what causes
them seems like it would be helpful for beginners.
* An element can only be accessed after it has been created
s/created/parsed

But that answer is not complete either, because it does not consider the
possibility of the element being created via createElement.

Instead:
"An element cannot be accessed before it exists in the DOM"

Is simpler and avoids the earlier confusion.
* JavaScript is case-sensitive
That's a basic syntax feature of the language. Unlikely to be a problem
here.
* IDs must be unique; the access may find a duplicate ID
* The element reference may be incorrectly expressed

I don't know what that means.

[snip examples]
I doubt whether it is necessary to include any of those, or any
examples; once the problem is understood, the cure should be easy but
will depend on circumstances.

Possibly not. I've shortened the examples.

| 8.8 I get an error when trying to access an element by getElementById
| but I know it is in the document. What is wrong?
|
| An element cannot be accessed before it exists in the DOM.
|
| Either: A) include your script after the HTML element it refers to, or
| B) use the "load" event to trigger your script.
|
| Example A:
|
| <div id="snurgle">here</div>
| <script type="text/javascript">
| document.getElementById("snurgle");
| </script>
|
| Example B:
|
| // In the HEAD.
| <script type="text/javascript">
| window.onload = findElement;
|
| function findElement(){
| var snurgle = document.getElementById("snurgle");
| }
| </script>

Garrett
 
G

Garrett Smith

Danny said:
3 suggestions

1) make sure no other code is redefining your window.onload like auto
inserted ads on free hosts or other included javascript files.

Hosting mayhem is not going to be covered in the FAQ.

The section on posting covers such problems well-enough:
2) move window.onload = findElement; to somewhere after the
findElement function. You might be assigning the event to a function
that does not exists yet. I am not going to go to the trouble of
running your code to check this but either way it makes sense to
assign onload to a function which is already created.

You obviously did not run the code. It sounds like your understanding of
variable instantiation is incorrect or uncertain.
3) check the page for multiple elements with the same id. Id's should
only be used once per page. You most likely will not find the element
if it's named twice.

That is a different problem and would not result in an error being
thrown. It touches a good point, though: Two elements with the same ID
means the document is not valid.

Invalid HTML is usually correlated with developer confusion and false
expectations. A frequent and easily preventable source of errors is
invalid HTML.

* Create a simplified example of the problem
* Validate your HTML and CSS:
* http://validator.w3.org/
* http://jigsaw.w3.org/css-validator/

That's pretty much covered in "postCode" in the FAQ:
http://jibbering.com/faq/#postCode

Garrett
 
T

Thomas 'PointedEars' Lahn

Garrett said:
You obviously did not run the code. It sounds like your understanding of
variable instantiation is incorrect or uncertain.

While you are correct that variable instantiation happens before execution,
Danny brings up an important point: the case should be considered that the
`findElement' were the identifier of an initialized variable, as in

var findElement = function(/* ... */) {
/* ... */
};

That does not look to me as so strange a pattern (for example, no need to
create a function object if certain preconditions for its use are not met),
and then it would matter where `findElement' was initialized with or
assigned the Function object reference.

That said, references to `window.onload' should be removed, and the
standards-compliant approach be suggested instead.


PointedEars
 
J

Jorge

Hosting mayhem is not going to be covered in the FAQ.

The section on posting covers such problems well-enough:


You obviously did not run the code. It sounds like your understanding of
variable instantiation is incorrect or uncertain.




That is a different problem and would not result in an error being
thrown.

As the element found might not be the one you were looking for, rest
assured that it's going to bite you, for sure.
It touches a good point, though: Two elements with the same ID
means the document is not valid.

Invalid HTML is usually correlated with developer confusion and false
expectations. A frequent and easily preventable source of errors is
invalid HTML.

* Create a simplified example of the problem
* Validate your HTML and CSS:
   *http://validator.w3.org/
   *http://jigsaw.w3.org/css-validator/

Validating the source .html file won't catch any problems with
dynamically inserted elements...
 
D

Dr J R Stockton

In comp.lang.javascript message <[email protected]
2000yqk.googlegroups.com>, Sun, 28 Jun 2009 12:15:22, Danny Wilkerson
3 suggestions

1) make sure no other code is redefining your window.onload like auto
inserted ads on free hosts or other included javascript files.
...

The FAQ is [substantially, at least] written on the assumption that, for
a given page, the code which is executed by the browser is the code
which was written by the author for that page.

That assumption can be made false in various ways, including

Use of author's include files, which may contain forgotten material;
Use of associates' include files, which may contain unknown material;
Use of library-type files, possibly intermittently updated;
Voluntary inclusion of gadgets from such as Google;
Compulsory insertions made by the server;
Coding 'eval' of an uncontrolled string;
The user copying and changing the page, then blaming the author.

IMHO, the FAQ should say something concise about such possibilities.
 
Ad

Advertisements

G

Garrett Smith

Thomas said:
While you are correct that variable instantiation happens before execution,

More to the point, Danny is wrong for posting something that suggests
otherwise and doing so without testing or reading the relevant
specifications.
Danny brings up an important point: the case should be considered that the
`findElement' were the identifier of an initialized variable, as in

var findElement = function(/* ... */) {
/* ... */
};

That is your code, and it is obviously not what Danny responded to. The
code in the FAQ is simple and works.
That said, references to `window.onload' should be removed, and the
standards-compliant approach be suggested instead.

NAK

Garrett
 
T

Thomas 'PointedEars' Lahn

Garrett said:
That is your code, and it is obviously not what Danny responded to.

I know. Hence my saying "brings up an important point" and not "points
out". Learn to read.
The code in the FAQ is simple and works.

It is too simple at that. To begin with, the declaration of the global
function is unnecessary and potentially harmful (depending on the runtime
environment, function identifier, and used libraries.)

Why not? Why should the FAQ show an example that only works under certain
conditions when it could provide an example that worked everywhere?


PointedEars
 
D

Dr J R Stockton

Sun said:
s/created/parsed

Elements are not parsed (in this context); source code is parsed.
But that answer is not complete either, because it does not consider
the possibility of the element being created via createElement.

It does not need to discriminate, AFAIK, between methods of creation.
If it does so need, that will need to be explained.
Instead:
"An element cannot be accessed before it exists in the DOM"

Is simpler and avoids the earlier confusion.

You're again writing for the knowledgeable. The target reader may not
understand what you mean by DOM. To my mind, the DOM is a mixture of a
schema for creating code-dependent structures and the structure provided
in an empty page.

Some elements, such as Math.random, are created before any user code can
execute, and so are always findable.


That's a basic syntax feature of the language. Unlikely to be a problem
here.

On the contrary : it is easy to forget, and so should be here. You are
not writing an International Standard, in which it can be assumed that
the reader of any sentence in it has already read, understood, and
memorised all previous sentences and all of any other required
standards.
I don't know what that means.

Example : I had a button which called Fn(this). Initially, function
Fn(B) { ... } only toggled the button's value, and a global Boolean.
Later, I wished in Fn to access another element of the form that
contained the button, and wrote something like form.otherelement.value.
To a human, the intent is clear enough; but script requires a preceding
"B.".
 
G

Garrett Smith

Dr said:
Elements are not parsed (in this context); source code is parsed.


It does not need to discriminate, AFAIK, between methods of creation.
If it does so need, that will need to be explained.


You're again writing for the knowledgeable. The target reader may not
understand what you mean by DOM. To my mind, the DOM is a mixture of a
schema for creating code-dependent structures and the structure provided
in an empty page.

We have:

| 2.4 What is the document object model?

I think changing that to:

| 2.4 What is the DOM (Document Object Model)?

Would be helpful. The entry needs a total rewrite though. Look:-

| This is the collection of objects provided by each browser.

That's roughly what you said, isn't it? I think that is completely a
wrong answer and misleading to the Math.random example. The Document
Object Model (DOM) is a model for Document objects etc.

The DOM entry should be changed and in a way so that the answer to "An
element cannot be accessed before it exists in the DOM" can be easily
understood.
Some elements, such as Math.random, are created before any user code can
execute, and so are always findable.

I see, so code such as the following:-

document.getElementById( Math.random );

should work just fine.

Kidding, of course ;-)

Given the topic in question is regarding getElementById, Math.random or
other non-Elements seem unlikely to pose a problem for most.
On the contrary : it is easy to forget, and so should be here. You are
not writing an International Standard, in which it can be assumed that
the reader of any sentence in it has already read, understood, and
memorised all previous sentences and all of any other required
standards.

I don't think it's a problem. Modern OO languages are case-sensitive.
CSS is case-sensitive. I don't see case-sensitivity issues, except maybe
occasionally getElementByID (instead of getElementById).

Example : I had a button which called Fn(this). Initially, function
Fn(B) { ... } only toggled the button's value, and a global Boolean.
Later, I wished in Fn to access another element of the form that
contained the button, and wrote something like form.otherelement.value.
To a human, the intent is clear enough; but script requires a preceding
"B.".

I think you're saying that [[scope]], as we discussed earlier, is of
consideration. Event handler attributes' scope and context is out of
context here.

Garrett
 
D

Dr J R Stockton

In comp.lang.javascript message <[email protected]
september.org>, Thu, 2 Jul 2009 00:28:34, Garrett Smith
We have:

| 2.4 What is the document object model?

I think changing that to:

| 2.4 What is the DOM (Document Object Model)?

or | 2.4 What is the Document Object Model (DOM)?
Would be helpful. The entry needs a total rewrite though. Look:-

| This is the collection of objects provided by each browser.

That's roughly what you said, isn't it? I think that is completely a
wrong answer and misleading to the Math.random example. The Document
Object Model (DOM) is a model for Document objects etc.

If that is the case, no further explanation should be needed.


The DOM entry should be changed and in a way so that the answer to "An
element cannot be accessed before it exists in the DOM" can be easily
understood.


I see, so code such as the following:-

document.getElementById( Math.random );

should work just fine.

It will, no doubt, do whatever it should do. In FF 3.0.11, it returns
an Object which is not a function, and which is === null.

But I wrote "findable", not "findable by getElementById".

Given the topic in question is regarding getElementById, Math.random or
other non-Elements seem unlikely to pose a problem for most.

The topic is over-particular; and the reference to Math.random was
intended as illustration, not draft.

FAQ Topic - Why can I not access an element?

That will be found both by those using getElementById and by those
trying to access elements by other means. The entry will be more
useful.

I don't think it's a problem. Modern OO languages are case-sensitive.
CSS is case-sensitive. I don't see case-sensitivity issues, except
maybe occasionally getElementByID (instead of getElementById).

The degree of problem depends on the skill of the typist, and on the
font and eyeballs used when reading the source. It's easy to make a
mistake and not notice it, either because the upper- and lower- case
versions differ only in size or because one has mis-remembered what case
the ID really uses.

Example : I had a button which called Fn(this). Initially, function
Fn(B) { ... } only toggled the button's value, and a global Boolean.
Later, I wished in Fn to access another element of the form that
contained the button, and wrote something like form.otherelement.value.
To a human, the intent is clear enough; but script requires a preceding
"B.".

I think you're saying that [[scope]], as we discussed earlier, is of
consideration. Event handler attributes' scope and context is out of
context here.

No. The Event only caused the attempted access, not its failure.
Consider describing the Highway from Mexico City to Managua, and
forgetting El Salvador.

Really, there are three basic reasons for element access failure :
* No such element
* No such element yet
* One does not access that sort of element like that.
 
Ad

Advertisements

T

Thomas 'PointedEars' Lahn

Garrett said:
That is not exactly what you wrote.

Learn to read!
| Danny brings up an important point

Yes, that is what I said. "Hence my saying" means "Therefore I said" in
proper English.
As I understood Danny's post, he didn't "bring up" the case you are
considering.

He brought up the point of using a function expression (probably without
knowing, but that makes no difference).
[snipped pointless babble]
It is too simple at that. To begin with, the declaration of the global
function is unnecessary and potentially harmful (depending on the runtime
environment, function identifier, and used libraries.)

From an organizational perspective, the creating a |findElement|
property on the global object is not necessary.

From all perspectives it isn't necessary, and potentially harmful. "Avoid
globals" is one of the first thing one should learn in client-side scripting.
Having an identifier is helpful, for debugging.

You're reaching. Any decent debugger can set a breakpoint in a function
expression. Some (like Firebug) can even recognize the "debugger" keyword.
Adding a closure is ugly for such a simple task.

Non sequitur. I have not suggested using a closure at all.
(function(){
window.onload = findElement;

function findElement(ev) {
//
}
})();

Completely unnecessary!

window.onload = function(ev) {
// ...
};

That said, `ev' is not of much use here in any case.
<body onload...> does not work everywhere;

Where does it not work? It has been working since the earliest Netscape
versions (that is, even when HTML did not specify it yet), and it is
specified in HTML 4.01, XHTML 1.0, and XHTML 1.1 (Intrinsic Events module).

You are not arguing with a user agent that is FUBAR, are you?
and will fail to work in my Firefox, because I am running NoScript.

And `window.onload' will work with NoScript? If yes, a bug in NoScript to
be fixed ASAP but nothing considerable for the general environment. If no,
a red herring. Irrelevant in any case.
Where does window.onload not work that <body onload...> does work?

Whereever this proprietary property is not implemented or implemented
differently. And window.onload does not handle the `load' event of the
document, but that of the window.


PointedEars
 

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

Top