requiring optional javascript files with requirejs (e.g. require a locale specific file) - requirejs

A few of the jquery plugins we rely on offer the ability to include locale/culture specific files to make non-en-us users feel more at home with their functionality (for example, jquery-globalize and bootstrap-datapicker).
The old school way of achieving this was as follows (where 'en-AU' is determined on the fly, sometimes resulting in a 404 for missing cultures):
<script type="text/javascript" src="/js/globalize/globalize.js"></script>
<script type="text/javascript" src="/js/globalize/cultures/globalize.culture.en-AU.js"></script>
Is there a recommended way of achieving this with requirejs (note that globalize is included as a shim)?
Here's my first attempt, not yet sure how the requirejs optomizer will handle it...
Globalize = require("globalize");
...
locale = module.config().locale;
if (locale != null) {
require(["globalize/globalize.culture." + locale], function() {
logger.debug("Loaded locale '" + locale + "'");
Globalize.culture(locale);
}, function() {
logger.debug("Unable to load locale '" + locale + "'");
});
}
edit: the optimizer handles it fine but but the solution doesn't really work because the culture file is loaded asynchronously it's possible that the app has used Globalize before the culture is set.

Kendo does something similar in their code.
This is a slight modification of their technique. This particular style allows the modules to load either through require or direct script inclusion.
I modified it slightly to set up the prereqs. On the downside, this code will no longer work through the r.js optimizer.
var myLocalPrereqs = ['file_english.min'];
("function" == typeof define && define.amd ? define : function (preReqs, func) {
return func()
})(myLocalPrereqs, function () {
(function () {
// Your module code goes here...
})()
});

Related

Code coverage for UMD block in nodejs module

I've written a node module with UMD (Universal Module Definition) Pattern to make it compatible with amd and plain javascript as well.
The definition is as below
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(factory);
} else if (typeof exports === 'object') {
module.exports = factory();
} else {
root.myModule = factory();
}
}(this, function (global) {
...
return {};
}));
With mocha & chai the tests are running fine, the only issue is that since the tests are executed from within node the code coverage for define(factory); and root.myModule = factory(); lines is showing red.
Just wanted to know if there is any way(maybe a hack) to get 100% coverage for this code with mocha chai.
Sure!
How coverage tools for JS basically work, is that their injecting little bit of tracker code for each line. So what you need is that the execution flow wonders there.
Since this is an if-else logic, to get 100% you will be needing multiple test scenarios to cover this.
Note: it's also important for actually achieving this effect, that loading that file (factory) should happen after every scenario setup, because that is when those module-loading-if-else lines are executed. Now this depends on what is your file/module loading in your test execution environment.
Now to enter into that branch of the if-else create a test scenario where you can just enforce the existence of that define function with a few lines like (e.g. in a beforeEach section):
define = function () {
console.log('hello I am a fake define, but I will be defined ...');
console.log(' ... so that if else branch will be executed.');
}
// and of course the needed .amd property.
define.amd = true;
I think the same weird stuff can be done w/ the exports variable, but it might be hard to achieve if you are just pure CommonJS require-ing that file, since require-ing defines the exports variable for that file context, so maybe you could modify your production code for this weird case. I wouldn't do that, but you said any way:
...
} else if (typeof exports === 'object' && testExportsEnabled) {
...
Now using this you can just have one scenario where in beforeEach you do: testExportsEnabled = true; and w/ this being false, the last branch should be executed.
Of course you can execute all branches with such a simple trick! Now to have no code modification AND trigger the third branch (basically the case for simple script-tag-loading in browser), you will need to dig in into your module loading code and create some hacks there, but that is a bit too much for me in an SO question! :]
Take care!

How to use underscore.string globally in a web page (with requireJS)

The documentation says once underscore.string included in my application, the library is available using s, __s global variables (http://epeli.github.io/underscore.string/#others), or within underscore properties __.str or __.string.
This simple code should then work properly (with config paths correctly set) :
require(['underscore','underscore.string'], function(){
console.log(s('test').capitalize().value());
});
But it does not work at all. Here is a simple jsfiddle example. I probably did something wrong, but I can't figure out what.
https://jsfiddle.net/mvenrtgy/10/
The relevant test code is:
require.config({
paths: {
'underscore':'https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min',
'underscore.string':'https://cdnjs.cloudflare.com/ajax/libs/underscore.string/3.3.4/underscore.string.min'
}
});
require(['underscore','underscore.string'], function(){
var t = 'This is a simple text I would like to SLUGIFY using unsercore.string';
// underscore is there!
console.log(typeof _)
// now check where underscore.string is...
console.log(typeof _.str);
console.log(typeof _.string);
console.log(typeof s);
console.log(typeof _s);
document.getElementsByTagName('body')[0].innerHTML = '<p>Sample text : ' + t + '</p>';
// this line will cause an error
document.getElementsByTagName('body')[0].innerHTML += '<p><em>Slugified</em> text : ' + s(t).slugify().value() + '</p>';
});
underscore.string is a well-behaved AMD library so it does not pollute the global space. You should change your require call so that it gets the parameters that correspond to the modules you are loading:
require(['underscore','underscore.string'], function(_, s){
By just making this change to your code, I get something that works. The 2nd line of your test comes up as:
Slugified text : this-is-a-simple-text-i-would-like-to-slugify-using-unsercore-string
Also, while underscore.string started as an underscore extension, it has grown beyond that, so you cannot access it through the _ global that underscore leaks into the global space, unless you take care of mixing it in with underscore. The documentation says you can do this:
_.mixin(s.exports());
But the documentation recommends against it because underscore.string will interfere with some of the basic functions that underscore exports. Use at your own risks.

How do you use a requirejs friendy JavaScript file without using requirejs? I.o.w. how to demodularize?

Suppose I have a JS-library, neatly wrapped in a define('myModule', function(myModule) { return myModule.someObject; });
How could I bind the myModule.someObject to global scope (please don't ask why, I know modular programming has a lot of benefits over putting stuff on the global scope), without using requirejs or any other module handling framework?
The thing is: while developing, I'd like to use requirejs. The library that we build should be able to be included by somebody using requirejs (AMD, CommonJS, whatever), but should also be available as window.SomeObject for the people that don't want to use require just for the sake of being able to use our SomeObject. After the development phase, all code will be minified and obfuscated to a single JS file.
I think I'm just googling with the wrong search terms, because all I can find is an answer to the question how to include code that isn't wrapped in a requirejs friendly define function.
Any ideas on this would greatly be appreciated. Thanks!
--- EDIT ---
My file (before it all started) looked like:
(function(define, global) {
define([a,b,c],function(theA, theB, theC) {
return theA + theB + theC; // or something, it doesn't matter
});
})(define, this);
I'm thinking of something like this:
(function(define, global) {
// same as above
})(typeof define === 'function'
? define
: function(factory /* need more args? */) { /* solution here */ }, this);
But I'm not sure how to implement it properly...
I guess you need to wrap your modules so that they could be accessed without requirejs:
if ( typeof define === "function" && define.amd ) {
define( "mymodule", [], function () {
// do your logic
return mystuff;
} );
} else {
// do your logic
window.mystuff = mystuff;
}
Look at jQuery as an example.
I would refrain from giving your module an id if you can help it, it makes it less portable. jQuery is incredibly annoying that it forces you to set a jquery path option, but they did it for compatibility reasons. Always prefer anonymous modules if you can.
From the jQuery source
// Register as a named AMD module, since jQuery can be concatenated with other
// files that may use define, but not via a proper concatenation script that
// understands anonymous AMD modules. A named AMD is safest and most robust
// way to register. Lowercase jquery is used because AMD module names are
// derived from file names, and jQuery is normally delivered in a lowercase
// file name. Do this after creating the global so that if an AMD module wants
// to call noConflict to hide this version of jQuery, it will work.
James Burke goes into a little more detail here also.
I would instead use a more common example from the umdjs repository:
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['b'], factory);
} else {
// Browser globals
root.amdWeb = factory(root.b);
}
}(this, function (b) {
//use b in some fashion.
// Just return a value to define the module export.
// This example returns an object, but the module
// can return a function as the exported value.
return {};
}));
For another example that also supports CommonJS, check out the reqwest library:
!function (name, context, definition) {
if (typeof module != 'undefined' && module.exports) module.exports = definition()
else if (typeof define == 'function' && define.amd) define(definition)
else context[name] = definition()
}('reqwest', this, function () {
return {};
});
How can I provide a library to others that does not depend on RequireJS?
This allows you to ship code that does not ship with all of RequireJS, and allows you to export any kind of API that works on a plain web page without an AMD loader.
You need to make a build config file which uses wrap and almond.
It all feels pretty dirty, but I've had it working (by following the almond ReadMe) with exactly what you're describing.

Why use alternate requirejs define: define(function(require) { ... }

I have seen people use an alternate define "syntax" in require js than what is described in the require js' documentation, or in many tutorials.
The usual define "syntax":
define(['module/first'], function (firstModule) {
//Module code with a dependency on module/first goes here.
});
The alternate define "syntax":
<script data-main="app/config" src="assets/js/libs/require.js"></script>
file: config.js:
require.config({
paths: {
jquery: '../assets/js/libs/jquery'
}
});
require(['app']);
file: app.js:
define(function(require) {
var FirstModule = require('modules/first');
//Module code with a dependency on module/first goes here.
What are the advantages, and disadvantages of using this alternate "syntax"?
I think your explanation is a bit misleading: in both cases, you will have a top-level require call with a data-main attribute specifying a file to kick-start the process of requiring different modules.
So typically you will have this in your HTML:
<script data-main="app/config" src="assets/js/libs/require.js"></script>
Then, in both cases, you would have a file app/config which sets your configuration (although you could do this directly in the HTML) and more importantly calls require on your modules:
require.config({
paths: {
jquery: '../assets/js/libs/jquery'
}
});
require(['app']);
Now, it's when we get to defining modules with dependencies that these styles differ. In the amd style you pass in the module names (paths) as an array, and a function which takes the same number of arguments:
app.js
define(['module/first', 'module/second', 'module/third'], function (firstModule, secondModule, thirdModule) {
// use firstModule, secondModule, thirdModule here
});
In the simplified CommonJS syntax, you just pass require into define and then require whatever modules you need inline:
app.js
define(function(require) {
var firstModule = require('modules/first');
var secondModule = require('modules/second');
var thirdModule = require('modules/third');
// use firstModule, secondModule, thirdModule here
}
Getting back to your original question, the advantages of the CommonJS style over the amd style should be clear.
For one thing, with the conventional syntax, if there are many modules being required, it is very easy to mistakenly assign modules to the wrong variable names. Consider this common case:
define(['jquery', 'underscore', 'backbone', 'modules/first', 'modules/second', 'modules/third', 'i18n', 'someOtherModule'], function ($, _, Backbone, first, second, third, I18n, someOtherModule) {
// ...
});
Right away, you can see that when we add a new module to this list, we have to be very careful that the corresponding new function argument appears in the right place, or else we can have jQuery assigned to Backbone, etc. In some cases this can create very subtle bugs that are hard to track down.
Now consider the CommonJS syntax:
define(function(require) {
var $ = require('jquery');
var _ = require('underscore');
var Backbone = require('backbone');
var firstModule = require('modules/first');
var secondModule = require('modules/second');
var thirdModule = require('modules/third');
var I18n = require('i18n');
var someOtherModule = require('someOtherModule');
// ...
}
Note that:
The pairing of module to variable name is very clear.
The order of the require statements is not important, since the variable names are being paired separately rather than as a mapping between an array and a function.
The modules do not need to be assigned first. They can be assigned anywhere, so long as it is before the module is actually used.
Those are just a few reasons that come to mind, I'm sure there are others. Basically, if you just have one or two dependencies, either syntax will do fine. But if you have a complex network of module dependencies, the CommonJS syntax is probably preferable.
Note that in the RequireJS docs, they mention this small caveat:
Not all browsers give a usable Function.prototype.toString() results. As of October 2011, the PS 3 and older Opera Mobile browsers do not. Those browsers are more likely to need an optimized build of the modules for network/device limitations, so just do a build with an optimizer that knows how to convert these files to the normalized dependency array form, like the RequireJS optimizer.
But this is not a major issue:
Since the number of browsers that cannot support this toString() scanning is very small, it is safe to use this sugared forms for all your modules, particularly if you like to line up the dependency names with the variables that will hold their module values.

RequireJS does not run data-main script before loading required modules

My project includes the following files:
./index.html
./js/main.js
./js/vendor/require.js
./js/viewmodel/vm.js
The index.html has the following relevant snippet:
<script data-main="js/main.js" src="js/vendor/require.js"></script>
<script type="text/javascript">
require(['viewmodel/vm', 'ko'],
function(viewmodel, ko) {
ko.applyBindings(viewmodel);
}
);
</script>
The js/main.js file is as follows:
var root = this;
define('jquery', ['http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.3.js'], function () { return root.$; });
define('ko', ['http://ajax.aspnetcdn.com/ajax/knockout/knockout-2.1.0.js'], function (ko) { return ko; });
The js/viewmodel/vm.js file...
define(['jquery', 'ko'],
function($, ko) {
return {
subject: 'world',
greeting: 'hello'
}
}
);
When you open a browser to index.html, then the browser tries to load a file called js/ko.js instead of using the module defined in main.js. It seems like the js file pointed to by the data-main attribute is not guaranteed to run before dependency resolution. This does not seem correct to me since one purpose of the data-main js file is to define require configuration (i.e. path, shim, etc). I am using require v2.1.2.
This works perfectly fine if I copy the contents of my main.js file into the script block in index.html. By "perfectly fine" I mean that it resolved ko to be a module and finds the appropriate CDN link to resolve ko instead of trying to download ./js/ko.js.
to use the data-main attribute for configuring your whole application, it is necessary that it is the single entry point for all your code.
your 2nd script block breaks this requirement by providing a 2nd entry point. since these entry points will resolve independently of each other (and asynchronously), you cannot rely on one to affect the other.
to resolve it, refactor your code in a way that provides a single entry point to your application and do your configuration via this entry point.
That's because requirejs sets the async. Attribute on the script.
The boolean async attribute on script elements allows the external
JavaScript file to run when it's available, without delaying page load
first.
This means that both scripts are loaded and evaluated parallel, so none of the two scripts can access methods or functions from the other one.
If you want to define requirejs variables in one script you mustn't load that script with require js.
For me there are three possibilities how you can solve that problem:
Add the content of main.js to your page (as you mention)
Load the main.js file without requirejs as normal script
Define the require config before loading the scripts (link to requirejs docu )
I had the same problem. The architecture of the site that i was working was components that was loading asynchronous at each part of the page.
Each component has its own html, css, and js code.
So, my solution is to keep a guard function for all the required dependency code, to protect them from running before the main javascript file:
index.html
<head>
<script type="text/javascript">
window.BeforeMainGuard = {
beforeMainLoadedFunctions: [],
hasMainLoaded: false,
guard: function( func ) {
console.assert( typeof func === 'function' );
if( this.hasMainLoaded ) {
func();
}else {
this.beforeMainLoadedFunctions.push( func );
}
},
onMainLoaded: function() {
for( var i = 0; i<this.beforeMainLoadedFunctions.length; ++i ) {
var beforeMainLoadedFunction = this.beforeMainLoadedFunctions[i];
beforeMainLoadedFunction();
}
this.beforeMainLoadedFunctions = null;
this.hasMainLoaded = true;
}
};
</script>
<script data-main="js/main.js" src="js/vendor/require.js"></script>
<script type="text/javascript">
window.BeforeMainGuard.guard( function() {
require(['viewmodel/vm', 'ko'],
function(viewmodel, ko) {
ko.applyBindings(viewmodel);
}
);
});
</script>
</head>
js/main.js
require.config({
// your config
});
require( [ 'AppLogic' ], function( AppLogic ){
AppLogic.Init();
window.BeforeMainGuard.onMainLoaded();
} );

Resources