I am using Almond and the r.js optimizer to combine all my scripts in a single file for a Backbone.js-based Single Page Application.
My build file:
({
name: '../bower_components/almond/almond',
include: ['main'],
insertRequire: ['main'],
baseUrl: 'src',
optimize: 'uglify2',
mainConfigFile: 'src/main.js',
out: 'javascripts/scripts.js',
preserveLicenseComments: false,
paths: {
jquery: '../bower_components/jquery/dist/jquery',
underscore: '../bower_components/underscore/underscore',
backbone: '../bower_components/backbone/backbone',
kineticjs: '../bower_components/kineticjs/kineticjs',
'jquery-ui': '../bower_components/jquery-ui/ui',
'jquery.layout': '../bower_components/jquery.layout/dist/jquery.layout-latest'
},
shim: {
'jquery.layout': {
deps: [
'jquery-ui/core',
'jquery-ui/draggable',
'jquery-ui/effect',
'jquery-ui/effect-slide'
],
exports: 'jQuery.fn.layout'
}
}
})
In my Backbone view I initialize the jquery-layout plugin:
define(['backbone', 'underscore', 'jquery.layout'], function(Backbone, _) {
'use strict'
return Backbone.View.extend({
el: $('#application'),
initialize: function() {
this.$el.layout({
west: {
size: '50%',
closable: false,
slidable: false,
resizable: true
}
});
}
});
});
The panes show up correctly, however I cannot resize any of them. I found that $.fn.draggable
(JQuery UI Draggable widget) is not being initialized at the time when the jquery-layout plugin is declared.
This indicates that probably the widget is not being loaded. So I checked the combined source file and noticed that the JQuery UI Draggable widget code appears before the jquery-layout plugin code, which means the dependencies are inserted in the correct order. Printing $.fn.draggable
in the Firebug console also shows that the widget is available, at least after the document is ready.
jQuery, underscore, backbone, jQuery UI are all AMD modules. jquery-layout has no AMD compatibility, hence the shim config. It depends on JQuery UI's ui.core and ui.draggable per their docs.
For all of this to not sound too abstract, here is a demo of the jquery-layout plugin.
I have "wasted" over 8 hours trying to figure this out in vain, any help on how to fix this would save my day. Most probably this would involve only some fix of my shim config in the build file.
I solved the problem by making the non AMD-aware jquery-layout plugin AMD-compatible. I used the onBuildWrite
hook of the r.js optimizer in the build file. This way the jQuery UI dependency ui.draggable
is initialized before the code of the non AMD-aware plugin loads:
({
name: '../bower_components/almond/almond',
include: ['main'],
insertRequire: ['main'],
baseUrl: 'src',
optimize: 'uglify2',
mainConfigFile: 'src/main.js',
out: 'javascripts/scripts.js',
preserveLicenseComments: false,
paths: {
jquery: '../bower_components/jquery/dist/jquery',
underscore: '../bower_components/underscore/underscore',
backbone: '../bower_components/backbone/backbone',
kineticjs: '../bower_components/kineticjs/kineticjs',
'jquery-ui': '../bower_components/jquery-ui/ui',
'jquery.layout': '../bower_components/jquery.layout/dist/jquery.layout-latest'
},
shim: {
'jquery.layout': {
deps: ['jquery', 'jquery-ui/draggable', 'jquery-ui/effect', 'jquery-ui/effect-slide'],
exports: 'jQuery.fn.layout'
}
},
onBuildWrite: function(moduleName, path, contents) {
if (moduleName == 'jquery.layout') {
contents = "define('jquery.layout', ['jquery', 'jquery-ui/draggable', 'jquery-ui/effect', 'jquery-ui/effect-slide'], function(jQuery) {" + contents + "});";
}
return contents;
}
})