Good afternoon everyone! I have searched the web to resolve this problem and tried to implement what I could see as the solution, but I still occasionally run into problems...
The project is modular in design with each module having a .html, .js, and .css file. When loading a module, those associated files are checked for and if they already exist in the DOM (e.g. the module has been opened at least once already), then there are no problems. If the files aren't already loaded (e.g. the module hasn't been loaded yet), then occasionally I run into a problem where a javascript function is called, but the external .js file hasn't been loaded yet. Here's the below function responsible for handling this:
function loadFile(sType,sURI,sCallback) {
// sType the type of file to load: link, script
// sURI the URI of the file to load
// sCallback the code to execute after successfully loading the file
var ref = document.createElement(sType);
if (sType == 'script') {
ref.setAttribute("type","text/javascript");
ref.setAttribute("src",sURI);
} else if (sType == 'link') {
ref.setAttribute("rel","stylesheet");
ref.setAttribute("type","text/css");
ref.setAttribute("href",sURI);
}
ref.async = true;
ref.onreadystatechange = ref.onload = function() {
var state = ref.readyState;
if (! sCallback.done && (! state || /loaded|complete/.test(state))) {
sCallback.done = true;
if (typeof(sCallback) === 'function') {
callback();
} else {
eval(sCallback);
}
}
};
document.getElementsByTagName('head')[0].appendChild(ref);
}
There are several other SO articles that were used for the above function:
Dynamically load external javascript file, and wait for it to load - without using JQuery
Javascript check if function exists
So the above function will be called like:
loadFile('link',"module.css?cache=0", $("#divModule").hide().load("module.php?action=init").fadeIn('slow'));
loadFile('script',"module.js?cache=0", "initModule('req')");
The first call will load the .html file contents (via the module.php call) for the module after the .css file has downloaded. The second call will call the modules js init function after the .js file has downloaded.
It doesn't appear to have any issues with the .css file, but sometimes the module will not load correctly meaning that the layout is rendered correctly, but no values populate (which is what happens with the modules js init function). If I check the 'Web console' in FF, there aren't any errors that are thrown. Any thoughts?
Thanks,
Dave
Hard to say for me w/o seeing what's happening in that module.php code, but it looks to me like your first one at least is firing immediately, rather than as a callback. Unless I'm missing something, the callback should be a function, while right now you're actually executing the jquery hide/load stuff right when you call loadfile. You might want to wrap it in a function.
Related
I'm trying to load another JS file from JS (because the url can change depending on what the user selected and load both would cause conflict issues) and then right after loading the file run a function from the file. I need to run a function and I can't just run code because the function requires client inputs. How can I do this?
In this example, I haven't included the dynamic URL part because that works. Also, no 2 attempts were tried at once. I tested them all separately. None of them worked. This is what I've tried:
var url="file.js", script = document.createElement('script');
script.setAttribute('src',url);
script.setAttribute('id','option');
document.head.appendChild(script);
// code attempt 1 at loading the function:
fileInit(param1);
// code attempt 2:
document.getElementById("option").onload = fileInit(param1);
// code attempt 3:
script = document.getElementById("option");
script.onload = script.onreadystatechange = fileInit(param1);
// code attempt 4:
document.getElementById("option").addEventListener("load", fileInit(param1));
I just want to load the file is JS (so I can have a dynamic url) and then when the file is loaded run the init function defined in the file. I also don't want to use jQuery. I want the code to be vanilla JS. I know you can use jQuery.getScript().
In both files you should have this statement exports.__esModule = true; and in the export file you do this for each thing you want to export exports.thingToExport = thingToExport; then you import like so:
var file = require("path/to/file");
file.thingToExport;
Edit: This question explains what you do in typescript to get this node code.This also works in modern browsers import functions from another js file and is probably a duplicated.
I would like to run my Javascript payload only once per page.
I explain the problem: I am appending my own Javascript payload at the end of each external scripts loaded by the browser. And therefore, the main function of my payload runs as many time as there are external scripts (kind of expected).
More info: I am doing all the job inside of the .js files.
My attempt: I tried to declared a global variable var check and to implement my main method as follow, but this 'quick fix' did not work:
main(function(callback) {
if (!check) {
f(callback);
f1(callback);
f2(callback);
check = true;
}
});
Any idea?
I solved my issue by using a global variable, here is the code:
var check;
if (typeof(check) == "undefined") {
check = true;
main(function(jsonObj) {
f(jsonObj);
f1(jsonObj);
f2(jsonObj);
});
}
The redundant declaration of the var check does not affect its value or whatever, hence this works, no many how many external scripts load this code they will all first evaluate the type of check which was set on the first execution of the main and then they will not re-execute the same code.
I am working on migrating an application that manually writes script tags to one that uses the YUI3 loader to manage script dependencies. I'm running into an issue with scripts like jQuery that shouldn't be loaded twice, because in some cases legacy code drops the script on the page, and then the YUI loader later loads it up again. Is there a way to prevent this from happening? It seems like the loader should be able to query for script tags with the same src as the one it's going to create before injecting a new tag.
About 3 / 4ths of this video you'll see how to load external modules not written for YUI and notify the loader that it has been loaded so it doesn't try to do it twice. Basically, you monitor the onProgress event of the loader and when it fires, you call YUI.add() with the name you want to give the module which will then make the loader mark that module as loaded.
It turns out that one way to do this is to call Y.add() proactively on the module name. This works well for modules that are not themselves defined with Y.add() (e. g. jQuery plugins). However, there is a potential race condition if you do this with modules that ARE defined with Y.add(). For example, consider the following sequence:
script for module A is run (calls Y.add('A', ...))
YUI goes off to load the requirements for module A before running the callback
Y.add('A') is called again with an empty callback (to notify YUI that the script file for A is on the page)
YUI since the async load hasn't yet returned, YUI takes the empty callback as the definition of A
The fix is to use the following script:
var preloadedModules = ['a', ... ]; // list of module scripts already on the page
, noop = function (Y) { }, version = '#VERSION#', i, len, moduleName;
for (var i = 0, len = preloadedModules.length; i < len; ++i) {
moduleName = preloadedModules[i];
if (!YUI.Env.mods[moduleName]) { // avoids overwriting YUI module definitions
YUI.add(moduleName, noop, version);
}
}
I'm getting into writing some more complex javascript applications, and I'm running into the limitations of my own knowledge-- please forgive any naming errors or obvious noob stuff, I'm not a js pro!
I have about 4 or 5 scripts I've put in their own files, just to keep things a little easier to maintain. So maybe there's one script that deals with building page elements (like complex forms), another that just handles data, creating generic ajax request objects, defining parsers and error functions for the data returned, and another that is purely display-oriented.
I've set global variables in the page that then get populated by various scripts that get loaded at run time. For example, I define var myapp = { }; in the main HTML page, and then in the scripts various function populate this "namespace" like:
myapp.myfunction = function(){
// do stuff
}
The problem is that despite all the scripts including a $(document).ready(function() block that wraps all function definitions, when a function is called from one script that refers to another (that is, if my data.js file calls a function myapp.myDisplayFunction that is in the display.js file, I sometimes get an Object has no method 'myDisplayFunction'
Other than slamming all functions into one massive script, how do you deal with this problem? Is there a best practice that I'm missing? or is this just a question of specifying a different order that the scripts are called in?
Thanks
When you are not sure if method you are about to call exists (is already loaded) you can do a check:
if (myapp) //my app namespace is defined
{
if (myapp.myFunction) //myFunction is defined
{
myapp.myFunction();
}
else
alert('You have to load myFile.js first!');
}
Just check for the function before using:
if(typeof(myapp.myDisplayFunction) !== undefined) {
// do your stuff
} else {
// wait for a while
}
And check whether you have async attribute set while loading the .js files.
In AppMenu.js,
AppMenu = function()
{
var scope = this;
}
Also noted:
Star.Bus.addEvent("AppMenu_StatSheet");
Star.Bus.on("AppMenu_StatSheet", scope.AppMenu_StatSheet, scope);
scope.registerApp("Exit Game", "AppMenu/images/exit_button.png", "AppMenu_exit", "");
Further down is a method
scope.AppMenu_StatSheet = function()
{
showStats();
}
I moved the location of the showStats() method to another js file, and I want the method to send its call there instead of where it originally was going. In Javascript, can I tell the program where to look to call showStats()?
EDIT Curiously, there is no AppMenu.html. I now believe that all of the html is dealt with by a main HTML file in the above folder.
If you include both Javascript files in your PHP/HTML page, the compiler automatically uses your showStats() function, even when it is called from file1.js and the actual function is located in file2.js.
As long as you include both files in your HTML page you'll be fine. Maybe load the file with showStats() before the other one.