tags:

views:

123

answers:

8

Is it possible to define some global variables above your functions on the same .html page?

    <script type="text/javascript">

        birthYear = document.getElementById('<%=ddlBirthYear.ClientID %>');
        birthMonth = document.getElementById('<%=ddlBirthMonth.ClientID %>');
        birthDay = document.getElementById('<%=ddlBirthYear.ClientID %>');

        function ValidateCardField(validator, args)
        {
            if (args.Value.length > 0)
             args.IsValid = true;
            else
             args.IsValid = false;
     }
...

I'm getting nulls for the variable values.

+1  A: 

Yes, it's possible to declare global variables but they are within the same namespace as the function definitions, if the variables are not defined in the function bodies and accessed inside, they descend upwards and reach the global/outer scope variables and use those.

OP - you should try moving your <script> block to right before the end body tag, that or adopt a domready/onload function.

meder
what do you mean by namespace? I've just got a bunch of Javascript functions inside a script tag in my ASP.NET .aspx page.
CoffeeAddict
+1  A: 

The var keyword in Javascript means those variables are not global (global being unfortunately the default) but function-scoped -- not much point in using var outside of any function's scope (and potentially confusing), though it's legal. But the beauty of var and function scopes is to allow you to define rich closures, one of the truly beautiful aspects of Javascript -- i.e., if you example code is defined inside some outer function, and the outerfunction returns ValidateCardField or an object having the latter as one of its value, that inner function will get to access the non-global variables defined in its outer function, while the rest of the world is shielded off from them -- a much better way to do "private fields" than the Java/C++ approach of private as a keyword...!

Alex Martelli
so if I moved them outside my functions and at the top right before my javascript script tag, then they must not be able to access them then.
CoffeeAddict
-1 While your insight is precise, the answer does not help him with his problem.
Josh Stodola
@coffeeaddict, of course they must be inside a script tag -- otherwise they'll be taken as text for HTML formatting, not as JS statements! What do you mean "**before**" your script tag?! If they're inside said tag, and outside of function scope, they'll be accessible throughout and the `var` keyword's redundant. @Josh, tx for explaining the downvote -- even though I disagree with you, I respect you for explaining, much as I despise anonymous, unexplaining downvoters!-)
Alex Martelli
+1  A: 

EDIT

I see what the problem is. The DOM hasn't completely loaded when you're calling those in the global context (when it was called from the function, the DOM had already loaded).

In this case, you are probably best off using a framework like jQuery or Prototype.

See http://docs.jquery.com/Events/ready for running code after the DOM is loaded in jQuery and http://www.prototypejs.org/api/document/observe for prototype

e.g. in jQuery:

 $(document).ready(function () {
    birthYear = document.getElementById('<%=ddlBirthYear.ClientID %>');
    birthMonth = document.getElementById('<%=ddlBirthMonth.ClientID %>');
    birthDay = document.getElementById('<%=ddlBirthYear.ClientID %>');
 });

and in Prototype:

 document.observe("dom:loaded", function() {
    birthYear = document.getElementById('<%=ddlBirthYear.ClientID %>');
    birthMonth = document.getElementById('<%=ddlBirthMonth.ClientID %>');
    birthDay = document.getElementById('<%=ddlBirthYear.ClientID %>');
 });
Jonathan Fingland
I want all functions to have access to those 3 variables
CoffeeAddict
+3  A: 

Yes it is possible to have global variables, and you seem to be doing it correctly (although you should probably be using the var keyword to define them). The problem you are currently facing is that you are trying to access elements in the DOM before they have been rendered. What you need to do is define your variables globally, and then wait for the page to load before assigning them to the appropriate DOM elements...

var birthYear, birthMonth, birthDay;

window.onload = function() {
  birthYear = document.getElementById('<%=ddlBirthYear.ClientID %>');
  birthMonth = document.getElementById('<%=ddlBirthMonth.ClientID %>');
  birthDay = document.getElementById('<%=ddlBirthYear.ClientID %>');
}

Now the variables will be globally accessible after the page loads.

Josh Stodola
I tested this and it's correct.
Mike Blandford
onload will work, but will fire later than DOMContentLoaded (or the framework abstractions doing the same thing). If some resources have not yet loaded by the time the user causes a function requiring these to be called, it will fail.
Jonathan Fingland
A: 

If you're unsure about this kind of thing, you can write up a quick test program and test it.

<html><head>
<script type="text/javascript">
var x = document.getElementById("bob");

function helloWorld(){
    alert(x == null);
}
</script>
</head>
<body onload="javascript:helloWorld();">
<div id="bob">hello back!</div>
</body>
</html>
Mike Blandford
+1  A: 

The issue isn't one of scoping, but one of execution order. In your original implementation, the DOM elements aren't retrieved until the function is fired. Now, the elements are looked-up as soon as the JavaScript is parsed, which is presumably before the document (and hence, the elements) are loaded - hence they are null when the function is invoked.

harto
+2  A: 

Your problem may be that the script is being executed before the DOM has been fully initialized. So when these lines of code run:

    birthYear = document.getElementById('<%=ddlBirthYear.ClientID %>');
    birthMonth = document.getElementById('<%=ddlBirthMonth.ClientID %>');
    birthDay = document.getElementById('<%=ddlBirthYear.ClientID %>');

no elements with those IDs exist yet, as far as the browser is concerned. One way to fix that would be to declare the variables as null, and then initialize them in a function that you call in the page's (client-side!) load handler.

It's probably also worth checking (by viewing the source in your browser) that those ClientID values are what you think they are, and that elements with those IDs really do exist in the rendered HTML.

Sixten Otto
A: 

I think the problem is not related to the scope of variables, but to when you try to assign them with references to some page elements. Probably the script is running before all the page elements have been loaded. So the getElementById function will fail when trying to find an element that does not exist. Wrap your script in the onLoad event of the window object, like this:

window.onload = function () (
     // Your code here ...
);
vinuz