views:

2317

answers:

5

(aggregated from another question)

Jquery 1.3.2 test code, run in FF3:

<input type="hidden" value="236434" id="ixd" name='ixd' />

<script>
console.log( $('#ixd').val() );

console.log( $('#ixd') );
console.log( $("input[name='ixd']") );
console.log( $("input:hidden") );

console.log( $("input[name='ixd'][type='hidden']") );
console.log( $("input[name='ixd']").val() );

$(document).ready(function() {
    console.log( $('#ixd').val() );
    console.log( $('#ixd') );
    console.log( $("input[name='ixd']") );
    console.log( $("input:hidden") );
});
</script>

Console output:

undefined
[]
[]
[]
[]
undefined
236434
[input#ixd 236434]
[input#ixd 236434]
[input#ixd 236434]

Can anybody offer any explanation or documentation links for hidden fields' data not being accessible until after $(document).ready()? It's not something I've ever experienced and it is proving troublesome.

A: 

You shouldn't trust anything until the dom is ready. It is just the way things work. Do you have a problem with waiting till ready?

Ballsacian1
Yes, i.e. an ajax call (to insert into/update a DOM "placeholder" element) fired before the DOM is finished loading
Andy
+4  A: 

Well, I guess you answered your own question. Using document.getElementById() needs the DOM tree to be loaded by the browser in order for the DOM API (which includes getElementById) to work.

That means that you cannot be sure that any getElementById call will work properly until the $(document).ready function is called. Check out http://dean.edwards.name/weblog/2005/02/order-of-events/ for more

Flavius Stef
`getElementById()` should work for all elements preceding the script
Christoph
Why has this answer been modded up? It's incorrect and references a 4 year old article, probably for a different JS version. Christoph is correct - elements "declared" above the <script> tags can usually be referenced.
Andy
@Andy: the referenced article (check it's follow-ups!) is still a nice read if you're interested in the so-called onload-problem (which has been solved well enough except in corner cases); it's just not really relevant in context of your problem ;)
Christoph
@Christoph I generally never use $(document).ready(), instead interspersing HTML with JS as it *seems* to reduce page load time (worth benchmarking!). Is this sensible?
Andy
@Andy: It might not reduce overall load times, but might result in better responsiveness; there are some nice articles about such things at yahoo and alistapart. Inline-scripting is often frowned upon as it breaks behavioral separation (a dogma of unobstrusive scripting); try to avoid the need for onload-actions altogether - event delegation and setting a single class on html or body if js is enabled can go a long way
Christoph
@Andy: Strictly speaking, you are right. But I think that getElementById() functioning before domReady is more of a tacit implementation choice by browser vendors and not something to rely upon (I failed to find any directive regarding its use in the W3C specs).
Flavius Stef
@Flavius: when `getElementById()` was introduced, there was no `DOMContentLoaded`, only `window.onload`, creating the so-called onload-problem; the solution was to put a script block as last element of `body` - meaning that strictly speaking, the DOM wasn't 'ready' when it executed - but this has worked reliably since the dawn of the DOM-era; also, the HTML5 spec makes heavy use of inline scripting and calling `getElementById()` without bothering with any ready checks, so even if it's not part of any standard (yet?), it's a de-facto standard
Christoph
A: 

document.ready when page is "ready", meaning fully rendered. Your hidden field is probably not rendered on page yet at the moment in the start log.

Use ready() to start manipulating with page elements, not before that, "it's the only way to be sure" :)

Andrija
+1  A: 

If I take your code (and add jQuery above) I get the same output. But if I change your code to the following, it will output the correct results. My guess is that firefox parses the HTML in a different order when no html/head/body is given.

<html>
<head>
<script type="text/javascript" src="jquery-1.3.2.js"></script>
</head>
<body>
<input type="hidden" value="236434" id="ixd" name='ixd' />

<script>
console.log( $('#ixd').val() );

console.log( $('#ixd') );
console.log( $("input[name='ixd']") );
console.log( $("input:hidden") );

console.log( $("input[name='ixd'][type='hidden']") );
console.log( $("input[name='ixd']").val() );

$(document).ready(function() {
    console.log( $('#ixd').val() );
    console.log( $('#ixd') );
    console.log( $("input[name='ixd']") );
    console.log( $("input:hidden") );
});
</script>

</body>
</html>

But, as said above, wait for the document to be ready before trying to retrieve elements by ID.

miguelle
Thanks miguelle, this is indeed correct! As speculated it appears that firebug's console has a bug relating to either console.log or the parsing of hidden elements that aren't declared in valid HTML.
Andy
+2  A: 

Contrary to what others have written, your example should work as all major browsers allow access to elements which precede the executing script block. I don't have Firebug installed, but when replacing console.log() with document.writeln(), your example works as expected.

What happens when you create the following HTML document:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"&gt;&lt;/script&gt;
<input type="hidden" value="236434" id="ixd">
<pre><script type="text/javascript">
document.writeln($('#ixd').val());
document.writeln(document.getElementById('ixd').value);
</script></pre>
Christoph
Christoph, thanks for your answer and working example. When considered in context of miguelle's answer (adding <head> and <body> tags) it appears that firebug's console has a bug relating to either console.log or the parsing of hidden elements that aren't declared in valid HTML.
Andy