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
Related
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.
I'm creating a program in Meteor JS. All the JS files are loaded at once, in a certain order.
A lot of variables need to be global, in order to work, but at the same time, I want my JS to be modular.
For FILE 3 to use the functions in FILE 1 and FILE 2, the functions have to be declared as variable assignments like in FILE 2 or else, they are not accessible outside of the file. I don't believe this is an issue of hoisting, because main.js is loaded last, those are the functions that use the functions in FILE 1 and 2. Either way, I theoretically should be able to see the function in the console if it is on a global level.
FILE 1
function foo() { } // This is not global outside of the file. Why?
FILE 2
bar = function() { } // This is considered global.
Functions in FILE 1 can access the function just fine, but if placed outside the file, the function or console cannot access them.
Is this a Meteor JS thing? A JavaScript thing? Someone help me understand and learn. :)
Your code is being wrapped in a function, so variables and function literals create local variables.
However, if you assign to a name that has not been declared, that will create a global variable.
You should add 'use strict'; to turn that into an error instead.
I followed the documentation to put the constants in the lib/constants.js file.
Question:
How to access these constants in my client side html and js files?
Variables in Meteor are file-scoped.
Normally a var myVar would go in the global Node context, however in Meteor it stays enclosed in the file (which makes it really useful to write more transparent code). What happens is that Meteor will wrap all files in an IIFE, scoping the variables in that function and thus effectively in the file.
To define a global variable, simply remove the var/let/const keyword and Meteor will take care to export it. You have to create functions through the same mechanism (myFunc = function myFunc() {} or myFunc = () => {}). This export will either be client-side if the code is in the client directory, or server-side if it is in the server directory, or both if it is in some other not-so-special directories.
Don't forget to follow these rules:
HTML template files are always loaded before everything else
Files beginning with main. are loaded last
Files inside any lib/ directory are loaded next
Files with deeper paths are loaded next
Files are then loaded in alphabetical order of the entire path
Now you may run into an issue server-side if you try to access this global variable immediately, but Meteor hasn't yet instantiated it because it hasn't run over the file defining the variable. So you have to fight with files and folder names, or maybe try to trick Meteor.startup() (good luck with that). This means less readable, fragile location-dependant code. One of your colleague moves a file and your application breaks.
Or maybe you just don't want to have to go back to the documentation each time you add a file to run a five-step process to know where to place this file and how to name it.
There is two solutions to this problem as of Meteor 1.3:
1. ES6 modules
Meteor 1.3 (currently in beta) allows you to use modules in your application by using the modules package (meteor add modules or api.use('modules')).
Modules go a long way, here is a simple example taken directly from the link above:
File: a.js (loaded first with traditional load order rules):
import {bThing} from './b.js';
// bThing is now usable here
File: b.js (loaded second with traditional load order rules):
export const bThing = 'my constant';
Meteor 1.3 will take care of loading the b.js file before a.js since it's been explicitly told so.
2. Packages
The last option to declare global variables is to create a package.
meteor create --package global_constants
Each variable declared without the var keyword is exported to the whole package. It means that you can create your variables in their own files, finely grain the load order with api.addFiles, control if they should go to the client, the server, or both. It also allows you to api.use these variables in other packages.
This means clear, reusable code. Do you want to add a constant? Either do it in one of the already created file or create one and api.addFiles it.
You can read more about package management in the doc.
Here's a quote from "Structuring your application":
This [using packages] is the ultimate in code separation, modularity, and reusability. If you put the code for each feature in a separate package, the code for one feature won't be able to access the code for the other feature except through exports, making every dependency explicit. This also allows for the easiest independent testing of features. You can also publish the packages and use them in multiple apps with meteor add.
It's amazing to combine the two approaches with Meteor 1.3. Modules are way easier and lighter to write than packages since using them is one export line and as many imports as needed rather than the whole package creation procedure, but not as dumb-error-proof (forgot to write the import line at top of file) as packages.
A good bet would be to use modules first, then switch to a package as soon as they're tiring to write or if an error happened because of it (miswritten the import, ...).
Just make sure to avoid relying on traditional load order if you're doing anything bigger than a POC.
You will need to make them global variables in order for other files to see them.
JavaScript
/lib/constants.js
THE_ANSWER = 42; // note the lack of var
/client/some-other-file.js
console.log(THE_ANSWER);
CoffeeScript
/lib/constants.coffee
#THE_ANSWER = 42
/client/some-other-file.coffee
console.log THE_ANSWER
I have a log.js file(it contains log function along with some properties) for debugging purpose.
I have two other js file which are the controlling various behavior of the web application.
Now I need to include the log function considering not to repeat the debug function in both the js file and just calling the file name.
How do I do it?
The idea is to make my code clean and separate them in other files to limit the size of a single js file.
Include all .js-files in the html page. Include log.js first.
Call the functions all you want.
All functions in all files are included in the source and are "written on the page", any functions can be accessed from anywhere within the HTML as they all become essentially one document. Make sure you do not have duplicate functions as this could cause an issue
I've spent a great deal of time creating and testing an application with quite a few functions. Now that I have configured everything and it works how I want, I would like to begin cleaning up the code so its not 400 lines of mush.
I have already created an external CSS file and would like to do something similar for the JS and possibly even the HTML (approx 100 lines of code of just HTML, ick).
Admittedly I am a novice programmer but I've picked up quite a bit of knowledge in the short time I've been doing this. What is the best way to separate out the functions into external files and then call them so that the whole application works as it does now?
For example (this is a web mapping application): I have functions for search, basemap gallery, legend, layers, init, infowindows, etc. Since the code is already written and I'll be creating multiple applications in the future, the goal would be to just have these js functions in files ready to be referenced by whatever application needs them.
Thanks.
To link an external javascript file, place a script tag with a src attribute pointing to your file.
<script src="legend.js"></script>
<script src="layers.js"></script>
<script src="init.js"></script>
Calling a function requires nothing special.
onclick="myFunction();"
Could you not just put all of those functions in one .js file and then call the file from within your web page?
<script src="../scripts/javascript.js"></script>
And then call on your functions as and when you need them?
The first thing you might consider doing do is to create a non-global "namespace" for your functions in a fashion such as the following:
window.MyApp = window.MyApp || {};
The above line can be at the top of every file; the first time it is invoked it creates a new namespace/object, subsequently it returns the one you previously created.
Then you can move your functions under MyApp in a manner such as the following:
MyApp.func1 = function() {...}
Google for creating Javascript namespaces, and possibly also the Javascript module pattern