Calling a JavaScript function from another function in a different JS file - javascript

I have a web page displaying an HTML5 canvas. When the web page loads, the following JavaScript function is called:
window.onload = function(){
var sources = {};
sources[0] = document.getElementById("building").src,
sources[1] = document.getElementById("chair").src,
sources[2] = document.getElementById("drink").src,
sources[3] = document.getElementById("food").src,
sources[4] = document.getElementById("fridge").src,
sources[5] = document.getElementById("land").src,
sources[6] = document.getElementById("money").src,
sources[7] = document.getElementById("oven").src,
sources[8] = document.getElementById("table").src,
sources[9] = document.getElementById("van").src,
sources[10] = document.getElementById("burger").src,
sources[11] = document.getElementById("chips").src,
sources[12] = document.getElementById("drink").src,
sources[13] = document.getElementById("franchiseFee").src,
sources[14] = document.getElementById("wages").src,
sources[15] = document.getElementById("admin").src,
sources[16] = document.getElementById("cleaners").src,
sources[17] = document.getElementById("electricity").src,
sources[18] = document.getElementById("insurance").src,
sources[19] = document.getElementById("manager").src,
sources[20] = document.getElementById("rates").src,
sources[21] = document.getElementById("training").src,
sources[22] = document.getElementById("water").src,
sources[23] = document.getElementById("burger").src,
sources[24] = document.getElementById("chips").src,
sources[25] = document.getElementById("drink").src,
sources[26] = document.getElementById("creditors").src,
sources[27] = document.getElementById("electricity").src,
sources[28] = document.getElementById("food").src,
sources[29] = document.getElementById("hirePurchase").src,
sources[30] = document.getElementById("loan").src,
sources[31] = document.getElementById("overdraft").src,
sources[32] = document.getElementById("payeTax").src,
sources[33] = document.getElementById("tax").src
loadImages(sources, drawImage);
drawGameElements();
drawDescriptionBoxes();
};
This function loads some images from the hidden section of the HTML into the JavaScript, and draws them to the canvas by calling the 'drawImage()' function on each image in the 'sources' array. It then calls the 'drawGameelements();' function, which draws a few more things to the canvas, and finally, I then want to call the 'drawDescriptionBoxes()' function.
This function however, is in a separate JS file to the rest of the code, and when I view the page in a browser, although 'loadImages()' and 'drawGameElements()' are called, and draw what they're supposed to to the canvas, I get an error in the console saying:
ReferenceError: drawDescriptionBoxes is not defined
which I assume means that I haven't referenced the function correctly, since it's not in the same file as where I'm calling it.
What I'm wondering is how do I call this function from the other file? Would it be something like: filename.js.drawDescriptionBoxes ?

There's really two possibilities why the drawDescriptionBoxes function is undefined.
1) It's out of scope
In JavaScript, variables exist in some sort of scope. This maybe global, such as:
<script>
var foo = 123; //foo can be referenced anywhere, it's global!
</script>
Or scoped within another block of code:
function myFunc()
{
var bar = function () //bar can only be accessed within myFunc
{
};
};
//bar() here is undefined
There's a possibility your drawDescriptionBoxes function is not in the global scope.
2) It's not yet defined when your code runs
It's also possible you have some code like this:
File 1
<script>
var result = someFunc(123);
</script>
File 2
<script>
function someFunc(x)
{
return x * 2;
}
</script>
If File 2 gets included after File 1, someFunc doesn't yet exist when file 1 is run. You can get around this by running everything after the document fully loads, using event handlers. If var result = someFunc(123); was run in the onload event, it would work fine regardless of what file someFunc was defined in.
Hope this helps!

if drawDescriptionBoxes is defined as a global function, such as
function drawDescriptionBoxes() {
}
then the fact that it is not found means that the javascript file containing it did not load. Show how you include this file in html and how the function is defined.

Related

javascript: save a variable's value between calls?

I have some code that looks like this:
createEntity = function (imageSource, baseX, baseY) {
tmpIndex = images.length;
images[tmpIndex] = new Image();
entities[tmpIndex] = new Entity;
images[tmpIndex].onload = function () {
entities[tmpIndex].ready = true;
// How do I get the line above to use the value of tmpIndex
// that existed when it was created?
// That is to say, I want the images[1].onload function to
// change entities[1].ready, not entities[4].ready
// (assuming I created 5 objects sequentially
// before any images finished loading)
}
images[tmpIndex].src = imageSource;
entities[tmpIndex].x = baseX;
entities[tmpIndex].y = baseY;
}
createEntity("images/background.png", 0, 0);
createEntity("images/pawn1.png",0,0);
createEntity("images/pawn2.png",30,30);
createEntity("images/pawn3.png",60,60);
createEntity("images/pawn4.png",90,90);
The problem is that when I load all 5 images sequentially, as the above code shows, my onload function triggers with the current value of tmpIndex, not the one that existed when the function was created. Is there a simple way to make it so that the entities[somenumber].ready is toggled appropriately?
You need to declare tmpIndex as a local variable. To do this change
tmpIndex = images.length;
to
var tmpIndex = images.length;
Why does tmpIndex have to be visible outside of createEntity function? If it doesn't, just declare it inside your function, like this: var tmpIndex = images.length;
Your onload callback will be able to read its value even after the createEntity function has finished executing because will keep a reference to the scope where it was created.
Every execution scope is different, so every time you call createEntity you create different scope and a different onload callback function which stores a reference to that execution scope, and therefore is able to consume variables defined there.
Exactly. Here's a working JSfiddle example catching onerror instead on onload : http://jsfiddle.net/bdn2775k/1/
Here's the revelant part :
//Don't forget to declare a local variable !
var tmpIndex = images.length;

javascript function to save data in global variables

I have problems to make this function (addMe) to save the data from img and span from div childBox in two global arrays?
I think something is wrong in the function but can't see what.
This is my code.
Global var: //before function init
var imgSrclist = [];
var imgSpanlist = [];
Function:
function addMe(obj) {
var el = document.getElementById(obj.getAttribute('data-img'));
var parent = el.parentNode.getElementsByClassName('childBox')[0],
imgSRC = parent.getElementsByName('img')[0].src,
spanTXT = parent.getElementsByTagName('span')[0].innerHTML;
if (obj.checked) {
imgSpanlist[el.id].imgSrc.push(imgSRC);
imgSrclist[el.id].imgSpan.push(spanTXT);
} else {
var imgIx = imgSrclist[el.id].imgSrc.indexOf(imgSRC),
spanIx = imgSpanlist[el.id].imgSpan.indexOf(spanTXT);
imgSrclist[el.id].imgSrc.splice(imgIx);
imgSpanlist[el.id].imgSpan.splice(spanIx);
}
}
The data should be saved on global variabels because it will be used later in a new window when you push a button. The script code for the new windows starts with this:
var imgSrclist = window.opener.imgSrclist;
var imgSpanlist = window.opener.imgSpanlist;
EDIT: The code is now updated, so the arrays is declared. But the problem is that the imgsrc and span text dosen´t comes to the new window. are they saved in the array at all?
Two things I want to mention is;
var imgSrclist;
var imgSpanlist;
should declare as an array and
function init() {
imgSrc=[]; //Empty array
imgSpan=[]; //Empty array
}
why they are declare as an array as you are not using these as an array.
I have updated two above changes, here is your code.

Javascript - canvas - drawImage does not work

I have read all the other similar posts but I don't understand why it I have this problem.
I have a canvas (#canvas) and an image (hero.png) on the page, and a JS file loaded at the end of the body. In the JS code...
This works:
var game = {};
game.canvas = document.getElementById('canvas');
game.ctx = game.canvas.getContext("2d");
game.draw = function(){
game.ctx.drawImage(game.hero, 200, 200);
}
game.hero = new Image();
game.hero.src = "hero.png";
game.hero.onload = game.draw;
And this doesn't work:
var game = {};
game.canvas = document.getElementById('canvas');
game.ctx = game.canvas.getContext("2d");
game.hero = new Image();
game.hero.src = "hero.png";
game.hero.onload = game.draw;
game.draw = function(){
game.ctx.drawImage(game.hero, 200, 200);
}
Nothing appears. No error in the console. Why???
Thanks!
You can call functions before define them only with this syntax:
function draw()
{
//COde here
}
By writting
game.draw = function(){};
You define a method to your object, you don't define a JavaScript function: that's why you can't call it before define it :)
In your second hunk of code, you're defining
game.hero.onload = game.draw;
When game.draw is undefined, so your onload is undefined and nothing happens when the image is done loading.
game.draw is not set when you assign it in your second example, you are copying an undefined value into hero.onload.
One workaround is to wrap the function you want to call in an anonymous function and call yours from there:
game.hero.onload = function(){ game.draw(); };
Have in mind that if hero loads before the definition of game.draw is finished, this code will fail.

can't get jqPlot chart to show line from Variable

I'm using jqPlot to plot some points in my webApp, so I'm trying this:
var plot10 = $.jqplot ('heightChartDiv', [[3,7,9,1,5,3,8,2,5]]);
and it works fine, I this exact chart here
but when I take it out, to give it a value, like so:
$(document).ready(function(){
var serie1 = [[3,7,9,1,5,3,8,2,5]];
}
function doGraph(){
var plot10 = $.jqplot ('heightChartDiv', serie1);
}
It doesn't work. am I declaring the variable wrong? please HELP!
~Myy
Your variable scoping is all off. The variable serie1 has local scope to the anonymous function defined in $(document).ready event. Read up on javascript scope here and here.
Perhaps something like this:
// the document ready will fire when the page is finished rendering
// inline javascript as you've done with your doGraph will fire as the page renders
$(document).ready(function(){
// first define graph function
// make the series an argument to the function
doGraph = function(someSeries){
var plot10 = $.jqplot ('heightChartDiv', someSeries);
}
// now call the function with the variable
var serie1 = [[3,7,9,1,5,3,8,2,5]];
doGraph(serie1);
}
EDITS IN RESPONSE TO COMMENT
See this below example:
$(document).ready(function(){
var a = 1;
someFunc = function(){
var b = 2;
alert(a);
}
someFunc(); // this works
alert(b); // this produces an error
});​
Here the variable a is considered global to the function someFunc. A variable declared in someFunc, though, does not persist outside of it.

Calling an object function from onload event makes it lose the context

I wanted to call a function when all required images are loaded. The number of images is known in advance, so I tried attaching a function call to the onload event of each image and count the number of times it was called.
<html>
<head>
<script>
var tractor;
function Tractor()
{
this.init_graphics();
}
Tractor.prototype.init_graphics = function()
{
this.gr_max = 3;
this.load_count = 0;
this.loading_complete(); // #1 test call, works OK
this.img1 = new Image();
this.img1.onload = this.loading_complete; // #2 gets called, but gr_max = undefined, load_count = NaN
this.img1.src = "http://dl.dropbox.com/u/217824/tmp/rearwheel.gif"; //just a test image
}
Tractor.prototype.loading_complete = function()
{
this.load_count += 1;
alert("this.loading_complete, load_count = " + this.load_count + ", gr_max = " + this.gr_max);
if(this.load_count >= this.gr_max) {this.proceed();}
};
function start()
{
tractor = new Tractor();
}
</script>
</head>
<body onload="start();">
</body>
</html>
When it's just called from another function of the object (see #1), it works just as I expected. When, however, it's called from onload event (see #2), the variables become "undefined" or "NaN" or something. What's happening? What am I doing wrong? How do I make it work?
I don't remember ever creating my own objects in Javascript before, so I certainly deeply apologize for this "what's wrong with my code" kind of question. I used this article as a reference, section 1.2, mainly.
Just in case, I put the same code on http://jsfiddle.net/ffJLn/
bind the context to the callback:
this.img1.onload = this.loading_complete.bind(this);
See: http://jsfiddle.net/ffJLn/1/ (same as yours but with this addition)
Here's an explanation of how bind works in detail: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
The basic idea is that it makes this in the bound function equal to whatever you pass as the parameter to bind.
Another option is to create a closure:
var self = this;
this.img1.onload = function() { self.loading_complete() };
Closures are functions that keep references to their context (in fact, all functions in javascript work this way). So here you are creating an anonymous function that keeps a reference to self. So this is another way to maintain context and for loading_complete to have the right this.
See: http://jsfiddle.net/ffJLn/2/ (same as yours but with the second possibility)
When #2 gets called, your this has changed. this now refers to the new Image() rather than the Tractor object.
Try changing...
this.img1.onload = this.loading_complete;
to
var that = this;
this.img1.onload = function() { that.loading_complete(); };
You can now use es6 arrow functions which provide lexical binding:
this.img1.onload = () => { this.loading_complete(); };

Categories

Resources