I was trying to make use of the CWSpear`s plugin, for dropdown menus with hover, using require.js.
But I keep getting an error for it: "Error: Script error".
What do I need to do with in order to use it with require.js?
EDIT:
To help #jakee by focusing the question, this is the configuration I've made :
requirejs.config({
paths: {
"myBootstrap": _myBootstrappingPath + "js/bootstrap",
"myControllers" : _myBootstrappingPath + "js/controllers",
//jquery
"jquery": _libsPath + "jquery/1.9.1/js/jquery",
"jquery_validate": _libsPath + "jquery/validate/1.12.0/js/jquery.validate",
//Bootstrap related
"twitterBootstrap": _libsPath + "bootstrap/2.3.1/",
"select2" : _libsPath + "select2/3.3.2/select2",
//misc
"underscore": _libsPath + "underscore/1.4.4/js/underscore",
"backbone": _libsPath + "backbone/1.0.0/js/backbone",
"backbonePageable": _libsPath + "backbone/backbone-pageable/1.2.0/js/backbone-pageable",
"backgrid": _libsPath + "backgrid/0.2.0/backgrid",
"backgridAssets": _libsPath + "backgrid/0.2.0/assets/js",
"backgridExtensions": _libsPath + "backgrid/0.2.0/extensions",
//plugins and extensions
"plugins_datetimepicker": _pluginsPath + "/datetimePicking/bootstrap-datetimepicker",
"plugins_dropdownHover": _pluginsPath + "/dropdownHover/dropdownHover",
},
shim: {
underscore: {
exports: '_'
},
backbone: {
deps: ["underscore", "jquery"],
exports: "Backbone"
},
bootstrap: {
deps: ["jquery"],
exports: "$.fn.popover"
},
'select2': ["jquery"],
'backgrid': {
deps: ["jquery", "backbone"],
exports: "Backgrid"
},
'backbonePageable': {
deps: ["jquery", "underscore", "backbone"],
exports: "PageableCollection",
init: function(nhonho){
Backbone.PageableCollection = PageableCollection;
}
},
plugins_datetimepicker: {
deps: ["jquery", "bootstrap"]
},
plugins_dropdownHover: {
deps: ["jquery", "bootstrap"]
}
}
});
and use it in:
(function (bs) {
require(["jquery",
"twitterBootstrap",
"select2",
"plugins_datetimepicker",
"plugins_dropdownHover",
"myControllers/defaultController"], function ($) {
var defaultCtrlr = new ticket.defaultController(bs);
bs.onInit();
defaultCtrlr.start(bs.options);
bs.onReady();
});
})(window.my.bootstrap);
As long as I comment the "plugins_dropdownHover" line, in the defines, it works fine. If it tries to load that script, it fails.
I see a couple possible issues with your config:
1: You may have some confusion in naming between the paths config and the shim config. For example, I see this in shim:
bootstrap: {
deps: ["jquery"],
exports: "$.fn.popover"
},
But then in paths you have this:
"twitterBootstrap": _libsPath + "bootstrap/2.3.1/",
They should match. I suspect that what happens is when you require 'plugins_dropdownHover', it looks for shim dependency 'bootstrap' and then never finds a path to load it since your paths config contains 'twitterBootstrap' and not 'bootstrap'
2: _libsPath + "bootstrap/2.3.1/" looks like a path to a folder, not a file. When you later require 'twitterBootstrap' and look at the network tab of Chrome dev tools (or whatever you use), do you see the right Bootstrap file loaded?
If you were just shimming this one library, I think it would look something like this:
requirejs.config({
paths: {
jquery: _libsPath + "jquery/1.9.1/js/jquery",
// note: full path to file (minus the .js)
bootstrap: _libsPath + "bootstrap/2.3.1/bootstrap",
plugins_dropdownHover: _pluginsPath + "/dropdownHover/dropdownHover"
},
shim: {
jquery: {
exports: ["jQuery", "$"]
},
bootstrap: {
deps: ["jquery"],
exports: "$.fn.popover"
},
plugins_dropdownHover: {
// might be able to list just bootstrap here since it will follow the chain
// and load jQuery before loading bootstrap
deps: ["bootstrap", "jquery"]
}
}
});
The Demo Page lists only three scripts: jQuery, Bootstrap, and the plugin. And this is exactly the order that RequireJS will load them with the above shim config.
Anything is practically available to use with RequireJS, either via the AMD way of through the shim config.
First you will want to know if the module is AMD-compatible. The best place to check is the source code. In RequireJS all AMD modules are declared with the define -function. If there is no reference to the said function in the source, you can be quite sure your library/plugin/whatever doesn't support AMD out of the box. If define is present, you can just import the file by declaring it in the paths config.
Thankfully RequireJS allows you to shim javascript files that don't declare their contents to be AMDable via define. What it basically does, is that you tell it what the file's dependencies are and what it should insert into the window object and RequireJS will make sure to have the deps loaded before and grabbing the results after.
paths: {
'otherlib': 'path/to/otherlib',
'mylib': 'path/to/mylib' // define alias for mylib
}
shim: {
'mylib': {
deps: ['otherlib'],
exports: 'MyLib'
}
}
As the file you're trying to load is a jquery plugin, there is no need for exports or anything, because the plugin just sticks its stuff into $. RequireJS provides a nice example of this
"shim": {
"jquery.someplugin": ["jquery"],
"jquery.otherplugin": ["jquery"]
}
N.B! In the example, RequireJs is configured so that there is no need to use aliases as the baseUrl points to the directory with jquery and the plugins!
Hope this helps!
Related
I am new working with requirejs, I have an old Asp.net Webform application that I am trying to apply some javascript module loading using requirejs. In this app I am using a jquery plugin named Time Entry, but is not working if I use requirejs, only works if I added the reference the old way. Here is my requirejs configuration and declaration.
In the aspx file:
<script src="../../scripts/require.js"></script>
<script>
require(["../../app/shared/require.config"],
function (config) {
require(["appIncidentTracking/incident-type-init"]);
});
</script>
My require.config file is like this:
require.config({
baseUrl: '../../scripts',
paths: {
app: '../../app/utilization-management',
appIncidentTracking: '../../app/incident-tracking',
jquery: 'jquery-3.1.1.min',
jqueryui: 'jquery-ui-1.12.1.min',
jqueryplugin: '../../js/jquery.plugin.min',
timeentry:'../../js/jquery.timeentry.min',
handlebars: 'handlebars.amd.min',
text: 'text',
moment: 'moment.min',
datatable: 'DataTables/jquery.dataTables.min',
blockUI: 'jquery.blockUI.min',
shared: '../../app/shared',
bootstrap: 'bootstrap.min',
'bootstrap-datepicker': 'bootstrap-datepicker.min',
'bootstrap-multiselect': '../js/bootstrap-multiselect/bootstrap-multiselect'
},
shim: {
bootstrap: {
deps: ['jquery']
},
'bootstrap-multiselect': {
deps: ['bootstrap']
},
timeentry: {
deps:['jquery', 'jqueryplugin']
}
}
});
and in my incident-type-init.js I only call the plugin:
/**
* Incident Type Init page
* #module incident-type-init
*/
define(function (require) {
var $ = require('jquery'),
jqueryplugin = require('jqueryplugin'),
timeentry = require('timeentry'),
bootstrap = require('bootstrap');
/**
* Jquery ready function
*/
$(function () {
$('.js-timeentry').timeEntry();
});
});
but when the application runs I got this error:
$.JQPlugin.createPlugin is not a function, it is like does not find the jquery.plugin.js
I checked the network tab in chrome and both files are loaded, jquery.plugin.js and jquery.timeentry.js
UPDATE: In our application, we are using Asp.net MasterPages, and there we are loading an old jquery version, 1.5.1, and I use that MasterPage in my page, but when I check the network tab in chrome, is loading the MasterPage scripts first,then all the requirejs stuff.
and the funniest part is that sometimes work, sometimes not.
Any clue?
The module jqueryplugin needs to have jQuery already loaded for it. It is not an AMD module because it does not call define. So you need an additional entry in shim for it:
jqueryplugin: ["jquery"]
The above is short for:
jqueryplugin: {
deps: ["jquery"]
}
I don't think your code is syntactically correct.
Try this:
1. Your script should refer to the require.config in data-main.
<script data-main="PATH_TO_CONFIG_FILE" src="../../scripts/require.js"></script>
2. Quotes are missing in paths of the config file. Instead it should be like this
require.config({
baseUrl: '../../scripts',
paths: {
"app": '../../app/utilization-management',
"appIncidentTracking": '../../app/incident-tracking',
"jquery": 'jquery-3.1.1.min',
"jqueryui": 'jquery-ui-1.12.1.min',
"jqueryplugin": '../../js/jquery.plugin.min',
"timeentry":'../../js/jquery.timeentry.min',
"handlebars": 'handlebars.amd.min',
"text": 'text',
"moment": 'moment.min',
"datatable": 'DataTables/jquery.dataTables.min',
"blockUI": 'jquery.blockUI.min',
"shared": '../../app/shared',
"bootstrap": 'bootstrap.min',
"bootstrap-datepicker": 'bootstrap-datepicker.min',
"bootstrap-multiselect": '../js/bootstrap-multiselect/bootstrap-multiselect'
},
shim: {
"bootstrap": {
deps: ["jquery"]
},
"bootstrap-multiselect": {
deps: ["bootstrap"]
},
"timeentry": {
deps:["jquery", "jqueryplugin"],
exports:"timeentry"
}
}
});
3. Since your module has dependencies, list them like this:
define(["jqueryplugin","timeentry","bootstrap"],function(jqueryplugin,timeentry,bootstrap) {
$(function () {
$('.js-timeentry').timeentry();
});
});
How do you load other extensions for a jquery control called 'fancytree' I'm trying to get fancytee to load or include the fancytree.table.js and other extensions that are needed - below is my config
require.config({
shim: {
underscore: {
exports: '_'
},
backbone: {
deps: [
'underscore',
'jquery'
],
exports: 'Backbone'
},
'jquery-ui': {
exports: "$",
deps: ['jquery']
},
'fancytree': {
deps: ['jquery-ui']
},
'alertify': {
deps: ['jquery']
},
'fancytreetable': {
deps: ['jquery', 'fancytree']
}
},
paths: {
'jquery': '../lib/jquery/jquery',
'underscore': '../lib/underscore/underscore',
'backbone': '../lib/backbone/backbone',
'text': '../lib/text/text',
'jquery-ui': '../vendor/jquery-ui/jquery-ui',
'fancytree': [
'../vendor/fancytree/fancytree',
'../vendor/fancytree/fancytree.table'/* this extension here needs to be added but it's not included */
],
'alertify': '../vendor/alertify/alertify'
},
baseUrl: '/js/app',
});
Nikhil Mehta's comment points you in the right direction. Your paths value for fancytree is wrong. You use an array there when you want to provide fallback values for modules. If you give [A, B, C], for instance, if A fails to load, RequireJS tries B and if this fails, tries C. And if all fail, then that's a load failure.
Based on the configuration you show, you'd need:
fancytree: '../vendor/fancytree/fancytree',
fancytreetable: '../vendor/fancytree/fancytree.table'
You already have a shim that establishes that fancytreetable needs fancytree.
Note that unless you are using fairly old versions of Underscore and Backbone, you do not need to specify shim values for them. RequireJS is probably going to just ignore them but it may confuse people reading your code.
Here is how made it work, requirejs with jquery.fancytree-all and latest jquery-ui with AMD support, since working with individual extensions will require a lot of shimming.
onBuildWrite is optional but i prefer it this way
requirejs.config({
paths: {
'jquery': './js/vendor/jquery',
'jquery-ui': './js/vendor/jquery-ui',
'jquery.fancytree': './js/vendor/fancytree/jquery.fancytree-all'
},
shim: {
'jquery.fancytree': {
deps: ['jquery', 'jquery-ui/core', 'jquery-ui/effect', 'jquery-ui/effects/effect-blind', 'jquery-ui/widgets/draggable', 'jquery-ui/widgets/droppable'],
exports: 'jQuery.fn.fancytree'
}
},
onBuildWrite: function (moduleName, path, contents) {
'use strict';
if (moduleName === 'jquery.fancytree') {
contents = 'define( "jquery.fancytree", ["jquery", "jquery-ui/core", "jquery-ui/effect", "jquery-ui/effects/effect-blind", "jquery-ui/widgets/draggable", "jquery-ui/widgets/droppable"], function(jQuery) { ' + contents + '});';
}
return contents;
}
});
// usage
define([
'jquery',
'jquery.fancytree',
'css!./css/fancytree/skin-custom/ui.fancytree.css',
],
function($) {
'use strict';
//
$('#tree').fancytree({
checkbox: true,
source: [{title: 'Node 1'}, {title: 'Node 2',key: 'id2'}]
});
//
});
//
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']
}
}
Is it possible to set dependencies for an entire folder using require.js?
I know that you can use the shim configuration to set dependencies for a file:
require.config({
shim: {
'plugin/backbone/xyz': {
deps: ['lib/backbone'],
exports: 'Backbone'
}
}
});
In the above example I define the dependencies for the plugin backbone/xyz, but I would like to define the dependencies for all backbone plugins:
require.config({
shim: {
'plugin/backbone/': { // I would like to specify a folder here but it doesn't work.
deps: ['lib/backbone'],
exports: 'Backbone'
}
}
});
I think that I once found a gist about it on GitHub, but I can't seem to find it again.
To clarify: This isn't about requiring an entire folder, but setting dependencies for it - What all files in the folder needs before they are ready to initialize, each and one of them. It would be accomplished by adding shims for all the files, but I would like to only have to add that shim once for the entire folder:
shim: {
'lib/backbone': {
exports: 'Backbone' // <- No use of .noConflict() so all plugins can be required and export Backbone as well.
},
'plugin/backbone/a': {
deps: ['lib/backbone'], // <- Require backbone
exports: 'Backbone' // <- Export backbone
},
// Same requirement and folder for these files:
'plugin/backbone/b': {
deps: ['lib/backbone'],
exports: 'Backbone'
},
'plugin/backbone/c': {
deps: ['lib/backbone'],
exports: 'Backbone'
}
}
No, you cannot easily create a wildcard to add dependencies to all files under a folder from the configuration itself. You can however create a loop before the config and add whichever dependencies you want.
var config = {
shim: {
'plugin/backbone/xyz': {
deps: ['lib/dependency'],
exports: 'Backbone'
}
}
};
for(var shim in config.shim) {
if(shim.indexOf('plugin/backbone/') == 0) {
if(config.shim[shim].deps == null) {
config.shim[shim].deps = [];
}
config.shim[shim].deps.push('lib/backbone');
}
}
require.config(config);
This is the only way I can think of without having to override one of require's functions yourself. Not elegant, I will admit, but it will do the job.
Inspired by #J_A_X's answer
You can make an array of files that should share the same dependencies and create the shim dynamically:
var config = { shim: { /*...*/ } }
var plugins = ['a', 'b', 'c', 'd'],
plugin_shim = {
deps: ['lib/backbone'],
exports: 'Backbone'
};
plugins.forEach(function(file) {
config.shim['plugin/backbone/' + file] = plugin_shim;
});
require.config(config);
But this wouldn't work very well if someone would minuglify using r.js
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! :)