JavaScript variable undefined on load; - javascript

I can't get following problem.
I define variables like this:
<script type="text/javascript">var myVar;</script>
<script type="text/javascript" src="/myScript.js"></script>
myScript.js looks something like this:
$(document).ready(function() {
myVar = new myClass();
myVar.init();
});
if I try to access the variable like this:
<div onclick="myVar.activate(x);">some content</div>
all is working fine, but if I do
<img src="path" onload="myVar.activate(x);"/>
I get an error "myVar is not defined". I don't get it.
<script type="text/javascript">var myVar;</script>
some DOM Elements
<script type="text/javascript" src="/myScript.js"></script>
<script type="text/javascript">myVar.activate(x);</script>
Is not working either?!?!! Weird, isn't it?
*x is generated serverside *

$(document).ready(function(){
// this function is executed after the entire document is ready,
// and it will fire after window.onload
myVar = new myClass();
myVar.init();
});
Here you are trying to access a method of myVar, but your .ready() function hasn't fired yet so myVar has not been set to new myClass(). It is still an undefined variable
<script type="text/javascript">
myVar.activate(x);
// this script executes *before* the code inside your document ready function,
// so this is *before* you have set myVar = new myClass();
var_dump(myVar);
// above should output 'undefined'
</script>
If you really need/want to call this method in an onload attribute, then you should set myVar to new myClass() in your inline script, like this:
<script type="text/javascript">
var myVar = new myClass();
myVar.init();
myVar.activate(x);
</script>

If it's absolutely necessary that your code to assign a value to myVar happen in the doc ready, a better way to handle this would be something like this:
$(document).ready(function() {
myVar = new myClass();
myVar.init();
$("#idOfMyImage").load(function() { myVar.activate(x); });
});
What happens here is that you are attaching the load handler only after the dom ready event is fired and myVar has a value assigned to it. If the image has already loaded by the time the doc ready fires, then this will execute immediately, it it hasn't, it will fire when the image loads. Now you've removed the race condition where you code depended on the order those two events would fire in (your original code might have worked if the server delivering the image was slow enough providing the data - what is probably happening is that the image you are loading is cached by your browser).
As a bonus, you've now got rid of the inline event handler which make a better separation of your HTML from your Javascript.

There is nothing scary here, you just doesn't declare the variable at a good time. When using online script, variable must be assigned before the browser read the DOM node.
In your code, you assign myVar on DOM ready, hence the browser already finished reading the DOM and throw an error.
My question now is why do you need to wait the DOM to be ready before creating an object? There sure have a work around.

The following function is executed when your HTML is completely rendered
$(document).ready(function() {
myVar = new myClass();
myVar.init();
});
And the following is rendered as soon as it's downloaded and added in the HTML by the browser:
<img src="path" onload="myVar.activate(x);"/>
So myVar cannot be defined, because when <img> is rendered by the page, ready() has not been called yet.
Same reason for your second example. myVar is null
You should remove:
$(document).ready(function() ...
And try again.

why not simply, depending on what x is and where it's declared, obviously:
$(document).ready(function() {
myVar = new myClass();
myVar.init();
myVar.activate(x);
});
the nett result should be the same without the error

Thanks to Billy Mathews, i do know why it is not working. Thank you very much!
This is now how i did it (not clean, but working!)
<script type="text/javascript" src="/myScript.js"></script>
myScript.js looks something like this:
$(document).ready(function() {
var ServerGeneratedValue = $('myID').html();
var myVar = new myClass();
myVar.init();
myVar.activate($ServerGeneratedValue);
});
Thank you very much to all answers!

Related

Calling a javascript function from other file

I have a javascript file that I'm am calling in the head of an HTML file, it's called custom.js, it defines this function:
var example = function(element){
console.log(element);
};
Then in the actual HTML document, just before the body tag closes, I try to initialize it by calling the same function like this
example('.header-background');
I get the error example is not a function, what exactly am I doing wrong? Thank you so much for your help.
here is a bit more context
<!DOCTYPE html>
<html>
<head></head>
<body>
// the main body of html
<script src="custom/custom.js"></script> // here is the file with the example function
example ('.header-background'); // here im calling the function
</body>
</html>
Change var example to window.example. If you declare a variable with var inside of a function or closure it isn't globally accessible.
e.g.,
function foo()
{
var test = 'hi';
}
console.log(test); // error, test isn't accessible
function foo()
{
window.test = 'hi';
}
console.log(test); // works
Global variables should generally be avoided there. There's most likely a better way to do what you want to do.
Make sure to the file where your function in the html page you are calling the function:
<script type="text/JavaScript" src="youtpathtothefile/custom.js"></script>
Hope it helps
Please make sure two things:
your javascript file is loaded after jQuery library.
your javascript is loaded after the every dom in the html file has finish loading.
Maybe that could help you.

inline javascript function not detecting script loaded via code

This works:
<script src="some.js">
<script>
afunction(); //this function is in some.js
</script>
Then I thought to improve the page speed of the site and load some.js like this
var element = document.createElement("script");
element.src = "some.js;
document.body.appendChild(element);
and now the function doesn't exist and i get an error.
Is there a solution to this?
As others pointed out above, some of the errors you might be encountering are perhaps due to missing " and so on. Assuming that you have every syntax correct, this approach will fail because how HTML parsing happens:
Assuming that you've got this code in the <HEAD> section:
When the parser (in your browser) reads the file stream where you've got this code, it is going to construct the DOM as it is doing so. This means that when it gets to the point in your code where you are telling it to append as a child your script node element to the body, it is going to fail because document.body does not exist yet and this is an error.
Assuming that you've got this code in the <BODY> section:
Then by the mere that you have attached a SCRIPT node element to the DOM does not imply that the file has been loaded by the Javascript engine and processed the content of "some.js". Therefore, when "aFunction" is called, it is undefined.
Finally, i do not think you gain anything peformance-wise by loading your script after your document has loaded.
There are many Syntax Error in your Script
But the answer to the actuall question is window.onload
<script>
window.onload = function () {
afunction();
}
</script>
Syntax Need Correction
1) Close Script Tag :
<script src="some.js"></script>
<script>
afunction(); //this function is in some.js
</script>
2) Missing double quote(")
var element = document.createElement("script");
element.src = "some.js";
document.body.appendChild(element);
The function needs to be written globally like,
$(document).ready(function () {
});
afunction () {
}
in 'some.js' script.
and access tat function using div tag.
<div id = 'a' onClick='afunction()'>
</div>
The problem is caused by calling the function too soon after the node has been appended. All you need is a timeout.
<script type="text/javascript">
var elem = document.createElement("script");
elem.src = "scripts/test.js";
elem.type="text/javascript";
//
function runTest()
{ document.body.appendChild(elem);
setTimeout("alertThis('This is a test')",50);
}
window.onload=runTest;
</script>
The external js for this example says
function alertThis(msg) { alert(msg); }
It runs correctly in all browsers.

How to hold called function until document.body not return complete

I am creating a function alerts() and call it in my script tag, that is in <head>
Actully currenty i am woking on live editor,so i have to put users code in head,normally all function call in head but here ,it shows error !
I want to hold the user code and run when DOM completes!
like:
HTML
<head>
<script src='alertResource.js' type ='text/javascript' ></script>
<script>
alerts();
<script>
</head>
alertResource.js
function alerts(msg) {
var _M_DoWn = { x: '', y: '', isdown: '' };
var _A = document.createElement('HTML_alert');
_A.id = "codeit_HTML_alert";
insertAfter(document.body, _A);
}
function insertAfter(refrNode, newNode) {
refrNode.parentNode.insertBefore(newNode, refrNode.nextSibling);
}
So, whenever I call the alerts() it shows me an error in my console :
Error
Uncaught TypeError: Cannot read property 'parentNode' of null
I guess the error appears because my function gets called before DOM is loaded. Now I want to do something like: delay any function call until DOM is ready. I know how to check readystate but not able to implement it, as per my case.
Any idea? What I need to do to achieve this?
When you call to "alerts" the document is not fully loaded and "refrNode.parentNode" return null.
Try this, without jQuery
<body onLoad="alerts();">
....
</body>
call your function after page is completely loaded by using this:
Using JavaScriopt
document.addEventListener('DOMContentLoaded', function() {
alerts();
}, false);
Using JQuery
$(function(){
alerts();
});
Please use this. (Javascript way)
window.onload=function(){SomeJavaScriptCode};
<body onload="SomeJavaScriptCode">
Depending on if you need to support IE8 or not, you could do this:
document.addEventListener('DOMContentLoaded', function(){
alerts();
});

Variable not accessible when initialized outside function

When I use code like this, it works fine:
function removeWarning() {
var systemStatus = document.getElementById("system-status");
systemStatus.innerHTML = "";
}
function indicateInvalidUsername() {
var systemStatus = document.getElementById("system-status");
systemStatus.innerHTML = "Invalid username";
}
However, when I then want to move the systemStatus to be a global variable, it doesn't work:
var systemStatus = document.getElementById("system-status");
function removeWarning() {
systemStatus.innerHTML = "";
}
function indicateInvalidUsername() {
systemStatus.innerHTML = "Invalid username";
}
What am I supposed to be doing here?
It really depends on where your JavaScript code is located.
The problem is probably caused by the DOM not being loaded when the line
var systemStatus = document.getElementById("system-status");
is executed. You could try calling this in an onload event, or ideally use a DOM ready type event from a JavaScript framework.
Make sure you declare the variable on "root" level, outside any code blocks.
You could also remove the var altogether, although that is not recommended and will throw a "strict" warning.
According to the documentation at MDC, you can set global variables using window.variablename.
My guess is that the system-status element is declared after the variable declaration is run. Thus, at the time the variable is declared, it is actually being set to null?
You should declare it only, then assign its value from an onLoad handler instead, because then you will be sure that it has properly initialized (loaded) the element in question.
You could also try putting the script at the bottom of the page (or at least somewhere after the system-status element is declared) but it's not guaranteed to always work.
Declare systemStatus in an outer scope and assign it in an onload handler.
systemStatus = null;
function onloadHandler(evt) {
systemStatus = document.getElementById("....");
}
Or if you don't want the onload handler, put your script tag at the bottom of your HTML.
A global variable would be best expressed in an external JavaScript file:
var system_status;
Make sure that this has not been used anywhere else. Then to access the variable on your page, just reference it as such. Say, for example, you wanted to fill in the results on a textbox,
document.getElementById("textbox1").value = system_status;
To ensure that the object exists, use the document ready feature of jQuery.
Example:
$(function() {
$("#textbox1")[0].value = system_status;
});
To define a global variable which is based off a DOM element a few things must be checked. First, if the code is in the <head> section, then the DOM will not loaded on execution. In this case, an event handler must be placed in order to set the variable after the DOM has been loaded, like this:
var systemStatus;
window.onload = function(){ systemStatus = document.getElementById("system_status"); };
However, if this script is inline in the page as the DOM loads, then it can be done as long as the DOM element in question has loaded above where the script is located. This is because javascript executes synchronously. This would be valid:
<div id="system_status"></div>
<script type="text/javascript">
var systemStatus = document.getElementById("system_status");
</script>
As a result of the latter example, most pages which run scripts in the body save them until the very end of the document. This will allow the page to load, and then the javascript to execute which in most cases causes a visually faster rendering of the DOM.

Problem accessing global javascript variables

My application has something like the following structure
window.object1;
window.object2;
$(document).ready(function() {
window.object1 = new type1object();
});
function type1object() {
//lots of code
this.property = 'property';
window.object2 = new type2object();
}
function type2object() {
//lots of code
this.property = new type3object();
}
function type3object() {
//lots of code
console.log(window.object1);
this.property = window.object1.property;
}
The problem is that whenever I try to access window.object1 from anywhere other than the document ready callback it comes back as undefined, this is even though when I inspect the DOM window.object1 is defined exactly as I expect it to be.
I've tried doing the same as above but using simple global variables instead (i.e. var object1 instead of window.object1) ... Tried declaring initial dummy values for object1 and object2 in various places... but run up against the same problem.
Does anyone know why I can't access my global variables globally?
You have to make sure you are evaluating window.object1 after initiating it.
That is, in your case, only after document.ready finished executing
If you look at this example below you can see that at click both are initialized.
<html>
<body>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
<script>
$(document).ready(function() {
window.object1 = new type1object();
window.object2 = new type2object();
//console.log(window.object1);
});
$(document).click(function(){
console.log(window.object1);
console.log(window.object2);
});
function type1object() {
}
function type2object() {
}
</script>
Since you are not setting the value of window.object1 until you are inside the document ready function, you wont be able to access it until it has run.
Nothing in your code shows that you couldn't just remove that document ready call altogether. It is generally reserved for waiting for elements to load in the dom, which it doesn't seem like you are doing. If you somehow do have elements that need to be waited on inside of code that isn't there, just put your script at the bottom of the page, right above the tag. This will do the equivalent of document ready.
writing the code really stripped out made the answer fall out - I was creating something that referenced object1 during the construction of object1.
So I changed it to this, so that the object exists (though with no content) before anything tries to reference it:
window.object1;
window.object2;
$(document).ready(function() {
window.object1 = new type1object();
window.object1.construct();
});
function type1object() {
//lots of code
this.construct = function() {
this.property = 'property';
window.object2 = new type2object();
};
}
function type2object() {
//lots of code
this.property = new type3object();
}
function type3object() {
//lots of code
console.log(window.object1);
this.property = window.object1.property;
}

Categories