SoundManager2 and require.js - requirejs

SoundManager2 flash component need a specific global JavaScript variable (soundManager) to be present in global scope. This way flash player communicates with SoundManager2 JavaScript API.
The problem is that when you want to build you web application using AMD (require.js) you have to make a compromise and let this global variable to be present.
Is there any way to not break the AMD way of constructing application including SoundManager?

Use RequireJS shim config to wrap your non-AMD library as a module that exports the global variable:
http://requirejs.org/docs/api.html#config-shim
requirejs.config({
paths: {
'soundmanager2' : 'some/path/soundmanager2'
},
shim: {
'soundmanager2': {
exports: 'soundManager'
}
}
});
Then, require the SoundManager2 shim like any other dependency, and use it in your own module code:
define(['soundmanager2'], function(soundManager) {
soundManager.setup({ ... });
soundManager.beginDelayedInit();
// The following may help Flash see the global.
window.soundManager = soundManager;
return soundManager;
});

Related

requirejs - define global variable as amd module

I wrote a requirejs app and it will be included in various environments, some of them will already provide some javascript frameworks, that i would like to reuse insteadof the provided amd modules i bring along.
I am speaking about jquery and Foundation. Some of my app-scripts make use of those frameworks themselves and i would like to do something like the following example, but i cant figure out, if this can even be done with requirejs and if yes - how...
requirejs.config({
paths: {
"jquery": "window.$",
"foundation": "window.Foundation",
"foundation.module": "window.Foundation.Module"
},
shim: {
"jquery": {
exports: "window.$"
},
"foundation": {
deps: ["jquery"],
exports: "window.Foundation"
}
}
});
Can i achieve something like this?
What you are looking for is a proxy module. As the Foundation and jQuery is already loaded, before the RequireJS I assume.
It is quiet simple, just define a module which will return a global variable and that's all, here, take a look at jQuery example:
define('jquery', function () {
return window.$;
});
No config needed for that. You can remove the paths and the shims as they are no needed.

Why do I need to add a "shim" for AngularJS when using Require.js?

I have seen several examples that use this:
main.js
/*global require*/
'use strict';
require.config({
paths: {
angular: './angular',
app: './Content/app',
ngAnimate: './Scripts/angular-animate',
uiRouter: './Scripts/angular-ui-router'
},
shim: {
angular: {
exports: 'angular'
}
}
});
require(['angular', 'app'], function (angular) {
angular.bootstrap(document, ['app']);
});
Can someone explain to me why the shim is needed? My application uses other modules such as angular-ui router, jQuery etc. Do I need to do something similar and add a shim for these?
The rule is pretty simple: if a library/script/package/plugin is AMD-aware, then you don't need a shim. (Actually, you must not use a shim for it.) If it is not AMD-aware, then you need a shim.
A library/etc is AMD-aware if it detects that an AMD loader is present and calls define to make itself known to the loader.
jQuery from about 1.8 onwards has not needed a shim because it calls define. Angular, on the other hand, does not call define.
To know whether a specific piece of code needs a shim, you can read its documentation or if the documentation is not clear on this, then you can check the source code for a call to define. For instance jQuery 1.11.0 has this code:
// 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.
if ( typeof define === "function" && define.amd ) {
define( "jquery", [], function() {
return jQuery;
});
}
How it looks like will vary from one case to the other but the basic think you want to look for is the check that define exists, is a function, has the amd property set and the call to define.
(Note that jQuery is a special case where they decided to hard code the name of the module in the define call (first parameter: jquery). Generally the name of the module won't be present in the define call but will be left for RequireJS to infer on the basis of the file name.)

requirejs with existing globals

I have a built library (concatenated, minified and included before require.js) of several globals (jQuery + plugins, constructor functions, etc ). This library is used as a base on which apps are built on top of, with assumed dependencies. i.e, if I include my app scripts after the library, then I can freely use jQuery and constructors without any issues.
For bigger apps I'm considering using requirejs (to manage the different modules within the app), while still using this built library. How might I add existing globals like jQuery to the dependency list in require?
<script src="pathto/lib.js" type="text/javascript"></script>
<script src="require.js" data-main="../js/app" type="text/javascript"></script>
requirejs.config({
shim: {
'jquery': {
exports: '$'
}
},
// jQuery is already loaded with lib.js, no need for any path...
path : {
jquery : 'jquery.js'
}
});
Is this possible? Or should I just continue with assumptions that certain globals will exist within the app modules because lib.js was included before require / the app js?
Using require to load the lib.js is not possible, because it is part of a CMS.
-- EDIT --
What about using a named module, and just return a handle on the global object, as that is where the lib content sits anyway?
define("lib", function () {
return this;
});
require(["lib"], function (lib) {
// use existing globals found in lib via
lib.jQuery
// or simply
jQuery
});
That allows me to follow the require() convention of naming dependencies, rather than assuming.
I am doing the exact same thing for my project where I load jquery from a CDN, so my path configuration looks like this
path: {
'jquery': '//path/to/the/cdn'
}
In your case, I think you should do as you updated (define and then return), because in some 3rd-party libraries, they might define jquery as the dependencies. If you don't have jquery in your RequireJS configuration, you have to modify the source code of the 3rd party libraries

Cannot get log4javascript to work with an InPageAppender when using requirejs

If I use log4javascript without requirejs, everything (including in-page appenders) works as expected.
When using requirejs, this works (a pop-up window appears with the warning):
var log = log4javascript.getDefaultLogger();
log.warn("This is a test error message.");
but this doesn't work (no in-page area is displayed):
var log4j = log4javascript.getLogger();
var log4jInPageAppender = new log4javascript.InPageAppender();
log4j.addAppender(log4jInPageAppender);
log4j.warn("This is a warning!");
It is shimmed like this:
requirejs.config({
shim: {'log4javascript': {exports: 'log4javascript'}
}
});
Everything seems to be defined properly for log4javascript so my log4j and log4jInPageAppender variables are set with valid values.
The problem is that the InPageAppender relies on log4javascript's own page load handling code to know whether it can start drawing itself. When loaded via RequireJS, the page is already loaded and log4javascript's page load handling code never runs.
You can get around this by calling log4javascript.setDocumentReady(). The most sensible place to do this would seem to be in the shim init() function, but I'm no expert in RequireJS so there may be a better way:
requirejs.config({
shim: {
'log4javascript': {
exports: 'log4javascript',
init: function() {
log4javascript.setDocumentReady();
}
}
}
});

JamJS - Still pulls for dependencies separately when compiled - Underscore not loaded for context?

A am relatively new to JamJS, and struggle to make it work properly.
I've got a very simple project based on Backbone and RequireJS, where I use JamJS to manage dependencies, namely: Backbone, _, Less, $, modernizr, underscore, bootstrap.
I tend to follow the method used by Backbone Boilerplate.
This is the code I use to get the Jam-compiled requireJS config file, together with my application-specific require config:
in html:
< script data-main="/assets/js/app/config" src="/assets/js/jam/compiled.min.js"> < /script>
'Compiled.min.js' is obviously the 600kb minified file generated by Jam.
The '/app/config' file is my Require.js configuration file where I'm planning to include all my project-specific code, not managed by the dependency manager.
Here's app/config.js:
require.config({
baseUrl:'/assets/js/',
deps: ['less','modernizer','bootstrap-jam','app/main'],
paths: {
'homeView': 'app/views/homeView'
// Use the underscore build of Lo-Dash to minimize incompatibilities.
,'lodash': '../jam/lodash/dist/lodash.underscore.min'
},
map: {
},
shim: {
}
});
(the files in deps are the ones I need on every page + my main.js - kind of a router.
The problem is that, in my homeView (which is initialized by main.js), I do this sort of thing:
define(['backbone'], function (Backbone) {
return Backbone.View.extend({
el:$('#homepageWrapper'),
initialize: function () {
this.$('#subTitle').text('This text is generated by homeView - the default Backbone View.');
}
})
});
As you can see I want Backbone to be available in this view. I assume that it's available through the compiled Jam code, however when I look in the Network panel in the Web Inspector, I see that this dependency is pulled in separately- this happens to any resource I try to use, not just Backbone.
I suspect that it might be something to do with the error I get as well, which I haven't been able to figure out. When using the compiled jam config, I get:
Uncaught Error: Module name "underscore" has not been loaded yet for
context: _. Use require([])
I'd really appreciate help with this
Thanks.

Resources