The RequireJS docs say that to support older versions of IE, you need to configure enforceDefine: true
.
So if you want to support Interne
I use this configuration inside my project:
startup.js
require.config({
paths: {
/* other paths are omitted */
'bootstrap': '../libs/bootstrap'
},
shim: {
'bootstrap/bootstrap-slider': { deps: ['jquery'], exports: '$.fn.slider' },
'bootstrap/bootstrap-affix': { deps: ['jquery'], exports: '$.fn.affix' },
'bootstrap/bootstrap-alert': { deps: ['jquery'], exports: '$.fn.alert' },
'bootstrap/bootstrap-button': { deps: ['jquery'], exports: '$.fn.button' },
'bootstrap/bootstrap-carousel': { deps: ['jquery'], exports: '$.fn.carousel' },
'bootstrap/bootstrap-collapse': { deps: ['jquery'], exports: '$.fn.collapse' },
'bootstrap/bootstrap-dropdown': { deps: ['jquery'], exports: '$.fn.dropdown' },
'bootstrap/bootstrap-modal': { deps: ['jquery'], exports: '$.fn.modal' },
'bootstrap/bootstrap-popover': { deps: ['jquery'], exports: '$.fn.popover' },
'bootstrap/bootstrap-scrollspy': { deps: ['jquery'], exports: '$.fn.scrollspy' },
'bootstrap/bootstrap-tab': { deps: ['jquery'], exports: '$.fn.tab' },
'bootstrap/bootstrap-tooltip': { deps: ['jquery'], exports: '$.fn.tooltip' },
'bootstrap/bootstrap-transition': { deps: ['jquery'], exports: '$.support.transition' },
'bootstrap/bootstrap-typeahead': { deps: ['jquery'], exports: '$.fn.typeahead' },
}
});
require(['domReady', 'app'], function(domReady, app) {
domReady(function() {
app.init();
});
});
then in my code I use this:
define(['jquery', 'underscore', 'backbone', 'text!templates/photos-list.html'], function($, _, Backbone, html) {
var PhotosListView = Backbone.View.extend({
viewImageFullscreen: function(e) {
e.preventDefault();
require(['bootstrap/bootstrap-modal', 'text!templates/photo-modal.html'], function(modal, htmlModal) {
var modalTemplate = _.template(htmlModal, options);
$('body').append(modalTemplate);
// setup
$(selector + '_modal').modal({
backdrop: true,
keyboard: true,
show: false
}).css({
'width': function() { return ($(document).width() * 0.55) + 'px'; },
'margin-left': function() { return -($(this).width() * 0.5); }
});
// trigger `modal`
$(selector + '_modal').modal('show');
}); // require() call
// ...
According to the docs that error is thrown if "Script was part of a shim config that specified a global string property that can be checked for loading, and that check failed."
To fix this you need to add exports value in the shim config so that RequireJS can check whether the script was succesfully loaded. In case of Bootstrap that's slightly tricky as Bootstrap doesn't 'export' a propert global variable only a bunch of jquery plugins, but you can use any of those plugins as an export value e.g. $.fn.popover
:
{
paths: {
"bootstrap": "../bootstrap",
"jquery": "../jquery-1.8.2"
},
shim: {
"bootstrap": {
deps: ["jquery"],
exports: "$.fn.popover"
}
},
enforceDefine: true
}
Instead of doing the magic with shim, I converted the bootstrap JS into a module:
define([ "jquery" ], function($) {
// bootstrap JS code
});
Everything else I found in the forums and on stackoverflow did not work for me because I get jQuery from the CDN. I assume because I hit the issue as described in the requireJS doc on http://requirejs.org/docs/api.html
Do not mix CDN loading with shim config in a build. Example scenario: you load jQuery from the CDN but use the shim config to load something like the stock version of Backbone that depends on jQuery. When you do the build, be sure to inline jQuery in the built file and do not load it from the CDN. Otherwise, Backbone will be inlined in the built file and it will execute before the CDN-loaded jQuery will load. This is because the shim config just delays loading of the files until dependencies are loaded, but does not do any auto-wrapping of define. After a build, the dependencies are already inlined, the shim config cannot delay execution of the non-define()'d code until later. define()'d modules do work with CDN loaded code after a build because they properly wrap their source in define factory function that will not execute until dependencies are loaded. So the lesson: shim config is a stop-gap measure for for non-modular code, legacy code. define()'d modules are better.
Converting the bootstrap into a ordinary AMD module and removing the shim config solved it for me. Only drawback: you cannot retrieve bootstrap from the bootstrap CDN.
@lexeme & @benjaminbenben how about wrapping this concept in a RequireJS plugin which creates the shim, requires jQuery and also returns jQuery so you wouldn't need to include this manually?
To use a bootstrap component you would simply use:
define(['bootstrap!tooltip'], function($){
$('[data-toggle="tooltip"]').tooltip();
});
And you would use this require-bootstrap-plugin to make it work.