Pass loaded file variables as arguments to callback function - javascript

In my new project, I am trying to avoid use of global variables using requirejs. I found that requirejs is using define and require methods to load supporting files. I am planning to write these methods on my own.
MyApp.loadFiles(['jquery', 'mustache'], function($, m){
// my code using the above arguments
});
I know how to load files, but I don't know how to pass the loaded files variables as arguments to a callback function. and also I need to call this function when those files are completely loaded.
Please help with this.

Related

How to create and implement a custom JavaScript library

I am new to javaScript and am unsure how to go about creating a new js library and referencing this in another js file.
If I have a standalone file Utilities.js
var Utilities=
{
show: function(input)
{
alert(input);
}
};
Am I missing something as to how a library should be defined standalone?
My second question is how to use that is sub-sequent js files. What I did so far is:
<script type="text/javascript" src="resources/Utilities.js"></script>
In my index.html. Is this enough to reference it as:
Utilities.show("Hello");
In any other java script file?
I tested it in this fashion and got and error "Utilities is not defined"
NOTE: This is just an example and not my full and practical purpose.
Yes, including that Javascript file with that global variable declared is enough to call your methods this way Utilities.show("Hello"); from another Javascript file loaded after Utilities.js or inside a <script></script> section of your html.
But you can actually improve it a little, following the module pattern and exposing only the functions you really need to the global scope (you'll likely write some functions that the users of your library should not call directly, this allows you to do it in a clean way):
var Utilities=Utilities||(function () {
//Accessible only here
var privateArray=[];
//Cannot be called from outside this function
var privateFunction=function(){
}
//Return only what must be publicly accessible, in this
//case only the show() method
return {
show: function(input){
privateFunction();
alert(input);
}
}
})();
That (function () { /* Code */})();, defining a new scope for your code will also avoid name clashes with other global javascript object/functions.
It is OK to use object literals, but you can define libraries using other patterns (module, revealing module, constructors, etc).
I recommend these links to understand primitives, scopes, closures, object literals, etc.
http://bonsaiden.github.io/JavaScript-Garden/
http://jsbooks.revolunet.com/
To call the method inside index.html you need to add a tag.
<script>
Utilities.show("Hello");
</script>
But this approach it's not recommended. Instead of it, you can create a new JS file to run your library code.
<script type="text/javascript" src="resources/Utilities.js"></script>
<script type="text/javascript" src="resources/main.js"></script>
In main.js
Utilities.show("Hello");
Hope it helps.
Given the fact that you gave, within yout question, zero context of what you're trying to achieve, the best answer to your original question is that it depends.
If you just need a bunch of files and you're done (like in your example, Utilities.js and a few more) then you're ok with the way you're heading to.
But of course, you'll allways want to scale your front end and thus you should adhere to some architectural pattern. So, if you're building a client side (browser-side) application, then you should really implement your libraries using the module pattern, and begin your project from a good project example / scaffold.
On the other hand, if you're rendering the html on server (e.g. you're using PHP to render the final html file that will be sent to browser) and you just need some thin functionality in the browser, the way you begun can be okay if you're careful. Also, you can still implement the module pattern here too, although I strongly suggest that you should make use of namespacing to have a clear separation of concerns.
In browser based javascript you can't just call functions from different files yet. In Es6 there are ways. But not yet. Which mean just because you have some variable or function etc then you cant reference it automatically in another file.
Unless both files are loaded into one html and are loaded in order.
Alternatively you could run task runner like grunt and 'merge' them upon each build.
Javascript doesnt have special concept of library, in es6 it's a little different, everything is an object.
What you are doing is just creating an object. and yes it will work.

Meteor and javascript: make functions in one file available to another

I use iron-router with Meteor and I have written a number of functions that I call from the Router.map() which defines all my routes and hooks. The file is getting to be cumbersome to scroll around in and I would like to move my functions to a different file.
The only way I've found to make functions in one file available to those in another file is to define those functions in a script tag inside the head tag. But of course, I'd rather not put them there. I assume there's a straightforward way to do this?
You create the functions the following way?
function myFunction(){
// Your code...
}
This creates a local variable storing your function (all code in each js-file is wrapped in a function!). You must instead store your function in a global variable, which can be done in the following way:
myFunction = function(){
// Your code...
}
Create a folder named "lib" in your project. Then create functions.js in the lib directory and put there all your functions.
See http://docs.meteor.com/#structuringyourapp

Using RequireJS with legacy code

I'm working with a very large project that uses:
Legacy JSP pages that includes javascript files with script tags
Backbone models and views that uses other javascript modules without RequireJS
We now want to start using RequireJS with jQuery, BackboneJS and UnderscoreJS for everything we develop from now on, but we don't have the resources to rewrite all the legacy JSP pages. We may have time to rewrite the Backbone models and views we have already developed.
The problem is that for our legacy code (both 1 and 2 above) we include all our javascript files in a huge file and ship to the browsers. This huge file must be able to co-exist with our new RequireJS templates, but how can I e.g. separate certain parts of the huge file, so I can use them with the templates using RequireJS? Without having to rewrite all pages that uses this part of the file, or having duplicate code.
Thanks!
I don't know if I fully grasp the problem at hand, but I think a the shim or map functions of RequireJS will help you out.
Extract the parts you want in a new module from your huge javascript file. Then tell RequireJS that your huge javascript file is a dependecy for this new module using shim. Something like:
requirejs.config({
shim: {
'new-module': {
deps: ['huge-javascript-file'],
exports: 'NewModule'
}
});
Shim documentation: http://requirejs.org/docs/api.html#config-shim
The map function might be useful when only portions of your new code have to use your old huge file. Check out this documentation: http://requirejs.org/docs/api.html#config-map
I don't think there is One True Way to achieve this, but I've approached a similar problem by defining module "facades" around the globally scoped code. Let's say your legacy scripts define a global variable called foo. You can define a AMD module and export that variable from it:
//foo.js
define(function() {
return window.foo;
});
//bar.js
define(['foo'], function(foo) {
//do something with foo
});
This way you only need to write a single-line facade every time you need to use a new piece of the existing, globally defined code, without breaking existing code which expects the same code to be globally defined. Over time you can move and refactor the actual implementation into the module without breaking consumer code.

Loading javascript files as and when needed

I am working on a widget/gadget based website, as in the user can choose which widgets/gadgets s/he wants on the screen.
This means that I will have hundreds/thousands of js files, 1 per widget/gadget. I thought that I could use $.getScript to load the correct js file as and when needed based on user selection.
The problem I have discovered is that $.getScript can only be sent variables via javascript global variables. Global variables and $.getScript don't play too well together it seems.
Is there another way of doing this? i.e. somehow only load js files as and when needed based on user selection where the loaded js file can receive variables from the js file which calls the sub js file?
The solution for this problem is to use a module loader system like require.js.
It will automatically know which files to load, based on each files named dependencies.
Your modules will clearly outline their depenedncies like this:
require(["helper/util"], function(util) {
//This function is called when scripts/helper/util.js is loaded.
//If util.js calls define(), then this function is not fired until
//util's dependencies have loaded, and the util argument will hold
//the module value for "helper/util".
});
Once they've done that the require.js loader will load up the correct JS files automatically for you. It's bit of a different syntax, but it will solve the problem.
The problem I have discovered is that $.getScript can only be sent variables via javascript global variables. Global variables and $.getScript don't play too well together it seems.
Scripts loaded via $.getScript can access globals just fine. (Not that global variables are a good idea.)
But another way to pass information to your loaded script would be for each script to implement a post-load callback based on the script name, and for your loader code to call that callback (with the arguments you want to pass to it) once $.getScript does its thing.
Live Example | Source
Of course, that example uses globals too — $ for jQuery, and the new script's theNewScript load complete function is a global. In a production system, to do this, I'd have just one global for my entire app (say, MyApp), define all of my code within a scoping function to avoid creating any other globals at all, and have the new script set its "load complete" function as a property on that. (Normally I don't define any globals at all, because I don't normally demand-load scripts.)
try to call your scripts using pure javascript
var html_doc = document.getElementsByTagName('head')[0];
js = document.createElement('script');
js.setAttribute('type', 'text/javascript');
js.setAttribute('src', '../scripts/jquery-1.7.2.min.js');
html_doc.appendChild(js);
js.onreadystatechange = function () {
if (js.readyState == 'loaded' || js.readyState == 'complete') {
doSomething
}
}
//works on ff e no chrome
js.onload = function () { doSomething }

require.js: Access all loaded modules

Is there any way to access all loaded modules of require.js?
Background:
I want to automatically call an init() function of my javascript-modules after all of them are loaded, see require.js + backbone.js: How to structure modules that have an initialize function?
Without require.js I looped over my own module-storage and called each init() function.
I now want to do this with require.js. I'm aware that calling a my_custom_init_function_favoritecolor_petname_love123 of every loaded module (including external libraries) is dangerous. I hope that this will cause less trouble than manually keeping a list of all modules (and the requirements of these modules) up-to-date. Forgetting one module init() is much more likely than a third-party library having my custom function name (though the latter is probably harder to debug).
Or does anyone have a better idea of how to accomplish that?
Yes, require.s.contexts._.defined is an object which its keys are the module names and the values include the value returned from that module.
require.s.contexts._.defined includes all the modules (either define() or require() such as the Javascript file that is the starting point of the program and is indicated using data-main for RequireJS).
Just finished a similar behavior within my RequireJS project. require.s.contexts['_'].registry holds the list of the registered modules.
I am using Underscore.js for getting, filtering and iterating the list of modules. Maybe the following code fragment helps you:
var modules_registered = _.keys(require.s.contexts['_'].registry);
var modules_to_be_initialized = _.filter(modules_registered, function(module_title) {
return module_title.indexOf('modules') > -1;
});
_.each(modules_to_be_initialized, function(module_name) {
require([module_name], function(current_module) {
current_module.init();
});
});
I'm lazy, so I just did this:
var modulesToLoad = Object.keys(require.s.contexts['_'].registry);
require(modulesToLoad);
Based on other answers here.

Categories