How to correctly execte function from external file onload? - javascript

I have a function myModule.myFunction in a larger external script mymodule.js that is executed on load. Everything seems to work fine. But now I have added
"use strict";
at the top of the external script. And I get a
TypeError: MyModule is undefined
and the page stops working. So I am wondering where I did something problematic. Here is the structure of my page (unfortunately, I did not manage to produce a minimal example):
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<!-- Some html here -->
<script src="mymodule.js"></script>
<script>
function myOnload() {
myModule.myFunction();
}
window.addEventListener('load', myOnload, false);
</script>
</body>
</html>
Here is what the MyModule in mymodule.js looks like:
var myModule = (function(){
// stuff
})();

In myModule.js you need to explicitly assign myModule to the window object (when using "use strict").
Change it to window.myModule = ...
Reason: in sloppy mode, undeclared variables are automatically added as properties on the global object. In strict mode they are not )to avoid accidental interference).

Related

How to use javascript module on an HTML page in a second inline script

I have a JavaScript module mymmodule.js exporting a list:
export var mylist = ['Hallo', 'duda'];
Normally this module is used in other modules and this works fine. But additionally I want to use the export(s) of the module as-is in an inline script on an HTML page. I tried to copy the exports to the window object:
<html>
<head>
<script type="module">import * as mm from './mymodule.js'; window.mm = mm;</script>
</head>
<h1>MyMain</h1>
<p>
<div id = "info">...</div>
</p>
<script type="text/javascript">
document.getElementById('info').textContent = window.mm.mylist;
</script>
</html>
but I get the error "window.mm is undefined" in the console. I tried referencing mm.mylist instead of window.mm.mylist with no better result.
How can I reference the exports of a module in a second inline script on the HTML page?
The problem is that modules are execute at the same stage as pscripts with the defer attribute](https://javascript.info/script-async-defer#defer), i.e. after reading the page and executing JavaScript in script tags.
Therefore, when the browser sees
document.getElementById('info').textContent = mm.mylist
the mymodule.js script hasn't been executed and the mm object is not available yet.
To mitigate this you need to run code referencing exports from mymodule after the DOM is completely loaded, e.g. in the onload event:
<html>
<head>
<script type="module">import * as mm from './mymodule.js'; window.mm = mm;</script>
</head>
<h1>MyMain</h1>
<p>
<div id = "info">...</div>
</p>
<script type="text/javascript">
window.onload = function() {
document.getElementById('info').textContent = mm.mylist;
}
</script>
</html>

Unable to access global variable in javascript?

I am trying to access a var one file from another file. Here is what I have:
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<button id="btn">Global</button>
<script src="/test.js"></script>
<script src="/testpass.js"></script>
</body>
</html>
test.js:
export var globalVariable = {
output: "test this"
};
testpass.js:
import { globalVariable } from './test.js'
document.getElementById("btn").addEventListener("click", function(){
alert(globalVariable.output);
});
Nothing happens. I also tried doing
var globalVariable = {
output: "test this"
};
and then simply accessing it from another file as demonstrated in this answer:
Call variables from one javascript file to another but it did not work. Tried exporting it as mentioned in this answer: Can I access variables from another file? as well but no success. I am using sublime text and vue.js and it does not work for both of them.
In addition if I do something like this:
import { globalVariable } from '.test.js'
document.getElementById("btn").addEventListener("click", function(){
alert("Not printing the globalVariable here");
});
the entire javascript file seems to fail and doesn't work at all when called in the HTML file.
You should be getting an error from the browser's JavaScript engine in the web console. To use import and export, you have to treat your code as a module. Your script tags don't, they treat the code as just script. To treat testpass.js as a module, you must use type="module":
<script src="/testpass.js" type="module"></script>
No need to list test.js, testpass.js will load it. So:
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<button id="btn">Global</button>
<script src="/testpass.js" type="module"></script>
</body>
</html>
Sadly, we can't show modules in SO's Stack Snippets, but if you make those changes, this codesandbox example is what you end up with (except I changed src="/testpass.js" to src="./testpass.js").
Note that globalVariable isn't a global variable (which is a Good Thing™). It's a local variable within test.js that it exports. Any other module can import it, but it's not a global.

Call .js function in another.js

I have...
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="xpath.js"></script>
<script src="myscript.js"></script>
</head>
<body>
<!-- some html code -->
</body>
</html>
myscript.js
$( document ).ready(function() {
$("body").click(function(event){
console.log(event.target);
//call xpath.js (getxpath(event.target))
});
});
xpath.js
here stored locally
How do I achieve this..?
Accessing functions from another file
Code separation between files does not matter (You could pack them all in a single file without any problem). Execution order and scopes do. All scripts loaded on a web page share a same global scope, which is window, and can add variables to it.
Most libraries do this so you can access them (jQuery creates a global $ variable, for example, and you can use it anywhere).
Your Xpath script, however, does not, because it's not meant to be directly embedded into a webpage. It's part of a Firefox addon. So in order to make it accessible, you need to modify it.
Modifying xpath.js
At the beginning, change this:
define([
"firebug/lib/string"
],
function(Str) {
... to this:
window.Xpath = new (function(Str) {
And at the end, change this:
});
... to this:
})();
Using it
Now that you did this, you have a global Xpath Object that you can access like this:
$(function() {
$("body").click(function(event){
console.log(Xpath.getElementXPath(event.target));
});
});

Requirejs and external scripts

Hi I have my js application that was built with requirejs. Now I have external page from other developer, he can load his scripts, html, css and other things that not connected to me.
Here example of my module that will be connected to his page:
require(['page', 'widgetGame', 'adDynamic'], function (Page, WidgetGame, AdDynamic) {
function PageExternalGame (params) {
var params = params || {};
Page.call(this, params); // call super constructor.
};
PageExternalGame.prototype.gameLoadingComplete = function() {
alert(111);
};
window.yepiExternalPageGame = new PageExternalGame();
return PageExternalGame;
});
and here example of his page:
<!DOCTYPE HTML>
<html lang="en"><head>
</head>
<body>
<div id='gameArea'>
<canvas id='canvas0' width='480' height='320' style="position: absolute; "></canvas>
</div>
<script data-main="../../YepiMobileNew/UI/js/pageExternalGame" src="http://requirejs.org/docs/release/2.1.14/minified/require.js"></script>
<script src='js/gamemin.js'></script>
<script>yepiExternalPageGame.gameLoadingComplete()</script>
</body>
</html>
So in his page he call my object yepiExternalPageGame, that should be loaded by requirejs. but when he call this object, require itself already loaded, but class pageExternalGame still wasn't loaded, so this object is not exist when he call it. How to handle with it? (His outer scripts also can call my object). Thanks.
Firstly if you sharing your amd app with other it is good to create build that isn't using require.js so you won't force other developers to add another lib and increase page size. You can do this with almond.js
But returning to your question.
Change
<script>yepiExternalPageGame.gameLoadingComplete()</script>
to
<script>
require(['../../YepiMobileNew/UI/js/pageExternalGame'], function() {
yepiExternalPageGame.gameLoadingComplete();
});
</script>
That will help.

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