I want to create a namespace or global object that will hold site wide used functions etc.
Also, on specific pages, I want to create a object that will hold state based on the current page and if the user is logged in, if so, then I will pull state information based on the current user.
What is the suggest pattern for this?
JavaScript does not have namespaces. However, when most of us refer to namespaces in the context of JavaScript, what we really mean is storing our functions and data in objects in a modular fashion without cluttering up the global context.
There are a several libraries that handle dependency management and script loading, but I'm not going to cover any of that right now:
To create a namespace, you must first create an object in the global context.
Creating a namespace:
At its most basic level, this is as easy as:
window["MyOrg"] = {};
Typically, your base object won't have any data or functions but will rather be composed of submodules. The most basic form for creating submodules is practically the same:
MyOrg.submodule = {}
You can extend this pattern to any level you want. e.g. MyOrg.submodule.tools.usefulFunction
Note: If you are defining your modules and sub modules in different files that may be loaded in any arbitrary order, you must first check to see if your namespace (and any parent modules) exists so 1) you don't get an error when defining your module and 2) so you don't overwrite any modules, but augment them.
For example, if you're defining the MyOrg.submodule
module, you would need to include:
var MyOrg = MyOrg || {};
MyOrg.submodule = MyOrg.submodule || {};
Now that you have your submodule setup, you can easily assign members to it using the expected notation:
MyOrg.submodule.add = function (x, y) {
return x + y;
}
MyOrg.submodule.CONSTANT = 42;
If you can guarantee that you are defining the sub module for the very first time (no risk of overwriting anything), you can also use:
MyOrg.submodule = {
add: function (x, y) {
return x + y;
},
CONSTANT: 42
};
"Advanced" methods
Ok, you should about get the gist of it. However, there are slightly more advanced patterns that you can follow, particularly the "Module Pattern:"
MyOrg = MyOrg || {};
MyOrg.submodule = (function () {
/* any variables (incl. functions) in here are effectively private -- they
cannot be accessed or modified unless they are explicitly exposed. */
var privateVariable = 42;
/* We return an object that will define the public API. Functions defined
in this object still have access to our "private" scope */
return {
getVar: function () {
return privateVariable;
},
setVar: function (value) {
privateVariable = value;
}
};
})();
You use your modules using the same exact notation, but with the added benefit of having private variables and functions:
MyOrg.submodule.setVar(2);
MyOrg.submodule.getVar(); // 2
Regarding your second question, there are a few ways you could do that.
First, you could add generate the javascript on the server side with the relevant data already baked in.
var MyOrg = MyOrg || {};
MyOrg.userInfo = {
userName: "<%= @user.user_name %>",
location: "<%= @user.location %>"
//etc.
}
You can also fetch it from the server from the client-side using AJAX and JSON
$.ajax({
url: "user/getInfo",
success: function (data) {
// data is an object created from a JSON string containing info for the
// current user, presumably using session data.
alert(data.userName)
}
});
If you use this method you may have to use callbacks in your user module to get the relevant info, or you can implement caching methods (with the added benefit of not creating so many server requests).
You can probably declare a base javascript file called base.js and define various namesspaces as below
base namespace
yourcompany.Projectname = {};
yourcompany.Projectname.modules = {};
yourcompany.Projectname.components = {};
and then in each javascript files , you can create functions with the above namespace
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With