I'm using the AMD module pattern and until now, it has been relatively simple to hide what would otherwise be global objects:
define([], function(){
/*jquery here */
var tmp = $;
$ = undefined;
return tmp;
}
However, I'm curious if it's possible to do something similar with google's global objects (I guess they're really into these.. maps and pretty much any of its APIs use em).
Just doing what I've done before actually breaks the code because. It seems internally google is self referencing itself with calls to the global window.google object from scripts it loads on the fly.
I'm going to keep investigating but am curious what you all think!
Thanks.
If you're using RequireJS as your AMD loader, you can use config shims to wrap non-AMD modules, express their dependencies, perform any necessary initializations (where you could clear their global, if the script supports it) and export their global.
For Google Maps, this would look something like this (and no, you probably don't want to clear the global google variable):
require.config({
paths: {
"maps": "https://maps.googleapis.com/maps/api/js?key=API_KEY"
},
shims: {
"maps": {
exports: "google.maps"
}
}
});
Later on, you can use this as a regular AMD module:
require(["maps"], function(maps) {
var map = new maps.Map(document.getElementById("map-canvas"), ....);
...
});
Related
How can one use the excellent ScrollMagic JS plugin as an AMD module to use with requirejs for example?
I couldn't find any reference to that online and looking at the code of ScrollMagic it doesn't seem as if it loads as an AMD module.
It does define 2 variables in the window level at the end of the module:
window.ScrollScene = ScrollScene;
window.ScrollMagic = ScrollMagic;
so it seems that a simple shim won't do because I'll need to export two variables. Is there a way to export that?
Any ideas?
Thanks!
I found something that works for me, it's little bit of a work around, but it does the trick.
in the shim configuration of requirejs I use:
shim: {
'scrollmagic': {
deps:['jquery', 'TweenMax'],
exports: 'ScrollMagic',
init: function() {
return {ScrollMagic: ScrollMagic,
ScrollScene: ScrollScene};
}
}
}
This is to comply with the fact that ScrollMagic requires jQuery as well as GSAP TweenMax libraries to be loaded.
It turns out that using the init function of the shim and then returning the two variables, does the trick.
BUT - this means that for using the ScrollMagic plugin one should use (example):
define(['scrollmagic'], function(scrollmagic) {
var magic = new scrollmagic.ScrollMagic();
var scene = new scrollmagic.ScrollScene({duration: 200});
});
Hoping that this will help somebody in the future...
== Edit ==
ScrollMagic 1.3 now supports the AMD pattern, so all this is unnecessary.
I am starting to use RequireJS now and I was already able to add my project dependencies but I still cannot add a jQuery anonymous function yet.
For example, with my normal_file.js I do something like:
normal_file.js:
define(['dependency1'], function(Dependency) {
var Test1 = ...;
return Test1;
});
Bu from a file that has no module, like the example below, I don't know how to encapsulate it:
lib_file.js:
(function ($) {
// Do stuff...
})(window.jQuery);
the lib_file was not made by me and I'm not sure on how it really works, but I would gess it is an anonymous auto-executed function, is that so?.
Anyway, my goal is to use both files in my main code, like below:
main.js:
requirejs.config({
baseUrl:'/static/editorial/js/',
paths: {
jquery: 'third_party/jquery-1.10.2',
react: 'third_party/react-with-addons'
}
});
var dependencies = [
'third_party/react-with-addons',
'third_party/jquery-1.10.2',
'build/utils/normal_file,
'third_party/lib_file
];
require(dependencies, function(React, $, Test1, ??) {
// do my stuff
});
How should I encapsulate that anonymous function in order to add it as a dependency to my main file?
From the RequireJS docs:
Ideally the scripts you load will be modules that are defined by
calling define(). However, you may need to use some traditional/legacy
"browser globals" scripts that do not express their dependencies via
define(). For those, you can use the shim config. To properly express
their dependencies.
Read this: http://requirejs.org/docs/api.html#config-shim
It has a really good explanation of what you have to do, and gives a nice example.
Basically, you just need to set up a shim config for lib_file.js so Require knows to load the right dependencies before giving you access to that script.
I'm using requirejs in a somewhat special JS environment where an application provides a global singleton (I cannot change this fact, this isn't running in a typical browser environment). I am writing a sort of JS SDK for this application and want to provide various modules that use this global.
Can I wrap that global in a module somehow in order to require it from my modules? Something like
define([the_global_application], function(app)
Thanks for your thoughts on this.
Yes, you just have to define it.
// mysingletonapp.js
// define the module for our global var
define(['list', 'any', 'dependency', 'here'], function (l, a, d, h) {
return yourGlobalVariable;
});
(I don't think you'll have dependencies in there, since you're just wrapping a global var)
The you can use that module as usual:
require(['mysingletonapp'], function (app) {
// do something cool
});
If you want to skip all this, you can use the shim property of RequireJS. You would just need to add this to your options file:
...
shim: {
'globalApplication': {
deps: ['underscore', 'jquery'], // again, you should not need them
exports: 'yourGlobalVar'
}
}
...
shims wrap libraries that don't support AMD, so to have this setting work, you would need a js for globalApplication. This isn't your case.
I am using require.js to load my modules which generally works fine. Nevertheless, I do have two additonal questions:
1) If you have a module that is like a helper class and defines additional methods for existing prototypes (such as String.isNullOrEmpty), how would you include them? You want to avoid using the reference to the module.
2) What needs to be changed to use jQuery, too. I understand that jQuery needs to be required but do I also need to pass on $?
Thanks!
1) If you have a module that is like a helper class and defines
additional methods for existing prototypes (such as
String.isNullOrEmpty), how would you include them? You want to avoid
using the reference to the module.
If you need to extend prototypes then just don't return a value and use it as your last argument to require:
// helpers/string.js
define(function() {
String.prototype.isNullOrEmpty = function() {
//
}
});
// main.js
require(['moduleA', 'helpers/string'], function(moduleA) {
});
2) What needs to be changed to use jQuery, too. I understand that
jQuery needs to be required but do I also need to pass on $?
The only requirement for jQuery is that you configure the path correct
require.config({
paths: {
jquery: 'path/to/jquery'
}
});
require(['jquery', 'moduleB'], function($, moduleB) {
// Use $.whatever
});
In my opinion it's unnecessary to use the version of RequireJS that has jQuery built into it as this was primarily used when jQuery didn't support AMD.
Nowadays it does and keeping it separate allows you to swap another library out easily (think Zepto).
2/ For jquery it's really simple :
require(["jquery", "jquery.alpha", "jquery.beta"], function($) {
//the jquery.alpha.js and jquery.beta.js plugins have been loaded.
$(function() {
$('body').alpha().beta();
});
});
More information on require site : http://requirejs.org/docs/jquery.html#get
1/ in my devs for such extension I did it in a global file without require module code.... and I include it in my app with require... not perfect, but it's work fine
global.js
myglobalvar ="";
(...other global stuff...)
myapp.js
// Filename: app.js
define([
(...)
'metrix.globals'
], function(.....){
myApp = {
(...)
I'm trying to load underscore.js with require.js like this:
require(["libs/underscore-1.2.3.js"], function(_) {
...
});
But this doesn't work because underscore.js exports a module name: define('underscore', function() { ... }).
Without renaming lib/underscore-1.2.3.js, how can I load it with require.js?
Alright, after some more googling, I've found: https://github.com/documentcloud/underscore/pull/338#issuecomment-3245213
Where
#dvdotsenko all AMD loaders allow mapping a module ID to a partial path, usually the configuration is called 'paths', so to do what you want:
requirejs.config({
paths:
underscore: 'js/libs/underscore-1.2.3.min'
}
});
require(['underscore'], function () {});
Since underscore is used by other higher-level modules, like backbone, a common dependency name needs to be used to communicate a common dependency on underscore, and it makes sense to call that dependency 'underscore'. The paths config gives a way to do the mapping to a specific URL you want to use for that dependency.
This doesn't answer my question (ie, I still don't know how I'd go about loading underscore if all I had was a URL), but at least it's a functional workaround.
While this doesn't strike me as the most ideal solution, you can require your external files, and then require their registered module names in the inner block.
JSFiddle Example
require(
['require','http://documentcloud.github.com/underscore/underscore-min.js'],
function(require){
require(['underscore'],function(_){
var a = _.intersection([1,2,3],[2,3,4]);
document.write("Underscore is available in the closure : " + a);
})
}
)
It might not look pretty, but that might be a recommended pattern for loading up initial assets so that they can be required intuitively in dependent modules.