Processing.js Can't Access a Global JavaScript Variable - javascript

So I have a switch statement inside my Processing file which changes a variable named 'zooText'. zooText is declared in a JavaScript file named text.js. However, when for some reason, Processing is unable to access, or change, the variable.
The expected behavior would for zooText to change to whatever it is set to in the switch statement. However, the <p> only says "undefined".
Here is the switch statement:
switch(sceneNum){
case 1:
zooText = "Welcome to the office. This is where we organize all our files. Important files include our certification by the AZA (Association of Zoos & Aquariums), and other"
+ " important documents which certify we keep our animals healthy and happy";
break;
case 2:
zooText = "This is the education area. Here we teach children about the importance of conservation, and protecting our planet. According to some people,"
+ "we're really influential!";
break;
case 3:
zooText = "Scene 3";
break;
case 4:
display = "This is the Aquatic Area. Although most of these animals have natural roaming areas of hundreds of miles, we like to keep them in small enclosures";
break;
And here is the relevant JavaScript:
var zooText;
function changeText(){
document.getElementById("demo").innerHTML = zooText;
}
setTimeout(changeText, 100);
And finally, the relevant HTML:
<head>
<title>Zoo Ethics</title>
<link rel='stylesheet' href='style.css' type='text/css'>
<script src="processing.js" width="1000" height="800"></script>
<script src='text.js'></script>
</head>
<body style="background-color:#e0eaf9">
<h1>Explore the Zoo!</h1>
<p id="demo"></p>
<canvas id="sketch" data-processing-sources="zoos.pde"></canvas>
<script src='text.js'></script>
I've been struggling with this for hours. I've kind of narrowed down the problem to maybe the sketch not being loaded before the JavaScript, or something of a similar manner.

Try importing the text.js file first and then the processing.js
<script src='text.js'></script>
<script src="processing.js" width="1000" height="800"></script>

I was able to find a workaround by simply including pure JavaScript in the .pde file. I created a variable named zooText, completely deleted the text.js file, and then simply made the .pde file update the <p> in the draw() function.

This truly depends on how you call your scripting. If it is just base code inside Processing.js then it will run the moment it is loaded, even before the DOM and all other scripts are loaded. One option is to reverse the order they are loaded as stated. However this can (for various reasons such as server lag) still potentially produce the same issue. If this is how it's run then you might look into placing the base/original command inside an init() function. Then have event run on document ready:
Inside processing.js:
function init(){
//call processing.js functions/commands here
}
//remaining processing.js function definitions here
if (document.readyState !== 'loading') {
init()
} else {
// the document hasn't finished loading/parsing yet so let's add an event handler
document.addEventListener('DOMContentLoaded', init)
}
Doing it this way will help ensure all scripting is loaded before running. If you have/user jQuery the last part can be simplified with something like $(document).ready(function(){init()});

<head>
<title>Zoo Ethics</title>
<link rel='stylesheet' href='style.css' type='text/css'>
<script src='text.js'></script> <---I MOVED ABOVE PROCESS.JS
<script src="processing.js" width="1000" height="800"></script>
</head>
<body style="background-color:#e0eaf9">
<h1>Explore the Zoo!</h1>
<p id="demo"></p>
<canvas id="sketch" data-processing-sources="zoos.pde"></canvas>
<script src='text.js'></script> <---THIS SEEMS LIKE A DUPLICATE

Related

access a variable declared on a separate JavaScript file in html

I have 2 files the first one is an HTML file the other one is a javascript file. What I was trying to do was define a variable on the javascript file and access it on the Html side. Is it possible? A rough code is attached below but it doesn't work I get favColor is not defined error. thanks in advance.
JS Side
const favColor = "red"
Html side
<script src="pathtojsfile"></script>
<p id="insertHere"></p>
<script>
document.getElementById("insertHere").innerHTML = favColor
</script>
It is widely considered bad practice to work with global variables. To avoid it, you can make use of ECMAScript Modules, introduced back in 2015 with ES6/ES2015.
This allows your first Javascript, let's name it colors.module.js to export the variable:
export const favColor = 'red';
Then, in your script that needs to access this variable, you import it:
import { favColor } from '/path/to/js/modules/colors.module.js';
For that to work, you need your importing script to have type=module attribute, and the import must be done on top of your Javascript. The script you import from does not need to be included in the page.
Here's some helpful links to get you started with modules:
ES Modules Deep Dive
Javascript Modules on MDN
Flavio Copes' take on ES Modules
I've set up a tiny github repo demonstrating this very basic usage of an ES module.
If modules are not an option, e.g. because you must support IE 11, or your build stack doesn't support modules, here's an alternative pattern that works with a single namespace object you attach to the global object window:
// colors.module.js
window.projectNamespace = window.projectNamespace || {};
projectNamespace.colors = window.projectNamespace.colors || {};
projectNamespace.colors.favColor = 'red';
and in your page you access it from that name space:
document.getElementById("insertHere").innerHTML = window.projectNamespace.colors.favColor;
This way you have a single location to put all your globally accessible variables.
As the code is written in your example it should work fine. Just like my example here:
<script>
const favColor = "red";
</script>
<p id="insertHere"></p>
<script>
document.getElementById("insertHere").innerHTML = favColor;
</script>
But there can be a number of issues if the code is not like this. But the JavaScript code could just go in the same file. Try to separate the html from the JS like this (the code in the script element could be moved to it's own file):
<html>
<head>
<script>
const favColor = "red";
document.addEventListener('DOMContentLoaded', e => {
document.getElementById("insertHere").innerHTML = favColor;
});
</script>
</head>
<body>
<p id="insertHere"></p>
</body>
</html>
Here I'm also adding the eventlistener for DOMContentLoaded, so that I'm sure that the document is loded into the DOM.
Where your variable is declared is not the problem per se, but rather the loading order of scripts.
If you want to make sure external scripts are loaded before you execute yours, you can use the load event of window object. It will wait until all resources on your page are loaded though (images, css, etc.)...
const myvar = "Hey I'm loaded";
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
<script>
//console.log(myvar); //<- fails
window.addEventListener('load', e => {
document.querySelector('#insertHere').innerHTML = myvar;
});
</script>
</head>
<body>
<p id="insertHere"></p>
</body>
</html>
Or you can put all your code in js files, and they will be invoked in the order they are declared.
Edit
Given objections and more questions popping in the comments, I'll add this. The best and cleanest way to achieve this remains to put your code in a .js file of its own and put all your <script> tags inside <head>, with yours last, as it relies on others to run.
Then you can either add the attribute defer to your <script> or have everything wrapped in an event handler for DOMContentLoaded so that it gets run after the DOM is fully loaded.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
<script src='other1.js'></script> <!-- let's say this one declares myvar -->
<script src='other2.js'></script>
<script src='other3.js'></script>
<script src='myscript.js'></script>
</head>
<body>
<p id="insertHere"></p>
</body>
</html>
myscript.js
window.addEventListener('DOMContentLoaded', e => {
document.querySelector('#insertHere').innerHTML = myvar;
});

Using functions from other files in JavaScript

I'm making a game in JS using P5, and I came upon a problem.
In my html file I have references to .js files:
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.3/p5.min.js"></script>
<script src="main.js"></script>
<script src="isKeyPressed.js"></script>
<script src="blocks.js"></script>
<script src="player.js"></script>
</head>
<body>
</body>
</html>
I have one .js file defining the function isKeyPressed():
function isKeyPressed(keyQuery) {
var did = false;
for(var i = 0; i < keysPressed; i++) {
if(keysPressed[i] === keyQuery) {
did = true;
}
}
return did;
}
I reference this in another object inside player.js:
player.motion = function() {
if(isKeyPressed('w')) {
this.velocity.add(0,-5);
}
if(isKeyPressed('s')) {
this.velocity.add(0,5);
}
if(isKeyPressed('a')) {
this.velocity.add(-5,0);
}
if(isKeyPressed('d')) {
this.velocity.add(5,0);
}
}
But when I try to call player.motion, I get the error:
Uncaught TypeError: isKeyPressed is not a function
Does anyone know why this is occurring?
For the record, I don't think the accepted answer is correct. Specifically, I don't think the accepted answer really changes anything from what you were originally doing. My guess is that you had another problem in your code (like a syntax error) that was causing this error, and you fixed that in the process of implementing the suggested solution. So while it might look like the solution fixed your problem, really it was something else.
I'm providing this alternative answer so you don't think you have to define your JavaScript in your html directly, as that is definitely not the case.
I tried testing out your setup by creating a smaller example consisting of three files:
index.html
<!DOCTYPE html>
<html>
<head>
<script src="one.js"></script>
<script src="two.js"></script>
</head>
<body onload="printObj()">
</body>
</html>
one.js
function printOne(){
console.log("one");
}
two.js
var obj = {};
obj.printTwo = function(){
console.log("two");
printOne();
}
function printObj(){
obj.printTwo();
}
This is pretty much exactly what your setup is, and it works fine. You absolutely do not need to put your JavaScript in your html. As long as the JavaScript files are correctly loaded in the proper order, then you can use functions and variables from one file in another file.
There are two main things that could cause your problem:
Are your files correctly loaded?
Are there any syntax errors you haven't noticed? (This is my guess as to what caused your original problem.) Check the JavaScript console, and try running some test code to actually run the functions you're trying to call.
Did you get all the file names correct?
Are you behind a firewall, or are there other network problems that might cause a problem with loading?
Are your files loaded in the proper order?
For file two.js to access code defined in one.js, you have to make sure one.js is loaded before two.js. It looks like you've done this correctly, but are you sure the JavaScript is where you think it is?
In other words, are you sure it was in player.js and not in main.js?
You might want to get rid of this ambiguity by placing related JavaScript in the same file. It doesn't make a ton of sense to have one file define a keysPressed array and then another file use that array to define an isKeyPressed() function. Just put them in the same file, and make sure that file is loaded before other files that use it.
The accepted answer doesn't change anything with regard to when stuff is loaded. Unless you had a syntax error, or the player.motion() function was actually in the main.js file, or you had a network loading problem, your code should have worked. So one of those things must be your actual problem. You do not have to define your JavaScript in your html for it to work.
I recommend not making a file name have capitals. So change it from
<script src="isKeyPressed.js"></script>
to
<script src="iskeypressed.js"></script>
also change the file name too.
You could try something like this
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.3/p5.min.js"></script>
<script src="main.js"></script>
<script src="isKeyPressed.js"></script>
<script src="blocks.js"></script>
<script src="player.js"></script>
<script>
player.motion = function() {
if(isKeyPressed('w')) {
this.velocity.add(0,-5);
}
if(isKeyPressed('s')) {
this.velocity.add(0,5);
}
if(isKeyPressed('a')) {
this.velocity.add(-5,0);
}
if(isKeyPressed('d')) {
this.velocity.add(5,0);
}
}
</script>
</head>
<body>
</body>
</html>
This is importing all functions from the isKeyPressed.js file and therefore you are able to reference it in the <script> tag. You were not able to use isKeyPressed.js's functions in player.js because you cannot reference it.

How define server variable into javascript context?

When I have a variable defined into server context, sometimes I need use it into javascript context; for example the session id.
What's the better way to do it?
I want to separate javascript files and view files (in my case jsp); for the moment I have found 2 ways:
1) myVariables.js.jsp: create a jsp file that returns javascript code
myLib = {
sessionID: "${sessionId}",
[...]
}
and import it as javascript into the jsp view file:
<html>
<head>
<script src="myVariables.js.jsp"></script>
[...]
</head>
<body>
[...]
</body>
</html>
I'm able to get the session id writing: myLib.sessionId.
Pros: handy and rapid.
Cons: write a jsp file that acts as js.
2) Save the server variable into hidden input fields (for example, in the main part of the template):
<html>
<head>
<script src="myLib.js"></script>
[...]
</head>
<body>
<form id="myVariables">
<input type="hidden" name="sessionId" value="${sessionId}" />
[...]
</form>
[...]
</body>
</html>
I'm able to get the session id writing a specific function into myLib.js library:
myLib = {
sessionId: function() {
return $("form#myVariables > input[name=sessionId]").val();
},
[...]
}
Pros: javascript and view completely separated.
Cons: more code to write; little harder to understand than the previous.
In my opinion first way is better because your pages will be clean and more readable. That'is very important! ;)
Best regards
There's a third way that I think takes the best of both of your suggestions: An inline script tag containing the variables:
<html>
<head>
<script>
var myLib = {
sessionID: "${sessionId}",
[...]
};
</script>
</head>
<body>
[...]
</body>
</html>
No separate JSP to write. Just as separated as the second solution in your question, as the JavaScript is tied just to the myLib, exactly as the JavaScript in your second solution is tied to the structure of the form.
There's a benefit to your first solution we should call out: It allows the HTML to be cached by the browser (by separating the variables into a separate request, e.g., for the .js.jsp). Combining the variables with the HTML (either as above, or the second approach in your question) means the HTML has to be served with caching diminished or disabled.

Best way to access external JavaScript file and place contents in div?

So, lets say you have a page that wants to load from a javascript file and it includes
temp.html file
<script src="example.js"></script>
<p class="one"></p>
Now in the example.js file you have a function that is
function getInfo() {
var place = "foo"
$(".one").html(place);
}
//Edit currently I call the function inside the JS file
getInfo();
My question is how would you connect the two files so that the external javascript file knows that it is pointed to the paragraph with the class one?
Normally when this is in a single page, you would call the function and the info will be set.
I have seen a getScript method and a load method for Jquery. Would that be applicable here?
Any ideas on how to approach this? If you provide some code that will be super helpful.
Thanks in advance.
Looks like you want to execute getInfo() as soon as it's defined (i.e.: example.js is loaded).
You can try this approach:
<script src="example.js" onload="getInfo();"></script>
In your example.js, change getInfo() to something like this:
function getInfo() {
$(document).ready(function() {
var place = "foo"
$(".one").html(place);
});
}
Your language is confusing, but you could use jQuery's $(document).ready function which would suffice. Generally speaking, an externally loaded file should execute where the tag is in the script.
A hack could be to place a tag before the end of your document body, give it an id, and then use $('#id').ready() there. In general though, you could just try coding the transclusion concept (I'm guessing you're used to this) from scratch using intervals and timeouts.
<div id="rdy">
</div>
</body>
Then in your file:
$('#rdy').ready(getInfo);
Just my added opinion, you should consider that Google is up to some not-so-nice things these days, they are long-gone from the "do no evil" mantra.
If we assume you have a JavaScript file that contains this content:
function getInfo() {
var place = "foo"
$(".one").html(place);
}
then your markup will look something like this:
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="example.js"></script>
<script>
$(function(){
getInfo();
});
</script>
</head>
<body>
<p class="one"></p>
</body>
</html>
$(function(){ ... }); is just the simplified version of $(document).ready(function(){ ... });. They both more or less handle the onload event, which fires when page has finished loading.

Jquery to merge all referenced pages into root page?

This sounds a little obscure, but...
Is there a technique in Jquery (or just straight javascript) to step thru all the external CSS and JS file references in an HTML file and replace the references with the contents of the files.
So instead of:
<link rel='stylesheet' id='style-css' href='http://domain.com/style.css' type='text/css' media='all' />
<script type='text/javascript' src='http://domain.com/js/domain.js'></script>
..it takes all the stuff from those files and sticks it into the rendering html to make one big html doc...?
<head>
...
<style type="text/css">
hr {color:sienna}
p {margin-left:20px}
body {background-image:url("images/back40.gif")}
.etc {color:red}
.etc {color:red}
.etc {color:red}
</style>
<script type="text/javascript">
function message()
{
alert("This is an alert");
}
etc
etc
</script>
</head>
<body>
...
</body>
Add this script..
$("script").each(function() {
var script = $(this);
script.load(script.attr("src"));
script.removeAttr("src");
});
$("link[rel='stylesheet']").each(function() {
var link = $(this);
link.after("<style type='text/css'></style>").next().load(link.attr("href"));
link.remove();
});
..and you can test it with..
alert($("head").html());
..when it's all done.
(And I don't see any reason in doing this ;)
The only place I can imagine that makes sense is if you run Javascript on the server, using Rhino or similar.
You can do as Sverre suggests and load the files yourself from the browser instead of letting the browser do it, but I can't see any scenario where that would be useful - you have the same number of background requests and end up with the same result, so the only thing you gain is extra work for yourself and probably some extra delay in rendering the page. Or do I misunderstand your goal?
On the server, on the other hand, it can make sense, as the browser can save a load of requests by getting all the external resources in the same document. Is this what you want to achieve?

Categories