3

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>
anon20010813
  • 131
  • 6
  • 2
    You shouldn’t do that and keep all the JS logic in js file. You can put your code surrounded with script tag in js file. – Rahul Kumar Apr 27 '21 at 15:01

3 Answers3

2

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.

chrwahl
  • 839
  • 6
  • 15
  • I don't know why but I'm still getting var not defined. I have multiple separate js scripts loaded onto my HTML do you think that has something to do with it? script works fine when on the same page but when on a different file it doesn't work @chrwahl – anon20010813 Apr 27 '21 at 15:31
  • @anon20010813 the code in comment https://stackoverflow.com/a/67285696/322084 should work perfectly fine. References to multiple js files. The order of the references is important. – chrwahl Apr 27 '21 at 15:49
2

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:

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.

connexo
  • 41,035
  • 12
  • 60
  • 87
  • ```Cannot use import statement outside a module```@connexo – anon20010813 Apr 27 '21 at 16:14
  • You need to **read** the post: *For that to work, you need your importing script to have type=module attribute*. `` or `` – connexo Apr 27 '21 at 16:15
  • My bad didn't see that part. But I am getting error ```unexpected token 'export' ```. @connexo – anon20010813 Apr 27 '21 at 16:23
  • Then you have something that alters/processes your `colors.module.js`, like a minifier or bundler. How to make your build chain work with modules is a different question. Feel free to ask a new question, describing in detail what you are using. Btw, what exactly is giving you that error? – connexo Apr 27 '21 at 16:24
  • My guess would be you're using `gulp` and something the like of `uglify.js`. Correct? – connexo Apr 27 '21 at 16:30
  • I had a minifier removed it and the error went away but I'm still getting var undefined. Can you think of any other reason why it might not work. @connexo – anon20010813 Apr 27 '21 at 16:33
  • I'm setting up a small github repo for you, demonstrating it works. – connexo Apr 27 '21 at 16:41
  • ok, thanks. @connexo – anon20010813 Apr 27 '21 at 16:51
  • https://github.com/franktopel/es-modules-test – connexo Apr 27 '21 at 16:54
  • Sorry, forgot two files required so you can reproduce the steps-to-run. `git pull` in your project folder, and you're good to go. You need `git` and `Node.js` installed properly; alternatively you can have any local webserver of your own host the two files (html and js). – connexo Apr 27 '21 at 16:58
  • Let me know how it works for you. – connexo Apr 27 '21 at 17:02
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/231666/discussion-between-anon20010813-and-connexo). – anon20010813 Apr 27 '21 at 17:04
1

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;
});
julien.giband
  • 1,306
  • 9
  • 14
  • First question I taught adding ```defer``` in the script tag when importing takes care of loading the script before DOM. second question how can I access the ```

    ``` tag if I include my whole js in one file? @julien.giband

    – anon20010813 Apr 27 '21 at 15:11
  • The scripts in the header section are executed before any scripts in the body section, unless you use async. So I think this answer is wrong. – Gerfried Apr 27 '21 at 15:16
  • The same way you would if the JS was in the script tag. – phuzi Apr 27 '21 at 15:16
  • @anon20010813 first, `defer` does the exact opposite: it waits until the DOM is loaded before running the script. And second, you can access any part of the DOM from any javascript, provided it's already loaded when the script runs. So you should probably use `window.DOMContentLoaded` event – julien.giband Apr 27 '21 at 15:16
  • @Gerfried it's a runnable snippet, so maybe you could try running it before declaring it's wrong. And the script is wrapped in a handler for `window.load`, so it will run only after everything is loaded, as stated before the snippet. Maybe you should read too – julien.giband Apr 27 '21 at 15:18
  • Your script works, but your explanation is wrong - see the answer of @chrwahl – Gerfried Apr 27 '21 at 15:19
  • @Gerfried answers are open to everyone so please feel free to post your own – julien.giband Apr 27 '21 at 15:20
  • I don't know why but I'm still getting var not defined. I have multiple separate js scripts loaded onto my HTML do you think that has something to do with it?script works fine when on the same page but when on different file it doesn't work @julien.giband – anon20010813 Apr 27 '21 at 15:28
  • @anon20010813 I don't. If some have the attribute `async` or `defer`, it may change the order in which they are loaded / evaluated though. The simplest way remains to keep your own script inside a js file of its own, import it last, and either tag it `defer` or wrap your code in an event handler for `DOMContentLoaded` – julien.giband Apr 27 '21 at 15:32
  • @julien.giband - I rebuilt the sample of anon20010813 on my localhost (html + js) - it works - could you please do the same? – Gerfried Apr 27 '21 at 15:33
  • did you use separate files for html and js @Gerfried – anon20010813 Apr 27 '21 at 15:41
  • @julien.giband - yes – Gerfried Apr 27 '21 at 15:44