Does anyone know what the pattern is for being able to create a module pattern but with being able to set the name space that the module lives under dynamically.
So instead of what is below:-
var MODULE = (function () {
var my = {},
privateVariable = 1;
function privateMethod() {
// ...
}
my.moduleProperty = 1;
my.moduleMethod = function () {
// ...
};
return my;
}());
MODULE could be set to anything you like, I remember seeing it done i a screencast but can't remember where...
Basically i'd like to create a library that could be assigned to any namespace the implementer likes.
I'd think you'd just be able to add a method that lets you set it, and nullify MODULE.
http://jsfiddle.net/yrsdR/
my.namespace = function( ns ) {
window[ns] = my;
window.MODULE = null;
}
then:
window.MODULE.namespace( "myNamespace" );
window.MODULE; // null
window.myNamespace // object
or you could have it return the module to whatever variable you want.
http://jsfiddle.net/yrsdR/1/
my.namespace = function() {
window.MODULE = null;
return my;
}
window.myNamespace = MODULE.namespace();
window.MODULE; // null
window.myNamespace // object
Funny to come across this now, I just set up a new code base this way. This is how I approached it (it depends on 1 extra global variable however):
// ability to rename namespace easily
var AXS_NS = 'App';
window[AXS_NS] = (function (app, $, Modernizr) {
app.config = {
debug: false
};
app.init = function() {
console.log('init');
};
return app;
})(window[AXS_NS] || {}, jQuery, Modernizr);
Then you could do:
jQuery(function($){
App.init();
});
I know this is a long ways after the original question. And I'm not sure of the relevance of having a dynamically named javascript object. But the following pattern does this is a reasonable way by allowing you to set up the object namespace name in the script element of your html page.
Something like
<script src="js/myscript.js" namespaceName="myObject"><script>
Which allows you to then call myObject.hello() in your javascript.
Example javascript that uses this solution.
/**
* Dynamic mechanism for setting a javascript namespace.
*
* This works by adding the namespaceName as an attribute to the script
* element on your page. Something like
*
* **<script src="js/myscript.js" namespaceName="myObject"><script>**
*
* When the script has loaded it will have created a new javascript object
* with the nemespace name "myObject".
*
* You can now use myObject.hello() which returns "ns.hello() called"<br/>
*
* This works on later versions of chrome, firefox and ie.
*/
(function (ns) {
ns.hello = function () {
return "ns.hello() called";
}
} (window[document.getElementsByTagName('script')[document.getElementsByTagName('script').length-1].attributes['namespaceName'].value]=
window[document.getElementsByTagName('script')[document.getElementsByTagName('script').length-1].attributes['namespaceName'].value] || {}));
The
window[document.getElementsByTagName('script')
[document.getElementsByTagName('script').length-1]
.attributes['namespaceName'].value]
Is used to pull the attribute namespaceName value from the script load
Related
I got js code from a design company, but I do not understand the reason for passing a function to a self executing function.
Here is the outline of the code.
(function(core) {
if (typeof define === "function" && define.amd) {
define("abc", function() {
var abc;
abc = window.Abc || core(window, window.jQuery, window.document);
abc.load = function(res, req, onload, config) {
var base, i, load, resource, resources;
resources = res.split(",");
load = [];
base = (config.config && config.config.abc && config.config.abc.base ? config.config.abc.base : "").replace(/\/+$/g, "");
if (!base) {
throw new Error("Please define base path to Abc in the requirejs config.");
}
i = 0;
while (i < resources.length) {
resource = resources[i].replace(/\./g, "/");
load.push(base + "/components/" + resource);
i += 1;
}
req(load, function() {
onload(abc);
});
};
return abc;
});
}
if (!window.jQuery) {
throw new Error("Abc requires jQuery");
}
if (window && window.jQuery) {
core(window, window.jQuery, window.document);
}
})(function(global, $, doc) {
var _c = {};
...
return _c;
});
Is there benefit of writing code such way over something like below?
(function( core, $, undefined) {
...
} (window.core= window.core|| {}, jQuery )};
Is this some advanced technique?
Basically, ....kinda.
In Javascript, functions are treated as first-class objects. This means you can pass them around in variables and whatnot. The first part, (function(core) { ... }), creates an anonymous function, taking a single argument called core. The parentheses around the function basically just resolve to a function. The second part, (function(global, $, doc) { ... }), is creating another function, which is passed immediately into a call to the first function as the value of core.
Put this way, here's what's happening.
// Define the first function (the one that takes core)
var firstFunc = function (core) { /* ... */ };
// Define the second function (the one that takes global, $, and doc)
var secondFunc = function (global, $, doc) {
var _c = {};
/* ... */
return _c;
};
// Call the first, passing in the second.
firstFunc(secondFunc);
The above code and the code you posted accomplish the same thing. One purpose for writing something like this would be to sandbox the second function so that the first can specify its own local versions of variables global, $, and doc, which avoids conflicts with, say, active-running versions of jQuery (which typically declares its own globally-scoped $ variable).
EDIT: Now that the code in the first function has been filled in, we can say for sure that the reason for doing this is to resolve dependencies and ensure they are present before manually passing them into the second function. From the look of the code provided, it appears that this is enforcing the presence of abc (which I'm assuming is some dependency) via require.js, as well as ensuring that jQuery is present. In addition, it looks like the values in _c returned from the function are used as a part of that dependency enforcement process, though I can't tell exactly how by looking at it.
I'm trying to use nunjucks in my JS stack.
I have pre-compiled my templates with gulp-nunjucks:
gulp.task("build:tpl", function() {
var options = {
// ... empty for the moment
};
return gulp.src("src/text/*.txt", { base : path.join(__dirname, "src/text") } )
.pipe(nunjucks())
.pipe(concat("ui-template.js"))
.pipe(gulp.dest("js/tpl"));
});
Then I include ui-template with require JS for use:
/**
* setup UI
*
* "ui-colorchess.txt" is the main template
* it contains (nested) subtemplates (include "ui-history.txt" and so forth)
*/
UI.prototype.setup = function() {
var that = this;
// first we grab precompiled templates
require(["js/tpl/ui-template.js"], function() {
// ... into requirejs variables (or not)
// some context vars, just to provide an ID in HTML
var ctx = {
id : "colorchess-1",
otherStuff : 2
};
var env = new nunjucks.Environment(
new nunjucks.WebLoader("/js/tpl")
);
// it sucks here !
var c = env.render("ui-colorchess.txt", ctx);
console.log(c);
// try to assign result to a container
that.bounds.innerHTML = c;
// one more time... when it will work !
// var board = new Board("colorchess-board-" + that.key);
// board.firstDraw();
});
And I get an error in my console:
Uncaught Template render error: (ui-colorchess.txt)
TypeError: Cannot read property 'resolve' of undefined
Can anyone identify what's wrong?
Same issue described in sindresorhus/gulp-nunjucks#1.
If you want to concatenate the files, you have to set the name option:
var options = {
name: function (file) {
return file.relative;
}
};
I have solved the problem by doing the following:
renaming my templates in *.html
removing paths like "./subtemplate.txt" in my includes
setting configure("../html")
requiring correctily with requireJS
I have a few questions about Best Practises using javascript in external files and namespacing.
Let's have a namespace MyCompany, global configuration stuff, code for individual pages and maybe some "API"s.
var MyCompany = {};
Global configuration in HTML
MyCompany.root = "/";
Which approach is better
First
MyCompany.Page = {};
(function(ns} {
ns.init = function() {
var root = MyCompany.root;
ajax(root+"somepage.html");
};
}(MyCompany.Page.Home = MyCompany.Page.Home || {});
and in html use
<script>
$( function() {
MyCompany.Page.Home.init();
});
</script>
Second (Page as an Class and its instance)
MyCompany.Page.Home = function() {
var root = MyCompany.root;
this.init = function() {
ajax(root + "somepage.html");
};
};
in html
<script>
var page = new MyCompany.Page.Home();
$( function() {
page.init();
});
</script>
Submodules and Mixing API with Page javascript
If our Homepage has some reviews.
MyCompany.Page.Home.Reviews = function() {
this.init = function() {
load_stuff();
}
};
And now inside Page init use
MyCompany.Home.Page = function(data) {
var reviews = new MyCompany.Home.Page.Reviews();
this.init = function() {
reviews.init();
};
};
Could that cause troubles?
It's obvious that Reviews extends MyCompany.Home.Page, but MyCompany.Home.Page requires Reviews.
It shouldn't cause troubles if instance on MyCompany.Home.Page is created after MyCompany.Home.Page.Reviews are loaded, right? Because Reviews in fact will extend the function object, is that right?
I guess this depends on answer to first question.
It also could be
(function(ns) {
ns.init = function() { MyCompany.Page.Home.Reviews.init(); };
})(MyCompany.Page.Home = MyCompany.Page.Home || {} );
(function(ns) {
ns.init = function() { load_stuff(); };
})(MyCompany.Page.Home.Reviews = MyCompany.Page.Home.Reviews || {});
Also should I somehow separate API of Page javascript?
Such as
MyCompany.APIS.Maps = function(location) {
/* Private variables */
var _location = location;
/* Private functions */
function search_address(address) { .. do search .. }
/* Public interface */
this.search = search_address;
do some initialization ...
};
I'd be glad if anyone reads it all to leave some comment.
Thank you in advance.
Which approach is better? Revealing singleton module (first) or a constructor function/class and its instance (second)?
Depends on your use case. If you don't expect multiple page objects to exist at once (and you hardly seem to), the singleton (with an init function) is really fine. Everything else could be considered wrong or at least overkill.
Same thing holds true for your MyCompany.Page.Home.Reviews (or MyCompany.Home.Page.Reviews?) class module, of which you seem to need only one instance.
It shouldn't cause troubles if instance on MyCompany.Home.Page is created after MyCompany.Home.Page.Reviews are loaded, right? Because Reviews in fact will extend the function object, is that right?
Yes.
(function(ns) {
ns.init = function() { MyCompany.Page.Home.Reviews.init(); };
})(MyCompany.Page.Home = MyCompany.Page.Home || {} );
If you have that ns shortcut available, you should use it:
(function(ns) {
ns.init = function() { ns.Reviews.init(); };
})(MyCompany.Page.Home = MyCompany.Page.Home || {} );
Also should I somehow separate API of Page javascript?
For development: Yes, in every case. Each module should have its own file. When deploying, you might concatenate them together for faster loading, but that's a different question.
I have a javascript function the initializes a bunch of global varaibles for a game.
function buildVariables(fs,fm) {
window.p1HPStart = fm.p1hp;
window.p2HPStart = fm.p2hp;
window.p1HP = 100;
window.p2HP = 100;
window.trn = 0;
}
Right now all this javascript is in the same HTML file. I want to move it to its own .js file and include it in this HTML file. I also want to replace "window" with a different global namespace like fight.p1HP.
How can I do this?
I've seen code like the below as a proposed answer in other similar questions, but I don't quite understand how it can be used to replace window.
var cartTotaler = (function () {
var total = 0; tax = 0.05;
// other code
return {
addItem : function (item) { },
removeItem : function (item) { },
calculateTitle : function () { }
};
}());
Thanks.
// initialize your own global object
if (!window.mySpace) {
window.mySpace = {};
}
// then use it
function buildVariables(fs,fm) {
mySpace.p1HPStart = fm.p1hp;
mySpace.p2HPStart = fm.p2hp;
mySpace.p1HP = 100;
mySpace.p2HP = 100;
mySpace.trn = 0;
}
Then just make sure everywhere you want one of your own variables, you use your namespace in front of it:
mySpace.variableName
Note: this doesn't really "replace" the window object (as there is no way to do that) - it just puts all your global variables into one master global object rather than pollute the global namespace with every single one of your variables.
The name mySpace can be anything you want it to be. Typically, it should be something that is unique to your application that is unlikely to conflict with something any other javascript or library might use.
(function(global){
global.p1HPStart = fm.p1hp;
global.p2HPStart = fm.p2hp;
global.p1HP = 100;
global.p2HP = 100;
global.trn = 0;
}(window));
This creates an 'immediately invoked function expression'. window is passed into the function, which then attaches a number of properties to it.
You can change window to whatever object you want, such as fight.p1HP, and this function will immediately attach the listed properties to that object.
this one for the javascript gurus:
I'm experimenting with a new javascript framework. Its structure is inspired by none other than the mighty jQuery.
It has a global variable called $j, and .. oh, just see it in action:
/* file: jfoo.js */
$j = new (function(){
var modules=[];
this.loadModule = function(mod) {
modules[ modules.length ] = mod;
}
this.hasModule = function(mod) {
for( ind in modules )
if( modules[ind]==mod ) return true;
return false;
}
})();
You see that modules is a private variable. No problem; that just what I intended.
Now, I want to write a plugin that adds a $j.loadBatch method to my system. So..
/* file: loadBatch.jfoo.js */
!$j || (function(){
$j.loadBatch = function(batch) {
for(ind in batch)
modules[ modules.length++ ] = batch[ind];
}
})();
But, since this method is not part of the closure in file jfoo.js, this is not possible.
I also tried this version:
/* file: jfoo.js */
$j = new (function(){
var modules=[];
this.loadModule = function(mod) {
modules[ modules.length ] = mod;
}
this.hasModule = function(mod) {
for( ind in modules )
if( modules[ind]==mod ) return true;
return false;
}
this.extend = function(extensions) {
for( ext in extensions )
this[ext] = extensions[ext];
}
})();
and
/* file:loadBatch.jfoo.js */
!$j || (function(){
$j.extend( {
loadBatch : function(batch) {
for(ind in batch)
modules[ modules.length++ ] = batch[ind];
}
});
})();
But I got no better results.
So, the questions:
Is there any way that I can write the loadBatch method in a separate file and still have it access the private method modules? (I expect the answer to be a resounding NO, but, who knows?)
is there any other way by which I can achive the desired effect without making modules public? (I know how to proceed if I make it public)
does jQuery use private members? how does it get over its "private accessibility" problems then?
Thanks,
jrh
AFAIK there's no way to give access to a "private" variable (variable only within the scope of a closure) to some execution contexts outside its scope, but not others. (e.g. you could write an accessor method but couldn't limit who gets access)