I am using require.js to load my js files and I am attempting to load mediaelementplayer but I am receiving two errors. mejs is not defined and object has no method. Is there a way I can delay this file to load even though jQuery is loading first and media element has jQuery as a dependency? I have tried to put it in the jquery load function but that didn't change anything.
The MediaElementPlayer as written has a dependency on jquery, hence shim accordingly (i.e jquery before mes!!)
requirejs.config({
"paths": {
"jquery" : "libs/jquery/jquery-1.10.2.min",
"mes" : "libs/mes/mediaelement-and-player.min"
},
shim: {
'jquery': {
exports: '$'
},
'mes' : ['jquery']
}
});
Then
require(["jquery","mes"], function($){
$('video').mediaelementplayer({});
});
Hope it helps some one else searching for this. If you are working on IE6-9 you probably need html5shiv
Related
I'm trying to get a jQuery plugin working properly with RequireJS, when using jQuery in the noconflict/noglobal state to force all modules to indicate whether they require jQuery. However, for non-AMD-friendly plugins, the shim config seems to not be working. Namely, if a jQuery plugin is defined with a wrapper like:
(function($) {
$.extend($.myPlugin, { myPlugin: { version:'0.0.1'} });
})(jQuery);
Then the following RequireJS configuration isn't working:
requirejs.config({
paths: {
jquery: ['//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min', 'jquery-min'],
},
map: {
'*': { 'jquery': 'jquery-noglobal' }, // Force all modules to use the non-global jQuery...
'jquery-noglobal': { 'jquery': 'jquery' } // ...except the wrapper module itself, which needs the real one.
},
shim: {
'sadPlugin': {
deps: ['jquery']
}
}
});
jquery-noglobal.js:
define(['jquery'], function(jq) {
return jq.noConflict( true );
});
The error that fires when the plugin code runs is: "can't call extend on undefined", meaning jQuery was never set at the outer level, so $ is undefined inside the self-executing function. I put breakpoints outside the plugin self-executing function, and inside to verify that.
I'm guessing part of the problem is capitalization; the module was written to expect jQuery (camelCase), while the AMD module name is jquery (lower case). Is there any way in the shim config to specify what the injected requirements' variable names should be?
I've also tried adding a sadPlugin: {'jquery':'jquery'} entry to the map hash, hoping to make shim give that module the global jQuery instead of the non-global one, but still jQuery/$ aren't defined by the time the function gets called.
EDIT: Found one kludge that does answer part of the problem: according to the comment found here, the deps of a shim need to be the full file path of the script to load, and cannot be an alias from the paths configuration.
So, since my CDN-fallback file of jQuery is jquery-min.js, if I do:
shim: {
'sadPlugin': {
deps: ['jquery-min']
}
}
The plugin works! However, since the "real" jQuery is now being used, it pollutes the global namespace, and the $ variable is then available without require()ing it, so defeats the whole purpose of the noglobal wrapper...
Just use
return jQuery.noConflict( true );
instead of
return jq.noConflict( true );
So, as local variable inside requirejs, your plugins can use the variable jQuery for the parameter $
(function($) {$.extend($.myPlugin, { myPlugin: { version:'0.0.1'} });})(jQuery);
The config that work for me is:
-- main.js
-- jquery-private.js
In main.js file:
require.config({
paths: {
},
map: {
'*': { 'jquery': 'jquery-private' },
'jquery-private': { 'jquery': '//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js' }
},
shim: {
myplugins: ['jquery']
}
});
In jquery-private.js file:
define(['jquery'], function () {
jQuery = $.noConflict(true);
return jQuery;
});
I'm trying to use Bootstrap with RequireJS, setting RequireJS' config like this:
js/
bootstrap.min.js
app.js
require.js
scripts.js
This is the app.js file:
requirejs.config({
"shim": {
"bootstrap": {deps : 'jquery' }
},
"paths": {
"jquery": "//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min",
"bootstrap" : "bootstrap.min"
},
enforceDefine : true
});
// Load the main app module to start the app
requirejs(["scripts"]);
This is the scripts.js file:
define(["jquery", "bootstrap"], function($) {
console.log(jQuery);
$('#video').click(function () {
var src = 'http://www.youtube.com/v/FSi2fJALDyQ&autoplay=1';
$('#myModal').modal('show');
$('#myModal iframe').attr('src', src);
});
$('#myModal button').click(function () {
$('#myModal iframe').removeAttr('src');
});
});
This doesn't work and on the console says Bootstrap needs jQuery to work. The weird thing is if I change Bootstrap's path to load it from a CDN, it works.
Your shim for Bootstrap should use an array to specify dependencies:
shim: {
"bootstrap": {
deps : ['jquery'] // Use an array even with a single dependency.
}
}
The way it is now RequireJS does not get the dependency you specify. (It might interpret the string as an array and look for modules j, q, etc. I'm not sure about this...) So it loads Bootstrap irrespective of whether jQuery is loaded.
It works when you use a CDN probably because of a timing difference: it takes long enough to fetch from the CND that jQuery is loaded before Bootstrap loads. When you do it locally, Boostrap loads too fast and jQuery is not loaded yet. At any rate, using the array as I show above should solve the problem.
thanks for your help, When I downloaded RequireJS i never realized what version I was using.
I thought I had the latest but I was using 1.0.8, I upgraded and now I have 2.1.14, that solved the problem.
There's no need of using an export on the shim object as many entries say
shim: {
"bootstrap": {
deps : ['jquery'], // Use an array even with a single dependency.
export : '$.fn.modal'
}
}
Thanks for your help :D
I have an add-on to an application (call it appX) that allows users to create their own customizations using javascript, css and appX's webservices api.
Usually customizations are small and do not involve a lot of external libraries/plugins but when they do have external libs the typical users' library of choice is jQuery.
In the next version of appX they are using jQuery natively which I know is going to break some of the customizations.
So I have a need to modularize this situation. I have some other problems that are coming up and RequireJS seems like a good solution to these issues. I just need to figure out how to apply RequireJS properly for this situation
In my POC I'm loading require.js as follows:
<!--A bunch of other script including jQuery (but not require) are loaded already -->
<script type="text/javascript" src="/custom/js/require.js"></script>
<script type="text/javascript" src="/custom/js/dostuff.js"></script>
We'll call the jQuery loaded with appX jqueryx and the one I want to load jqueryp (p for private)
jQuery utilizes AMD and by default uses this definition internally:
define( "jquery", [], function () { return jQuery; } );
But in this case RequireJS is loaded AFTER jQuery (jqueryx) so there will be no default 'jquery' definition correct?
Some more background before I show you my problem... the file structure is like this:
appx
/js:
jqueryx.js
other.js
appx
/custom/js:
jqueryp.js
dostuff.js
Looking at the RequireJS api it seems that I should be doing something like this:
require.config({
baseUrl : 'custom/js',
paths : { 'jquery' : 'jqueryp'},
map: {
'*': { 'jquery': 'jquery-private' },
'jquery-private': { 'jquery': 'jquery' }
}
});
define(['jquery'], function (jq) {
return jq.noConflict( true );
});
require(['jquery'], function(jq){
console.log(jq.fn.jquery);
});
But when I do this I get an error:
Mismatched anonymous define() module: function (jq)...
I've played around with switching references to jquery, jquery-private as it's kind of confusing but with no progress.
How should I be applying RequireJS to this situation?
Almost a year late but better than no answer at all...
The following part should be moved into a "jquery-private.js" file:
define(['jquery'], function (jq) {
return jq.noConflict( true );
});
You can't define a module in your main entry point. Even if you could, the module has no name so how would you reference it?
I'm attempting to load the Highcharts library using a shim in RequireJS. However, when Highcharts loads, it throws an exception because it can't access the jQuery methods it depends on.
The require config looks like so:
require.config({
baseUrl: "js",
shim: {
'libs/highcharts/highcharts.src.js': {
deps: ['jquery'],
exports: function(jQuery)
{
this.HighchartsAdapter = jQuery;
return this.Highcharts;
}
}
}
});
The exception that is thrown is:
Uncaught TypeError: undefined is not a function
and is in regards to this line:
dataLabels: merge(defaultLabelOptions, {
The issue is the merge call, which eventually maps itself back to jQuery (or some other adapter that Highcharts supports; but I'm just using jQuery).
I'm not sure exactly how to make sure Highcharts gets access to jQuery using RequireJS and shim.
Has anyone used RequireJS and Highcharts together before? I guess the issue isn't specific to highcharts, but any library that has other sorts of dependencies.
Thanks in advance for any advice or points to the correct direction!
To add further context, in hopes that someone who is familiar with require.js or shims will be able to help without having to be too intimately familiar with highcharts, here's some source that sets up this merge method in Highcharts
var globalAdapter = win.HighchartsAdapter,
adapter = globalAdapter || {},
// Utility functions. If the HighchartsAdapter is not defined,
// adapter is an empty object
// and all the utility functions will be null. In that case they are
// populated by the
// default adapters below.
// {snipped code}
merge = adapter.merge
// {snipped code}
if (!globalAdapter && win.jQuery) {
var jQ = win.jQuery;
// {snipped code}
merge = function () {
var args = arguments;
return jQ.extend(true, null, args[0], args[1], args[2], args[3]);
};
// {snipped code}
}
The win object is a reference set up to window at the beginning of the script. So, I thought adding window.jQuery = jQuery; to the export method on the shim would result in highcharts picking up the jQuery reference; but it didn't.
Again, any insight, info, advice, or heckles would be appreciated at this point - I'm at a complete loss, and starting to question whether trying to implement and AMD package system in browser javascript is even worth it.
After accepting the answer from pabera below I thought it appropriate to update my question to reflect how his answer helped my solution (though, it's basically his answer).
RequireJS uses "paths" to find libs that aren't "AMD" supported and loads them on your page. the "shim" object allows you to define dependencies for the libraries defined in paths. The dependencies must be loaded before requirejs will try to load the dependent script.
The exports property provides a mechanism to tell requirejs how to determine if the library is loaded. For core libs like jquery, backbone, socketio, etc they all export some window level variable (Backbone, io, jQuery and $, etc). You simply provide that variable name as the exports property, and requirejs will be able to determine when the lib is loaded.
Once your definitions are done, you can use requirejs' define function as expected.
Here's my example require.config object:
require.config({
baseUrl: "/js/",
paths: {
jquery: 'jquery',
socketio: 'http://localhost:8000/socket.io/socket.io', //for loading the socket.io client library
highcharts: 'libs/highcharts/highcharts.src',
underscore: 'libs/underscore',
backbone: 'libs/backbone'
},
shim: {
jquery: {
exports: 'jQuery'
},
socketio: {
exports: 'io'
},
underscore: {
exports: '_'
},
backbone: {
deps: ['jquery', 'underscore'],
exports: 'Backbone'
},
highcharts: {
deps: ['jquery'],
exports: 'Highcharts'
}
}
});
As pabera mentioned before, this is for Require.JS version 2.0.1.
I hope someone gets some use out of this; I know it road blocked me for a little while; so hopefully we kept you from banging your head into the same spot in the wall that we did, by posting this.
I had the exact same problem and I was struggling around many hours until I saw your entry here. Then I started over from scratch and now it works for me at least.
requirejs.config({
baseUrl:'/js/',
paths:{
jquery:'vendor/jquery',
handlebars: 'vendor/handlebars',
text: 'vendor/require-text',
chaplin:'vendor/chaplin',
underscore:'vendor/underscore',
backbone:'vendor/backbone',
highcharts: 'vendor/highcharts'
},
shim: {
backbone: {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
underscore: {
exports: '_'
},
highcharts: {
exports: 'Highcharts'
}
},
});
Since I use Chaplin on top of Backbone, I am including some more files in my paths attribute. Highcharts has a similar structure to Backbone so I thought I could load it the same way. It works for me now. As you can see, I am introducing highcharts in the paths attribute already to export it as a shim afterwords.
Maybe this helps, otherwise let's try to contribute on it even more to solve your problem.
Although jQuery can be used as an AMD module it will still export itself to the window anyway so any scripts depending on the global jQuery or $ will still work as long as jQuery has loaded first.
Have you tried setting a path? jQuery is an interesting one because although you're encoruaged not to name your modules by the RequireJS documentation, jQuery actually does.
From the jQuery source
if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
define( "jquery", [], function () { return jQuery; } );
}
What that means is you will need to tell RequireJS where to find 'jquery'. So:
require.config({
paths: {
'jquery': 'path/to/jquery'
}
});
If you're interested in why jQuery registers itself this way then there is a pretty large comment in the source which goes into more detail
So this is the setup, my base file is main.js which defines the scripts that are needed on all pages of the site I'm building. It looks like this:
define([
'/javascript/requirePlugins/require-order.js!http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js',
'/javascript/requirePlugins/require-order.js!/javascript/jquery-global-plugins.js',
'/javascript/requirePlugins/require-order.js!/javascript/globals.js'
], function () {
loadFonts();
}
);
It loads jQuery, some plugins and the globals script file. On one page I'm trying to load a jQuery plugin, but the plugin tries to load before jQuery is loaded. It looks like this:
require(['/javascript/requirePlugins/require-order.js!/main','/javascript/requirePlugins/require-order.js!/javascript/3rdparty/lemon-slider-0.2.js'], function () {
$j('#carousel<%= ClientID %>').lemmonSlider({loop:false});
});
The function doesn't appear to be following the order requested. I'm not sure I can even nest ordered functions like this. I've also tried just applying jQuery as a dependency, but this also fails:
require(['/javascript/requirePlugins/require-order.js!/jquery','/javascript/requirePlugins/require-order.js!/javascript/3rdparty/lemon-slider-0.2.js'], function () {
$j('#carousel<%= ClientID %>').lemmonSlider({loop:false});
});
Any suggestions to where I'm doing this wrong is appreciated, thanks
order plugin is removed and you may try shim config to load plugins in order
requirejs.config({
paths: {
'jquery': 'https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min',
'bootstrap': '../bootstrap/js/bootstrap.min',
'select2': 'vendor/select2',
'jshashtable': 'vendor/jshashtable-2.1',
'jquery.numberformatter': 'vendor/jquery.numberformatter-1.2.3.min',
'jq-datepicker': 'vendor/bootstrap-datepicker',
'jq-datepicker.da': 'vendor/bootstrap-datepicker.da'
},
// Use shim for plugins that does not support ADM
shim: {
'bootstrap': ['jquery'],
'select2': ['jquery'],
'jq-datepicker': ['jquery'],
'jshashtable': ['jquery'],
'jquery.numberformatter': ['jquery', 'jshashtable']
},
enforceDefine: true
});
EDIT:
require-jquery is also no more maintaining.
The order plugin is useful if you just have a few top-level scripts you wanted loaded in order and those scripts do not use the module API supported by requirejs. It does not work out so well if you mix it/use it to load modules that do use the define() module API.
In particular, order just makes sure the script gets loaded first. However, the define() API specifies other scripts to load, and the order plugin does not know to wait for those scripts to load.
For this particular problem, I suggest using require-jquery.js as sinsedrix suggested. That, or wrap the scripts you use in define() calls. volo can help you do this with its amdify command:
volo.js amdify path/to/lemon-slider-0.2.js depends=jquery
Also, I would set the baseUrl and use "module naming" for the dependencies instead of full paths. This will allow the optimizer to work correctly. You can also map 'order' to the requirePlugins path, which helps cut down some of the line noise. I would also create a 'jquery' paths entry so that if you do wrap the other plugins in define calls, it will map back to the jquery loaded in your main.js file. So, in the top level script for your page:
requirejs.config({
baseUrl: '/javascript/',
paths: {
order: 'requirePlugins/require-order',
jquery: 'http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min'
}
});
Then your main.js can be written like so:
define([
'order!jquery',
'order!jquery-global-plugins',
'order!globals'
], function () {
loadFonts();
}
);
Note that here, the order usage is fine, as long as those dependencies do not call define() themselves.
But if you are wrapping the scripts you use in define calls, then you can get rid of the order! usage above. Keep the jquery paths config though.
Maybe you should try tu use the require-jquery : http://requirejs.org/docs/jquery.html
Then you won't have to worry about when jquery is loaded.