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();
});
});
Related
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'}
}
})
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 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!
I have a working application using requirejs, which I'm trying to optimize. I'm launching the application in 2 steps:
First I start with a setup file setup.js, which I'm calling from the page source code:
<script data-main="../js/setup" src="../js/l/require/require.js"></script>
This file contains my require setup
var IS_LOCAL = /(:\/\/localhost|file:\/\/)/.test(document.location.href);
requirejs.config({
waitSeconds: (IS_LOCAL ? 2 : 45),
baseUrl: "../js",
paths: {
intro: 'intro',
overrides: 'overrides',
jquery: 'l/jquery/jquery-1.8.2.min',
mobile: 'l/jquery-mobile/jquery-mobile-1.3pre.min',
multiview: 'p/multiview/multiview.min',
respond: 'p/respond/respond.min',
i18next: 'p/i18next.min.js'
},
shim: {
'overrides': { deps: ['jquery'] },
'mobile': { deps: ['jquery'] },
'multiview': { deps: ['jquery', 'mobile'] },
'respond': { deps: ['jquery'] },
'i18next': { deps: ['jquery'] }
}
});
// launch application - works, but I'm not happy with it
requirejs('overrides','jquery','mobile','multiview','respond','i18next','intro'],
function (overrides, $, mobile, multiview, respond, i18next, Intro) {
'use strict';
Intro.start(overrides, $, mobile, multiview, respond, i18next);
}
);
This "triggers" my application controller intro.js, which looks like this:
define([], function () {
'use strict';
var start = function () {
require(['overrides','jquery','mobile','multiview','respond','i18next'],
function () {
// stuff
}
); // end require
} // end start
return {
"start": start
};
});
I'm still figuring out my way with requireJS, so while the above initializes correctly, I'm not sure if this is the best way to handle. Specifically I'm wondering:
Questions:
1) In my setup.js file, I'm triggering Intro.start() with plenty of parameters. Do I need the parameters there or should I put them inside intro.js when I'm doing my second require call?
2) Do I need the first require at all, because I'm requiring all files and then trigger a "file" (intro), which requires everything again?
3) How do I make objects available in intro.js? Say I need the i18next object inside intro.js to do some manual translations. Do I export in the shim and pass along through my two requires?
Thanks for some insights!