Can I load jQuery migrate via RequireJS? I don't understand how the timing can be handled correctly. See this example:
require([
'jquery',
'jqmigrate'
], function ($) {
if ($.browser.msie) {...}
});
Isn't is possible that jqmigrate will load before jquery? Also, I do not want to keep loading jqmigrate explicitly in every module. Any way to do this in the require.config so it loads jqmigrate automatically when jQuery is required?
There are a couple of things you will need:
make sure jqmigrate depends on jquery.
you could write a wrapper module that include both, and return jquery, so your require.config could look like:
jquery-wrapper.js:
define(['jquery-src', 'jqmigrate'], function ($) {
return $;
})
require.config
{
paths: {
'jquery-src' : '/path/to/jquery',
'jqmigrate': '/path/to/jqmigrate',
'jquery': '/path/to/jquery-wrapper'
}
}
using shims worked for me. I did get stuck because i had pluralized shims its; shim
requirejs.config({
paths: {
'jquery': '//code.jquery.com/jquery-2.1.4',
'jquery-migrate': '//code.jquery.com/jquery-migrate-1.2.1'
},
shim: {
'jquery-migrate': { deps: ['jquery'], exports: 'jQuery' },
'foo': ['jquery']
}
});
require(['jquery-migrate', './foo'], ($, foo) => {
console.log('bootstrapped', $, foo);
});
jQuery Migrate 3.0.1 currently has a defect that renders it unusable for RequireJS or any AMD loader. A change is required to the UMD fragment before implementing the accepted answer:
define( [ "jquery" ], function ($) {
return factory($, window);
});
Details and solution are here.
jquery-migrate-wrapper.js
define(['jquery', 'jquery-migrate'], function ($) {
// additional initialization logic can be added here
$.UNSAFE_restoreLegacyHtmlPrefilter();
return $;
})
require-config.js
require.config({
...otherConfigOptions,
shim: {
...otherShimSettings,
'jquery-migrate':{deps: ['jquery']},
},
map: {
// provides 'jquery-migrate-wrapper' for all (*) modules that require'jquery'
'*': { 'jquery': 'jquery-migrate-wrapper' },
// but provides the original 'jquery' for 'jquery-migrate-wrapper' and
// 'jquery-migrate'
'jquery-migrate-wrapper': { 'jquery': 'jquery' },
'jquery-migrate': {'jquery': 'jquery'}
}
})
Related
I am having a lot of trouble wrapping my head around requireJS dependancy management. I've read the docs and all online resources plenty of times but I can't seem to get it working correctly.
End scenario: I have an embeddable widget that eventually will attach a responsive iFrame to a page. The outer page is assumed to have some version of jQuery, but to be safe I am including my own jQuery.
I am using a library called responsiveIframe, which depends on jQuery.
Basically, when I call $('#responsive-frame').responsiveIframe({xdomain: '*'}); from inside the require function, I get an undefined function error. When I change $ to jQuery it works because it is able to use the existing library on the page (not what I want).
Here is the code (assume paths all work):
require.config({
baseUrl: 'http://localhost:4000/assets',
paths: {
'jquery': 'jquery-1.11.1.min',
'responsiveIframe': 'jquery.responsiveiframe'
},
map: {
'*': {'jquery': 'jquery-lc'},
'jquery-lc': {'jquery': 'jquery'}
}
});
require(['jquery', 'responsiveIframe'], function($) {
$('#responsive-frame').responsiveIframe({
xdomain: '*'
});
});
I've tried using various shims like so:
shim: {
responsiveIframe: {
init: function() {
return this.responsiveIframe
}
}
}
,
shim: {
'responsiveIframe': ['jquery']
}
,
shim: {
'responsiveIframe': {
'deps': 'jquery',
'exports': 'ResponsiveIframe'
'init': function() {
return this.responsiveIframe.noConflict()
}
}
I feel like I'm missing something fundamental about requireJS. Any help would be greatly appreciated, please let me know if you need more information :)
edit
Also, wrapping my responsiveiframe.js lib in this:
define(['responsiveIframe', 'jquery'], function(ri, jQuery) {
Seems to work... but this seems 'hacky'.
edit #2
I was able to get this to work by wrapping the responsiveIframe lib like this:
define(['jquery'], function(jQuery) {
//library code here
}
I was able to remove all shims:
require.config({
baseUrl: 'http://localhost:4000/assets',
paths: {
jquery: 'jquery-1.11.1.min',
responsiveIframe: 'jquery.responsiveiframe'
},
map: {
'*': {'jquery': 'jquery-lc'},
'jquery-lc': {'jquery': 'jquery'}
}
});
... and call like so:
require(['jquery','responsiveIframe'], function($) {
$('#responsive-frame').responsiveIframe({xdomain: '*'});
});
However, I am always a fan of doing things the 'right' way and modifying libraries rubs me the wrong way.
I feel like I should be able to use shim to properly apply this wrap code...
The last shim you tried was close, but the values of deps should be an array rather than a string. Try:
shim: {
'responsiveIframe': {
deps: ['jquery']
}
}
This is ensure jquery is loaded before the responseIframe script is loaded and run.
You should set shim like this:
shim: {
'responsiveIframe': {
deps: ['jquery'],
exports: '$'
}
}
And change your module definition to this
define(['responsiveIframe'], function($) {
$('#responsive-frame').responsiveIframe({xdomain: '*'});
}
That should do the trick
UPD.
If exports returns different jquery then you should modify shim to this:
shim: {
'responsiveIframe': {
deps: ['jquery'],
init: function(jquery) {
return jquery;
}
}
}
I'm using require.js and have a page with an from that used jquery.fileupload. After introducing the plugin I now see some files fail to be imported before the define call back is executed. This causes random errors where the libraries can't find their dependencies. It's as though require.js is moving on before all the dependencies can be resolved.
I've followed these instructions:
https://github.com/blueimp/jQuery-File-Upload/wiki/How-to-use-jQuery-File-Upload-with-RequireJS
But beyond that it's a very vanilla install. I'm using the minified versions of libraries where possible. Any insight is welcome.
here's the main.js:
(function () {
'use strict';
require.config({
baseUrl: '/js',
waitSeconds: 800,
paths: {
jquery: ['//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min',
'lib/jquery/jquery-2.0.3.min'],
'jquery.fileupload': 'lib/jquery.fileupload/jquery.fileupload',
'jquery.fileupload-ui': 'lib/jquery.fileupload/jquery.fileupload-ui',
'jquery.fileupload-image': 'lib/jquery.fileupload/jquery.fileupload-image',
'jquery.fileupload-validate': 'lib/jquery.fileupload/jquery.fileupload-validate',
'jquery.fileupload-video': 'lib/jquery.fileupload/jquery.fileupload-video',
'jquery.fileupload-audio': 'lib/jquery.fileupload/jquery.fileupload-audio',
'jquery.fileupload-process': 'lib/jquery.fileupload/jquery.fileupload-process',
'jquery.ui.widget': 'lib/jquery.ui/jquery.ui.widget',
'jquery.iframe-transport': 'lib/jquery.iframe-transport/jquery.iframe-transport',
'load-image': 'lib/load-image/load-image.min',
'load-image-meta': 'lib/load-image/load-image-meta',
'load-image-exif': 'lib/load-image/load-image-exif',
'load-image-ios': 'lib/load-image/load-image-ios',
'canvas-to-blob': 'lib/canvas-to-blob/canvas-to-blob.min',
tmpl: 'lib/tmpl/tmpl.min',
bootstrap: 'lib/bootstrap/bootstrap',
bootstrapTab: 'lib/bootstrap/bootstrap-tab',
EventEmitter: 'lib/event_emitter/EventEmitter',
linkedin: ['//platform.linkedin.com/in.js?async=true',
'http://platform.linkedin.com/in.js?async=true'],
skinny: 'lib/skinny/skinny',
selectize: 'lib/selectize/selectize.min',
sifter: 'lib/sifter/sifter',
microplugin: 'lib/microplugin/microplugin.min'
},
shim: {
bootstrap: {
deps: ['jquery'],
},
bootstrapTab: {
deps: ['jquery', 'bootstrap'],
},
linkedin: {
exports: 'IN'
},
selectize: {
deps: ['jquery', 'sifter', 'microplugin']
},
'jquery.iframe-transport': {
deps: ['jquery']
}
}
});
require(['app'], function (App) {
App.initialize();
});
}());
And the from code:
define([], function () {
'use strict';
return function () {
require(['jquery', 'tmpl', 'load-image', 'canvas-to-blob',
'jquery.iframe-transport', 'jquery.fileupload-ui'], function ($) {
$('#product').fileupload({
url: '/products/create'
});
});
};
});
The module gets called after the page has been loaded.
It's also worth noting that all files are downloaded successfully. No 404's, etc.
It turns out there is a flaw in the minified version of load-image.js that breaks how the dependencies load. I don't have exact proof as to why, it could be the smaller size causes a race condition, or it could be something weird in that particular file. What I do know is the minified version causes the random errors and the normal version does not (this is off master so I suppose I was taking a risk).
I raised a flag here
EDIT: it turns out the minified version of the plugin includes all the extensions which explains the odd dependency behavior.
The Answer from matt is the best solution in this case. Thanks a million, it save us a lot of time.
In requirejs.config, you have to add the load-image dependecies separatly - file by file.
For example:
require.config({
'jquery.ui.widget' : 'lib/jQuery-File-Upload-9.9.2/js/vendor/jquery.ui.widget',
'jquery.fileupload':'lib/jQuery-File-Upload-9.9.2/js/jquery.fileupload',
'jquery.fileupload-ui': 'lib/jQuery-File-Upload-9.9.2/js/jquery.fileupload-ui',
'jquery.fileupload-image': 'lib/jQuery-File-Upload-9.9.2/js/jquery.fileupload-image',
'jquery.fileupload-validate':'lib/jQuery-File-Upload-9.9.2/js/jquery.fileupload-validate',
'jquery.fileupload-audio':'lib/jQuery-File-Upload-9.9.2/js/jquery.fileupload-audio',
'jquery.fileupload-video':'lib/jQuery-File-Upload-9.9.2/js/jquery.fileupload-video',
'jquery.fileupload-process': 'lib/jQuery-File-Upload-9.9.2/js/jquery.fileupload-process',
'jquery.fileupload-jquery-ui': 'lib/jQuery-File-Upload-9.9.2/js/jquery.fileupload-jquery-ui',
'jquery.iframe-transport': 'lib/jQuery-File-Upload-9.9.2/js/jquery.iframe-transport',
'load-image':'lib/load-image-1.10.0',
'load-image-meta':'lib/load-image-meta-1.10.0',
'load-image-ios':'lib/load-image-ios-1.10.0',
'load-image-exif':'lib/load-image-exif-1.10.0',
'canvas-to-blob':'lib/canvas-to-blob-2.0.5',
'tmpl':'lib/tmpl.2.4.1'
}
});
call in html site:
requirejs(['jquery',
'jquery.ui.widget',
'tmpl',
'load-image',
'jquery.iframe-transport',
'jquery.fileupload-ui'], function () {
$('#fileupload').fileupload({
url: 'photo-upload.html'
});
}
);
One possibility modify the shim:
shim: {
bootstrap: {
deps: ['jquery'],
},
bootstrapTab: {
deps: ['jquery', 'bootstrap'],
},
linkedin: {
exports: 'IN'
},
selectize: {
deps: ['jquery', 'sifter', 'microplugin']
},
'jquery.iframe-transport': {
deps: ['jquery']
},
'jquery.fileupload-ui':{
deps: ['jquery']
}
Another option downgrade jquery to 1.X (this is because the sample page is using jquery 1.X)
This is what my config.js file looks like:
require.config({
baseUrl: '../',
paths: {
jQuery: 'js/jquery-1.10.2.min',
uiEffectsCore: 'js/jQueryUIEffectsCore',
//Handlebars: 'js/handlebars',
SyntaxHighlighter: 'js/syntaxhighlighter/scripts/shCore',
shXml: 'js/syntaxhighlighter/scripts/shBrushXml'
},
shim: {
jQuery: {
exports: 'jQuery'
},
uiEffectsCore: {
deps: ['jQuery']
},
shXml: {
deps: ['SyntaxHighlighter']
}
}
});
require(['js/main']);
Then my main.js looks like this:
define(function(require){
require('jQuery');
require('uiEffectsCore');
require('SyntaxHighlighter');
require('shXml');
});
I think the problem is that there is no define(...) wrapper around my shXml file... I am wondering if I can make this work without having to use that wrapper. Maybe an export shim would do it.
As it stands now, i get this error every time.
This question has also been asked here on github.
Check out this article, also from github. I tested this, and it works great, but you have to replace the first line of your brush.js files (inside syntaxhighlighter) with this line here:
SyntaxHighlighter = SyntaxHighlighter || (typeof require !== 'undefined'? require('shCore').SyntaxHighlighter : null);
I don't even know why that fixes the issue, but it does, and you can load your scripts like this:
define(function(require){
require('jQuery');
require('uiEffectsCore');
require('SyntaxHighlighter');
require('shXml');
require('shCss');
require('shJs');
require('Raphael');
And you need a shim in your config for dependencies:
paths: {
SyntaxHighlighter: 'js/syntaxhighlighter/scripts/shCore',
shXml: 'js/syntaxhighlighter/scripts/shBrushXml',
shCss: 'js/syntaxhighlighter/scripts/shBrushCss',
shJs: 'js/syntaxhighlighter/scripts/shBrushJScript'
},
shim: {
shXml: {
deps: ['SyntaxHighlighter']
},
shCss: {
deps: ['SyntaxHighlighter']
},
shJs: {
deps: ['SyntaxHighlighter']
}
}
I'm trying to use both Underscore and Underscore.string with RequireJS.
Contents of main.js:
require.config({
paths: {
'underscore': '//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min',
'underscore-string': '//cdnjs.cloudflare.com/ajax/libs/underscore.string/2.3.0/underscore.string.min',
},
shim: {
'underscore': {
exports: '_'
},
'underscore-string': {
deps: ['underscore'],
exports: '_s'
},
}
});
var modules = ['underscore-string'];
require(modules, function() {
// --
});
Browser sees the _, but doesn't see the _s - it is undefined.
Ideally i want to have Underscore under _ and Underscore.string under _.str, but _ and _s are fine too. How can i do that?
Versions: RequireJS 2.1.5, Underscore 1.4.4, Underscore.string 2.3.0
Note: Thanks to #jgillich make sure, that paths have two slashes (//cdnjs.cloudfare.com/...), otherwise the browser would think that URL is relative to the server, and Firebug will throw:
Error: Script error
http://requirejs.org/docs/errors.html#scripterror
I found the error. For some reason RequireJS doesn't work with version of Underscore.string from cdnjs.com, so i replaced it with Github version. I guess it has something to do with the commit 9df4736.
Currently my code looks like the following:
require.config({
paths: {
'underscore': '//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min',
'underscore-string': '//raw.github.com/epeli/underscore.string/master/dist/underscore.string.min',
},
shim: {
'underscore': {
exports: '_'
},
'underscore-string': {
deps: ['underscore'],
},
}
});
var modules = ['underscore', 'underscore-string'];
require(modules, function(_) {
// --
});
Underscore.string resides in _.str.
Edit: As of 16 July 2013 the CDNJS version is updated with the upstream.
Battling with this for hours before i understand what i was doing wrong
This is what i did wrong
You should not rename the file underscore.string in main.js
even though in my library i did rename the file in paths i name it back to 'underscore.string'
This is how your main.js should look like
require.config({
paths: {
underscore: 'lib/underscore',
'underscore.string' : 'lib/_string' ,
},
shim: {
underscore: {
exports: '_',
deps: [ 'jquery', 'jqueryui' ]
},
'underscore.string': {
deps: [ 'underscore' ]
},
}
....
You could then either add it as dependency with in your shim like i did for my mixin file
shim: {
mixin : {
deps: [ 'jquery', 'underscore', 'underscore.string' , 'bootstrap' ]
},
Or just define it in your different pages like
/*global define */
define([
'underscore.string'
], function ( ) {
it just work now you can access it through _.str or _.string
This is why you should do it this way and not try to name it something else
on line 663 of underscore.string.js
// Register as a named module with AMD.
if (typeof define === 'function' && define.amd)
define('underscore.string', [], function(){ return _s; });
Which means that it will only register it with AMD require JS if you are defining 'underscore.string'
works for my ONLY if I use exact "underscore.string" module name in shim. Seems related to hardcoded name in underscore.string itself
Exempt from underscore.string source code (this branch is executed when require used):
// Register as a named module with AMD.
if (typeof define === 'function' && define.amd)
define('underscore.string', [], function(){ return _s; });
So for me the only working configuration is:
require.config({
paths: {
'underscore': '//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min',
'underscore.string': '//raw.github.com/epeli/underscore.string/master/dist/underscore.string.min',
},
shim: {
'underscore': {
exports: '_'
},
'underscore.string': {
deps: ['underscore'],
},
}
});
var modules = ['underscore', 'underscore.string'];
require(modules, function(_) {
// --
});
Here's a working code using Requirejs "order" plugin, also includes Jquery, and everything loads without any conflict:
requirejs.config({
baseUrl: "assets",
paths: {
order: '//requirejs.org/docs/release/1.0.5/minified/order',
jquery: 'http://code.jquery.com/jquery-2.1.0.min',
underscore: '//underscorejs.org/underscore-min',
underscorestring: '//raw.githubusercontent.com/epeli/underscore.string/master/dist/underscore.string.min',
underscoremixed: 'js/underscore.mixed' // Create separate file
},
shim: {
underscore: { exports: '_' },
underscorestring: { deps: ['underscore'] }
}
});
require(['order!jquery','order!underscoremixed'], function($,_) {
// test
console.log( _.capitalize('capitalized text') );
});
Inside js/underscore.mixed.js put the following...
define(['underscore','underscorestring'], function() {
_.mixin(_.str.exports());
return _;
});
Cheers! :)
I have my bootstrap file which defines the require.js paths, and loads the app and config modules.
// Filename: bootstrap
// Require.js allows us to configure shortcut alias
// There usage will become more apparent futher along in the tutorial.
require.config({
paths: {
bfwd: 'com/bfwd',
plugins: 'jquery/plugins',
ui: 'jquery/ui',
jquery: 'jquery/jquery.min',
'jquery-ui': 'jquery/jquery-ui.min',
backbone: 'core/backbone.min',
underscore: 'core/underscore.min'
}
});
console.log('loading bootstrap');
require([
// Load our app module and pass it to our definition function
'app',
'config'
], function(App){
// The "app" dependency is passed in as "App"
// Again, the other dependencies passed in are not "AMD" therefore don't pass a parameter to this function
console.log('initializing app');
App.initialize();
});
app.js is loaded like it should, and it's dependencies are loaded. it's define callback is called, with all the correct dependencies passed as arguments. No error is thrown. HOWEVER, in the bootstrap's callback, App is undefined! no arguments are passed. What can be causing this? Here's my app file ( modified for space)
// Filename: app.js
define(
'app',
[
'jquery',
'underscore',
'backbone',
'jquery-ui',
'bfwd/core',
'plugins/jquery.VistaProgressBar-0.6'
],
function($, _, Backbone){
var initialize = function()
{
//initialize code here
}
return
{
initialize: initialize
};
}
);
As far as I am aware you should probably just drop the 'app' string in your app.js define method.
// Filename: app.js
define([
'jquery',
'underscore',
'backbone',
'jquery-ui',
'bfwd/core',
'plugins/jquery.VistaProgressBar-0.6'
], function($, _, Backbone){
...
);
Ok I had the same problem, the key is the jquery path alias you define. It turns out that RequireJS has some special handling for jquery. If you use the jquery module name it will do a little bit of magic there.
Depending on what you have in jquery.min.js it may cause some problems, also the jquery plugin you have there may be a problem. Here are the relevant lines of code from the RequireJS source:
if (fullName) {
//If module already defined for context, or already loaded,
//then leave. Also leave if jQuery is registering but it does
//not match the desired version number in the config.
if (fullName in defined || loaded[id] === true ||
(fullName === "jquery" && config.jQuery &&
config.jQuery !== callback().fn.jquery)) {
return;
}
//Set specified/loaded here for modules that are also loaded
//as part of a layer, where onScriptLoad is not fired
//for those cases. Do this after the inline define and
//dependency tracing is done.
specified[id] = true;
loaded[id] = true;
//If module is jQuery set up delaying its dom ready listeners.
if (fullName === "jquery" && callback) {
jQueryCheck(callback());
}
}
For me I have it setup such that I have a file called /libs/jquery/jquery.js which returns the jquery object (just a wrapper for RequireJS). What I ended up doing was simply changing the path alias from jquery to $jquery. This helps avoid the undesired magic behavior.
In the original tutorial I read they use jQuery which also works.
This is a simple example that might help get you started:
I've created a very simple module:
https://gist.github.com/c556b6c759b1a41dd99d
define([], function () {
function my_alert (msg) {
alert(msg);
}
return {
"alert": my_alert
};
});
And used it in this fiddle, with only jQuery as an extra dependency:
http://jsfiddle.net/NjTgm/
<script src="http://requirejs.org/docs/release/1.0.7/minified/require.js"></script>
<script type="text/javascript">
require.config({
paths: {
"jquery": "https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min",
"app": "https://gist.github.com/raw/c556b6c759b1a41dd99d/20d0084c9e767835446b46072536103bd5aa8c6b/gistfile1.js"
},
waitSeconds: 40
});
</script>
<div id="message">hello</div>
<script type="text/javascript">
require( ["jquery", "app"],
function ($, app) {
alert($.fn.jquery + "\n" + $("#message").text());
app.alert("hello from app");
}
);
</script>
This is how I do it with requirejs and backbone:
first, define main or bootstrap file with config:
// bootstrap.js
require.config({
paths: {
text: 'lib/text',
jQuery: 'lib/jquery-1.7.2.min',
jqueryui: 'lib/jquery-ui-1.8.22.custom.min',
Underscore: 'lib/underscore-1.3.3',
Backbone: 'lib/backbone-0.9.2'
},
shim: {
'Underscore': {
exports: '_'
},
'jQuery': {
exports: 'jQuery'
},
'jqueryui': {
exports: 'jqueryui'
},
'Zepto': {
exports: '$'
},
'Backbone': {
deps: ['Underscore', 'Zepto'],
exports: 'Backbone'
}
});
define(function (require) {
'use strict';
var RootView = require('src/RootView');
new RootView();
});
Then, I use this syntax to load my scripts. I find it easier than the array notation to just define my depencies via var declarations.
// rootview.js
define(function (require) {
'use strict';
var $ = require('Zepto'),
Backbone = require('Backbone'),
LoginView = require('./LoginView'),
ApplicationView = require('./ApplicationView'),
jQuery = require('jQuery').noConflict();
return Backbone.View.extend({
// append the view to the already created container
el: $('.application-container'),
initialize: function () {
/* .... */
},
render: function () {
/* .... */
}
});
});
Hope it helps!
This is a bit late, but I just had this problem. My solution can be found here:
https://stackoverflow.com/questions/27644844/can-a-return-statement-be-broken-across-multiple-lines-in-javascript
I posted that question for a different reason, to ask why my fix worked in the first place. Elclanrs provided the perfect answer. To make a long story short, the undefined is probably appearing due to javascript's automatic semicolon insertion: Automatic semicolon insertion & return statements
If you try changing the position of the curly bracket from underneath to directly after the return statement, I think your problem will disappear.
// Filename: app.js
define(
.
.
.
function($, _, Backbone){
var initialize = function()
{
//initialize code here
}
return {
initialize: initialize
};
}
);