jquery hidden field not accessible until $(document).ready() called
Asked Answered
A

5

0

(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.

Airflow answered 15/6, 2009 at 17:22 Comment(3)
It almost sounds like you're asking, "Why isn't the document ready before it's ready?"Blurt
eh? Haven't you tried accessing a DOM element in script immediately after it's "declared"? Normally fine chuck.Airflow
I try to keep almost all of my scripts in external files so that they can be cached by the browser when the rest of my page content is dynamically generated. So no, I haven't tried accessing a DOM element from script prior to the dom-ready event, and I don't think it's a very good idea to do so.Blurt
N
4

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"></script>
<input type="hidden" value="236434" id="ixd">
<pre><script type="text/javascript">
document.writeln($('#ixd').val());
document.writeln(document.getElementById('ixd').value);
</script></pre>
Novice answered 15/6, 2009 at 17:37 Comment(1)
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.Airflow
S
4

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

Sulamith answered 15/6, 2009 at 17:27 Comment(7)
getElementById() should work for all elements preceding the scriptNovice
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.Airflow
@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 ;)Novice
@Novice I generally never use $(document).ready(), instead interspersing HTML with JS as it seems to reduce page load time (worth benchmarking!). Is this sensible?Airflow
@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 wayNovice
@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).Sulamith
@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 standardNovice
N
4

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"></script>
<input type="hidden" value="236434" id="ixd">
<pre><script type="text/javascript">
document.writeln($('#ixd').val());
document.writeln(document.getElementById('ixd').value);
</script></pre>
Novice answered 15/6, 2009 at 17:37 Comment(1)
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.Airflow
D
1

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" :)

Dupaix answered 15/6, 2009 at 17:28 Comment(0)
R
1

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.

Rustin answered 15/6, 2009 at 17:37 Comment(1)
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.Airflow
D
0

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?

Doradorado answered 15/6, 2009 at 17:27 Comment(1)
Yes, i.e. an ajax call (to insert into/update a DOM "placeholder" element) fired before the DOM is finished loadingAirflow

© 2022 - 2024 — McMap. All rights reserved.