make javascript module global? - javascript

I am trying to execute a function from within a script. It shows no error but also doesnt execute the function.
file.mjs
function test() {
console.log("test")
}
This is my html:
index.html
<head>
<script type="module" src="file.mjs">
</head>
<body>
<button type="button" id="Submit">Submit</button>
<script>
document.getElementById('Submit').addEventListener('click', test);
</script>
</body>
This worked fine using 2 separate scripts, to make it global I was using type="text/javascript".
But since my file.mjs is actually importing a library I had to set it as type="module" and the function wont execute. Is there a way to make the module scope global?

Before I go on, there's a big problem that needs addressing:
Your syntax is wrong. If you want to import a script, that tag must have the src attribute and nothing within the tag. If you want to execute an "inline" script, it should NOT have the src attribute, so what you should have is two script tags, one to import the module, the other to execute your inline code.
Now, I'm not sure what you mean by "global". To obtain true "globalness", you would have to define your variable in the global object (window or globalThis) like so:
// file.mjs
function test() { ... }
window["test"] = test;
Then in your regular script you could just do document.getElementById('Submit').addEventListener('click', test);.
That sort of completely destroys the purpose of JS modules though, as it's supposed to be an "import/export" model.
Ignoring the "global" part of your question: if you want to use modules for what they're worth, you would be importing and exporting them, and you would only (almost always) link a <script type="module"> in your HTML if it only imports and never exports (exporting would be useless). The reason you need type="module" is to tell the browser that you're operating on modules so it'll allow you to import/export. With that said, your code would look like this:
// file.mjs
export function test() { ... }
And in your HTML, you would only need one script tag (that goes right before the ending body tag):
<script type="module">
import { test } from "/path/to/file.mjs";
document.getElementById('Submit').addEventListener('click', test);
</script>
I hope that clears it up for you, and docs if you need them.

Related

Importing functions in javascript

Trying to use GoJS library I get an "import declarations may only appear at top level of a module" error.
main.html
...
<script id = "code">
import {makeNodes} from "./make_nodes.js";
function init(){
makeNodes(model);
...
}
</script>
<body onload="init()">
...
make_nodes.js
export function makeNodes(model){
...
}
As the error says, you can't use import except in a module. Your code isn't in a module. To make it a module, use type="module" in the script tag:
<script id = "code" type = "module">
All modern browsers natively support modules (Obsolete ones like Internet Explorer don't, and never will.)
Despite that native support, though, most people using import/export syntax are still doing so via transpilers and/or bundlers (like Vite, Rollup, Webpack, Browserify, ...).
Once you're actually using a module, init will no longer be a global, but your <body onload="init()"> expects init to be a global. (This is one of several reason not to use onxyz-attribute-style event handlers.) To fix that, hook up the event in your code, removing the onload attribute from <body>:
function init(){
makeNodes(model);
// ...
}
window.addEventListener("load", init);
However, the load event you're using happens very, very late in the page load process, waiting for all images and other resources to finish loading. In most cases, you're better off not doing that. Modules are always deferred, so they don't run until the HTML of the page has been parsed into the DOM, which is usually all you need. (We used to have to put script tags at the very end of the body element instead, but then the defer attribute was added for scripts, and again all type="module" scripts are deferred automatically.)
Here's an exmaple — notice that the script type="module" is above the elements its code operates on, and yet it works just fine (because it's deferred):
<script type="module">
document.getElementById("btn").addEventListener("click", () => {
console.log("Button clicked");
});
</script>
<input type="button" id="btn" value="Click me">
That wouldn't work with a non-module script unless you added the defer attribute.

jQuery "$ is not a function" error

I swear I have included jquery in the page header, it is right there!
Nonetheless the following code, which I've included near the bottom of the page (and inline for now) gives me an error saying "TypeError: $ is not a function."
<script>
function displayResult(longA, latA, longB, latB, units) {
$("#distance").html(calcDist(longA, latA, longB, latB, units));
if (units=="m") {
$("#unitLabel").html("miles");
$("units").prop("selectedIndex",0);
} else {
$("#unitLabel").html("kilometers");
$("#units").prop("selectedIndex",1);
}
$("#longA").val(longA);
$("#latA").val(latA);
$("#longB").val(longB);
$("#latB").val(latB);
}
$("#calculateButton").click(function() { //This is the line it's complaining about
var longA=$("#longA").val();
var latA=$("#latA").val();
var longB=$("#longB").val();
var latB=$("#latB").val();
var units=$("#units").val();
displayResult(longA, latA, longB, latB, units);
})(jQuery);
</script>
Higher up in the page header I've got the following:
<script src="jquery.js" ></script>
<script src="calcDistSinglePage.js" ></script>
I'm not using Wordpress or anything, this is a very straightforward hand-coded HTML page.
Try wrapping your code in a closure (which is considered good practice anyways):
(function($) {
$("#calculateButton").click(function() {
// do stuff...
});
}(jQuery));
If this snippet still complains with the same error, there's bound to be a problem with the way you're loading the jQuery library.
Also, make sure that you don't overwrite the $ variable in your other code. For example, inside calcDistSinglePage.js.
The dollar-sign is a very straight-forward javascript variable and can be reassigned to whatever you want. According to the error, $ currently is something but not a function (otherwise you'd receive a ReferenceError stating that $ is undefined). So probably, somewhere in your code, you've overwritten it.
Make sure the jQuery library it's the first script you load.
Add this just before the closing </body> tag.
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/vendor/jquery-{{JQUERY_VERSION}}.min.js"><\/script>')</script>
Download the file locally and inside js/vendor/ add the file.
Replace the value {{JQUERY_VERSION}} in the script above adding your jquery version.
Here one CDN you could use.
https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js
https://code.jquery.com/jquery-2.1.3.min.js
You are probably linking it from a root folder that is not your HTML folder. Use an absolute path:
<script src="/jquery.js" ></script>
Or make sure jquery.js is in the same folder as your HTML.

How to call a internal script function from external js file method?

I am working with the MVC4 application with the aid of an external js file. In the view (.cshtml) file, I have a function which performs an action of creating the row in the grid,
based on the button click.
I have defined the button click in the external .js file.
But, when I tried to call the internal script function from that external js file method, it throws an exception saying that, that particular method is not defined.
I surfed but was not able to find a convincing answer..
Is what I'm trying possible??.. How should I achieve it??
Can any Js expert out there help me with this?...
Thanks All...;)
EDIT:
this is in external .js file:
$('#AddRowButton').on('click', function () {
window.CreateRow();
}
in my view:(.cshtml)
<script>
function CreateRow()
{
// creting row goes here...
}
window.CreateRow = CreateRow; //defined like what #joseeight suggested...
</script>
This is most likely due to a scoping issue. The internal script and external must be in a different scopes. The easiest, and hackiest, way to get around this would be to add the internal method to the Window, and access it as such in the external.
//Internal script
function myInternalMethod () {
//some code..
}
window.myInternalMethod = myInternalMethod;
Since window is global, and the name is the same, you could either use window.myInternalMethod or myInternalMethod when referencing it in the external scripts.
Make sure your external file is included below the internal
.......
<script>
function createRow(){
console.log('created');
}
</script>
<script src = "external.js"></script>
</body>
yes it is possible only when you call that external js file from html where that internal javascript have..
Example :
a.html
<html>
<head>
<script type="text/javascript">
function displayAlert(){
alert('displayAlert');
}
</script>
<script type="text/javascript" src="../../abc.js"></script>
</head>
<body>
//call the sample() javascript function which is in abc.js
</body>
</html>
abc.js
function sample(){
displayAlert();
}

Loading javascript in body onload with 2 functions

I am trying to load 2 javascript events/functions in the body onload as follows :-
<body onLoad="getSubs(document.form1.HotelID.options[document.form1.HotelID.selectedIndex].value);getTags(document.form1.HotelID.options[document.form1.HotelID.selectedIndex].value);">
Whenever I load using 2 functions the first one aborts - but if I just load the one it works fine - am I doing something wrong is it no possible to put 2 functions within the onload?
try this:
<html>
<head>
<script language="javascript">
function func1(){
//the code for your first onload here
alert("func1");
}
function func2(){
//the code for your second onload here
alert("func2");
}
function func3(){
//the code for your third onload here
alert("func3");
}
function start(){
func1();
func2();
func3();
}
</script>
</head>
<body onload="start()">
</body>
</html>
Multiple onload
Just do it from java script instead, one of the link shared into a comment explains well why it is best to use this approach over inline attributes.
<head>
<script>
document.body.onload = function() {
getSubs(...);
getTags(...);
};
</script>
</head>
<body>
...
</body>
I would avoid at all cost to have inline javascript, that is what you did in the code of your question: add javascript within an HTML attribute.
Best practice is to add your javascript in a separate file, see the related question on this principle What is Unobtrusive Javascript in layman terms?
So you'd have an other file called for instance "myjsfile.js", then you reference it from your HTML page
<script src="./path/to/your/myjsfile.js"></script>
Here is the answer to where to place this reference: Where to place Javascript in a HTML file?
Your "myjsfile.js" file would simply have:
window.onload = function(){
getSubs(...);
getTags(...);
};
Another thing to avoid: add javascript within the same HTML file. The reason is also based on the same principle of unobstrusive javascript. What is Unobtrusive Javascript in layman terms?
But I guess there are corner cases where you may want to do that.
If you really have to, do use window.onload instead of the inline javascript onload="...", see why here window.onload vs <body onload=""/>
Just add the following to your HTML file:
<script type="text/javascript">
window.onload = function(){
getSubs(...);
getTags(...);
};
</script>
Here is the answer to where to place this code: Where to place Javascript in a HTML file?
Note: Yes, in the same place as where you would put the reference to an external javascript file
Another thing: I do not know where your getSubs() and getTags() functions are defined. But if you want your code to work, it needs to call these functions after the file (or part of javascript) that defines them has been loaded.
In short: make sure the javascript file containing the definitions of getSubs() and getTags() is referenced before your code.
One thing that you could do is create a new JS function that accepts the document.form1.HotelID.options[document.form1.HotelID.selectedIndex].value parameter and call the two functions in the newly created function.
I tried calling two functions using the below code and it worked fine for me.
<html>
<body onload="callStart();callAgain();">
<script type="text/javascript">
function callStart() {
alert('First');
}
function callAgain() {
alert('Again');
}
</script>
</body>
</html>

Creating an instance in addOnLoad method of dojo doesn't have global scope

I've a Utils class in JavaScript. Below is the source code of that JavaScript.
function UtilityMethod(){
this.testMethod=function(){
alert("Test method is called");
}
}
Above code is included in Utils.js file.Now I need to create an instance of UtilityMethod in my HTML File. I've referenced Utils.js in my HTML file. Below is my HTML Code.
<html>
<head>
<title> New Document </title>
<script type="text/javascript" src="/dojo/dojo.js"></script>
<script type="text/javascript" src="/js/Utils.js"></script>
</head>
<body>
<script type="text/javascript">
dojo.addOnLoad(function(){
var Utils = new UtilityMethod();
});
</script>
TestMethodCall
</body>
</html>
But when I click on the HyperLink, it is giving me the error Utils is not defined. But even though I'm clicking on the link after page load, why is it still giving the error?
I need to include the instance creation in dojo.addOnLoad() method. Can you please suggest if there are other easy alternatives to this?
I know that we can do this using dojo.connect(), but is there another approach to do this. If we are using dojo.connect, we have to make changes to lot of code.
It's because Utils is created in a function; it won't be available outside the function. A nice explanation of this scoping behavior can be found here. To make this work, you'll need to tell the browser that Utils is a global variable:
window.Utils = new UtilityMethod();
Now, Utils is set on the window object thus making it accessible anywhere (A nice feat of the window object is that its properties are available without the window. prepended, so you can still use Utils.testMethod as normal)

Categories

Resources