So I'm working with jquery.flot and jquery.flot.selection and since define({... loads modules asynchronously I am having a problem because the selection plugin is trying to push itself into $.plot.plugins (which is created by jquery.flot) but at that moment $.plot.plugins still isn't defined.
I found that the "shim" argument in require.config should help me with this but I am having no luck...
so here's the rundown...
jquery.flot creates $.plot
and jquery.flot.selection adds itself to $.plot.plugins
what I've tried...
shim:{
'js/lib/jquery.flot':{
exports:'$.plot'
},
'js/lib/jquery.flot.selection':{
deps:['js/lib/jquery.flot']
}
}
also
shim:{
'js/lib/jquery.flot.selection':['js/lib/jquery.flot']
}
my plugin looks like this..
define(['jquery','lib/jquery.flot','lib/jquery.flot.selection'], function() {
(function($) {
// jQuery plugin definition
.....
I also tried
define(['jquery'],function(){
require[('js/lib/jquery.flot.selection'],function(){
//jQuery plugin definition
...
What should I do???
For anyone who happens to run into this in the future, RequireJS can be a little opaque when it comes to diagnosing problems. Here's a working example of RequireJS 2 with jquery.flot and jquery.flot.selection, without the use module.
It's a little hard to tell what's different between this example and the question above, thus the opaqueness!
require.config({
shim: {
'jquery': {
exports: '$'
},
'jquery.flot': {
deps: ['jquery'],
exports: '$.plot'
},
'jquery.flot.selection': {
deps: ['jquery.flot']
}
},
paths: {
'jquery': '//cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min',
'jquery.flot': '//cdnjs.cloudflare.com/ajax/libs/flot/0.8.1/jquery.flot.min',
'jquery.flot.selection': 'https://raw.github.com/flot/flot/master/jquery.flot.selection'
}
});
require(['jquery', 'jquery.flot', 'jquery.flot.selection'], function ($) {
// jQuery plugin definition
console.log($.plot);
$('#x').text($.plot.plugins);
});
Related
I'm trying to load textext.js jquery plugin, with one of it's plugins, textext tags. On my project, I'm using require.js in order to load all scripts with it's dependencies.
As used for other scripts, I'm using a shim config on my main.js file:
main.js
require.config({
shin: {
jquery: {
exports: '$'
},
'textext': {
deps: ['jquery'],
exports: '$.fn.textext'
},
'textext_tags': {
deps: ['jquery', 'textext'],
}
},
paths: {
jquery: 'lib/jquery-min',
textext: 'lib/textext/textext.core',
textext_tags: 'lib/textext/textext.plugin.tags',
}
});
On the page that I use it, I call it as above:
file-app.js
define([
'jquery',
'textext',
'textext_tags',
], function($, Textext, TextextTags) {
// do stuff
});
The code is loading and working correctly on firefox, but on Chromium, sometimes (about 2/3 of the times), at the first time that I load the page, I've receive the following error, that broke the functioning of the page:
TypeError: Cannot set property 'TextExtTags' of undefined
#3 localhost/js/lib/textext/textext.plugin.tags.js:23:27
Inside the file textext.plugins.tags.js, we have at line 23 (the failure line):
$.fn.textext.TextExtTags = TextExtTags;
So, inspecting it with Firebug, I realize that Jquery is not loaded, so $ and $.fn is undefined.
My question is: why this schema of require.js is working with other jQuery plugins on the same project (like jquery cookie and others), but not with this, a jquery plugin with it's subplugins?
As Vishwanath said, only changing from "shin" to "shim" worked, like above:
require.config({
shim: {
jquery: {
exports: '$'
},
...
Thanks!
I'm creating a web application using Backbone.js and Handlebars.js (with Underscore.js and jQuery as dependencies for Backbone). I'm loading modules for the app with requirejs.
Following the instructions here:
http://requirejs.org/docs/jquery.html#noconflictmap
and here:
http://requirejs.org/docs/api.html#config
So my requirejs config looks like:
map: {
'*' : { 'jquery': 'jquery-private' },
'jquery-private': { 'jquery': 'jquery' }
},
shim: {
'underscore' : {
exports: '_',
init: function() { return this._.noConflict(); }
},
'backbone' : {
deps: ['underscore', 'jquery'],
exports: 'Backbone',
init: function(_, $) {
// need to manually set Backbone.$ since it looks for it on the global object
this.Backbone.$ = $;
return this.Backbone.noConflict();
}
},
'handlebars' : { exports: 'Handlebars' }
}
I'm loading local copies of my dependencies by calling noConflict() on backbone, underscore, and jquery. However, Handlebars does not have a noConflict method; if I attempt to configure the shim for it in the same way as backbone & underscore, I get an error:
Uncaught TypeError: Object #<c> has no method 'noConflict'
No real surprise there, but then I'm concerned about conflicts! Is there a workaround? Can I somehow manually achieve the same goal by writing my own version of the noConflict for Handlebars? What would that look like?
As I understand, purpose of noConflict is to release some namespace (or, in other words, global variable). I think, you could accomplish it in following way:
Add to Handlebars some fake dependency (it may be simple AMD module,
written by yourself)
in Handlebars shim config, use init option in following way:
handlebars : {
deps: ['myFakeModule'],
init: function(myFakeModule) {
myFakeModule.Handlebars = this.Handlebars;
this.Handlebars = undefined;
return myFakeModule.Handlebars;
}
}
This is a theory and a bit hacky, but it might do the trick.
I've written a full web app and I bootstrap it with require in this line at the end of my HTML document:
<script src="js/vendor/require-2.1.6.min.js" data-main="js/main.js"></script>
Inside main.js, I declare my app using the following two functions:
requirejs.config({
paths: {
'jquery': 'vendor/jquery-1.9.1.min',
'lodash': 'vendor/lodash-1.3.1.min',
'knockout': 'vendor/knockout-2.2.1.min',
'bootstrap': 'vendor/bootstrap-2.3.2.min'
},
shim: { 'bootstrap': { deps: ['jquery'] } }
});
requirejs(dependencies, function main(dependencies) { ... });
Now, I want to port my app as a jQuery plugin. As such, the end result I desire is to wrap my app in a jQuery fn,
(function($) { $.fn.myPlugin = function() { ... }; }(jQuery));
modularize the code to compile into a single js file (plugin-1.0.0.min.js), include the code in another project, with or without AMD, and load my app into a div using
$('#pluginDiv').myPlugin({ options: {} });
First, do I need to change the requirejs/requirejs.config functions to declares in order to package my app as a modular component? Or do I simply leave my app like this? What about the config?
Next, how do I expose my plugin to the jQuery which the plugin user will be using, e.g. the one declared in the global scope? Will this work if they're using an AMD?
UPDATE
For question 1, I moved my requirejs.config to a build file, build.js, which requires some additional properties:
({
baseUrl: ".",
paths: {
'jquery': 'vendor/jquery-1.9.1.min',
'lodash': 'vendor/lodash-1.3.1.min',
'knockout': 'vendor/knockout-2.2.1.min',
'bootstrap': 'vendor/bootstrap-2.3.2.min'
},
shim: { 'bootstrap': { deps: ['jquery'] } },
optimize: "none", // for debug
name: "main",
out: "plugin.js"
})
I was able to use r.js to compile this and it works great.
I am still stuck on question two, however. The code in my compiled myPlugin.js is as follows:
requirejs(dependencies, function main(dependencies) {
(function($) {
$.fn.myPlugin = function(options) {
...
return this;
};
})(jQuery);
});
where dependencies does not include jQuery. Then, I bootstrap the app by calling:
<script src="js/vendor/require-2.1.6.min.js" data-main="js/app.js"></script>
And the code in app.js is
requirejs.config({
paths: { 'jquery': 'vendor/jquery-1.9.1.min' },
shim: { 'myPlugin': ['jquery'] }
});
requirejs(['jquery','myPlugin'], function main($) {
$('#plugin').myPlugin(options);
});
However, my code always attempts to bind the plugin (from app.js), fails when the plugin is not a method on jQuery, and THEN loads the compiled plugin code and creates the method on jQuery. What's the problem here??
UPDATE 2
So, I've created a modular JavaScript file plugin.js using requirejs and its optimizer. The main code in the compiled plugin script,
requirejs(dependencies, function main(dependencies) {
(function($) {
$.fn.plugin = function(options) { return this; }
})(window.jQuery);
);
doesn't get called until after the main code in the parent app:
requirejs(['jquery','plugin'], function main($) {
$('#plugin').plugin({});
});
I assume this is because they are both making calls to requirejs. So the problem here is how to write my plugin such that it is usable within an AMD loader.
Sorry, I'm still figuring out the right questions to ask.
There is a pretty standard convention for modularizing plugins for use with and without requirejs. It looks something like this:
(function(){
var makeplugin = function(dependancies){
//do your plugin
};
if(define && define.amd) {
defined(dependancies,function(dependancies){
makeplugin(dependancies);
});
} else {
makeplugin(dependancies)
}
}());
Because your plugin uses require internally, but your parent app doesn't have to, you can load requirejs using $.getScript()
(function(){
var makeplugin = function($){
//do your plugin
};
if(define && define.amd) {
// require is defined already, just use the plugin and have it load what it needs
define(["jquery"],makeplugin);
} else if(jQuery){
// load require
jQuery.getScript("/vendor/require",function(){
require.config({
// your config
});
makeplugin(jQuery);
});
} else {
throw "requirejs or jquery are required for this plugin";
}
}());
It isn't pretty but it should work.
I'm having a lot of troubles with RequireJS, I get errors simply by using a define module.
Let's assume I have this configuration:
require.config({
baseUrl: "js/",
paths: {
jquery: "libs/jquery/jquery-2.0.2.min",
handlebars: "libs/backbone/template/handlebars",
lodash: "libs/backbone/template/lodash.min",
backbone: "libs/backbone/backbone-1.0.0.min",
helper:"app/helper",
jquery_cookie:"libs/jquery/plugin/jquery.cookie",
text:"libs/require/text-2.0.7"
},
shim: {
"lodash": {
exports: '_'
},
"handlebars": {
deps:["jquery"],
exports: 'Handlebars'
},
"backbone": {
deps: ["helper", "lodash", "handlebars", "jquery"],
exports: "Backbone"
}
},
urlArgs: "bust=" + (new Date()).getTime()
});
define(["jquery"], function ($) {
console.log('define "jquery" on config.js');
return $;
});
console.log("end config.js");
First, I've tried the classic way, I've loaded a config file where I have all the dependances of my JavaScript files, I'm using jQuery, Backbone and other libs.
<script type="text/javascript" data-main="config" src="js/libs/require/require-2.1.6.min.js"></script>
<script type="text/javascript">
require(["jquery"], function ($) {
console.log("jquery loaded");
});
</script>
With this configuration, i get these errors and logs sequence:
Uncaught Error: Mismatched anonymous define() module: function (){return r}
> http://requirejs.org/docs/errors.html#mismatch
end config.js
define "jquery" on config.js
It seems the error is referred to the function require.config(...);
I thought it was a load problem, so I've tried to use the var require as described in RequireJS site without solving it.
The absurd thing is I'm working on a fullscreen app built in Backbone with the same configuration without getting any problem, here I need to work more with different views and I cannot start, basically the whole difference is here I'm using CakePHP.
Why this won't work, where I'm wrong?
The jQuery version you are using already has AMD support. So you don't have to use shim for it. You can directly give the path and start using it.
Since the module is already defined in the jQuery library, it throws errors when you try to redefine it. The following code tries to define an anonymous module.
define(["jquery"], function ($) {
console.log('define "jquery" on config.js');
return $;
});
remove the above code and should work fine. The following code uses require method to load the jquery module.
require(["jquery"], function ($) {
console.log($(document));
});
Hopefully this works.
I am totally new to RequireJS so I'm still trying to find my way around it. I had a project that was working perfectly fine, then I decided to use RequireJS so I messed it up :)
With that out of the way, I have a few questions about RequireJS and how it figures out everything. I have the file hierarchy inside the scripts folder:
I have the following line inside my _Layout.cshtml file:
<script data-main="#Url.Content("~/Scripts/bootstrap.js")" src="#Url.Content("~/Scripts/require-2.0.6.js")" type="text/javascript"></script>
And here's my bootstrap.js file:
require.config({
shim: {
'jQuery': {
exports: 'jQuery'
},
'Knockout': {
exports: 'ko'
},
'Sammy': {
exports: 'Sammy'
},
'MD': {
exports: 'MD'
}
},
paths: {
'jQuery': 'jquery-1.8.1.min.js',
'Knockout': 'knockout-2.1.0.js',
'Sammy': 'sammy/sammy.js',
'MD': 'metro/md.core.js',
'pubsub': 'utils/jquery.pubsub.js',
'waitHandle': 'utils/bsynchro.jquery.utils.js',
'viewModelBase': 'app/metro.core.js',
'bindingHandlers': 'app/bindingHandlers.js',
'groupingViewModel': 'app/grouping-page.js',
'pagingViewModel': 'app/paging-page.js'
}
});
require(['viewModelBase', 'bindingHandlers', 'Knockout', 'jQuery', 'waitHandle', 'MD'], function (ViewModelBase, BindingHandlers, ko, $, waitHandle, MD) {
BindingHandlers.init();
$(window).resize(function () {
waitHandle.waitForFinalEvent(function () {
MD.UI.recalculateAll();
}, 500, "WINDOW_RESIZING");
});
var viewModelBase = Object.create(ViewModelBase);
ko.applyBindings(viewModelBase);
viewModelBase.initialize();
});
require(['viewModelBase', 'bindingHandlers', 'Knockout'], function (ViewModelBase, BindingHandlers, ko) {
BindingHandlers.init();
var viewModelBase = new ViewModelBase();
ko.applyBindings(viewModelBase);
viewModelBase.initialize();
});
Then I implemented my modules by using the define function. An example is the pubsub module:
define(['jQuery'], function ($) {
var
publish = function(eventName) {
//implementation
},
subscribe = function(eventName, fn) {
//implementation
}
return {
publish: publish,
subscribe: subscribe
}
});
I've basically done the same thing to all of my javascript files. Note that the actual file containing the pubsub module is jquery.pubsub.js inside the /Scripts/utils folder. This is also the case with other modules as well.
UPDATE:
Ok I updated my bootstrap file now that I think I understand what a shim is and why I should be using it. But it's still not working for me, although I've also declared all the paths that I think would've caused me trouble in getting them right. The thing is that it's not even going into my require callback inside the bootstrap file, so I guess I still have a problem in the way I'm configuring or defining my modules?
Well, for one, if you are going to use a non-amd library, say jQuery, with require and have the jQuery function passed to the callback, you need to specify a shim with exports in your require config, like so:
require.config({
shim: {
jQuery: {
exports: '$'
}
},
paths: {
jQuery: 'jquery-1.8.1.min.js',
}
});
Other than that I'm not sure I understand what your issue is exactly.
If you are using ASP.NET MVC take a look at RequireJS for .NET
The RequireJS for .NET project smoothly integrates the RequireJS framework with ASP.NET MVC on the server side using xml configuration files, action filter attributes, a base controller for inheritance and helper classes.
I did not completely understand what the problem is. But if it relates to JS libraries to be loaded with require.js then this boot file works for me:
require.config({
paths: {
"jquery": "/scripts/jquery-1.8.2",
"sammy": "/scripts/sammy-0.7.1"
},
shim: {
"sammy": {
deps: ["jquery"],
exports: "Sammy"
}
}
});
require(["jquery", "sammy"], function ($) {
$(document).ready(function () {
alert("DOM ready");
});
});
Please, note, there is no '.js' in paths.
BTW, if you use MVC 4, you don't need #Url.Content in 'href' and 'src' any more.