I'm working on an HTML5 page whose Javascript is powered by RequireJS. I've defined many dependencies using RequireJS, even ones that do not support AMD, with success (I mention this to illustrate that my RequireJS config is mostly functional). I have run into an issue with one particular dependency, however.
I'm trying to get Medialize's JQuery ContextMenu Plugin working.
The relevant parts (or, at least, the parts I believe to be relevant) of my RequireJS config are:
require.config({
paths: {
'jquery': "jQuery/jquery-latest", //jQuery 1.10.2
'jquery-ui': "jQuery/jquery-ui-1.10.3",
'jquery-contextmenu': "jQuery/jquery.contextmenu.r2.packed",
...
},
shim: {
"jquery-ui": ["jquery"],
"jquery-contextmenu": ["jquery"],
...
}
});
Then, in my code, I'm doing:
define(["jquery", "jquery-contextmenu"], function ($) {
$(document).ready(function () {
$.contextMenu({
selector: 'a',
items: {
"edit": {name: "Edit"}
}
});
});
});
So, the idea would be that any time an "a" tag got right-clicked, a context menu should pop out with one option, Edit.
Instead, Before I click anything, I get the error Uncaught TypeError: $.contextMenu is not a function which, to me, sounds like the contextMenu isn't being loaded correctly by/for RequireJS...but I'm not sure how to fix it.
Any assistance is appreciated
EDIT: Added a Plunker, but it's not working very well. I'm getting some timeouts and RequireJS script errors. Not sure why.
The errors you got in your Plunker were due to slapping ".js" at the end of your paths. Don't do this. (You did not do this in the code you show in the question but introduced this problem in your plunker.) You also did what this answer suggested, which was bad advice, because with the shim you are using for it jquery-contextmenu returns undefined for a module value. So assigning it to $ makes $ undefined.
Once I edit those issues out of your plunker (which I forked), the error in your question here does not happen.
Related
I'm running a gulp-concat script, which concats jquery, slick-carousel, t.js and my index.js files.
const pack = () => {
return gulp.src(['./node_modules/jquery/**/jquery.js', './node_modules/slick-carousel/**/slick.js', './assets/js/t.js-master/t.js', './js/index.js'])
// .pipe(gulp_babel({
// 'presets': ['#babel/env'],
// 'plugins': ["transform-remove-strict-mode"]
// }))
.pipe(gulp_concat('main.js'))
// .pipe(gulp_uglify())
.pipe(gulp.dest('./build'));
}
As you can see, I removed any pipes that might be causing the issue. The only task running is gulp-concat. (index.js is all in ES5 and I'm running on latest version of firefox, no need for babel atm) When I open my page, however, I get the error
Uncaught ReferenceError: define is not defined
Looking at main.js, I found a define object at the end of the jquery section - but only in the concatinated file, not the jquery in node_modules. I didn't add this, and I'm not using require.js as far as I know:
define( [
"./core",
"./selector",
"./traversing",
"./callbacks",
"./deferred",
"./deferred/exceptionHook",
"./core/ready",
"./data",
"./queue",
"./queue/delay",
"./attributes",
"./event",
"./event/focusin",
"./manipulation",
"./manipulation/_evalUrl",
"./wrap",
"./css",
"./css/hiddenVisibleSelectors",
"./serialize",
"./ajax",
"./ajax/xhr",
"./ajax/script",
"./ajax/jsonp",
"./ajax/load",
"./core/parseXML",
"./core/parseHTML",
"./effects",
"./effects/animatedSelector",
"./offset",
"./dimensions",
"./deprecated",
"./exports/amd",
"./exports/global"
], function( jQuery ) {
"use strict";
return jQuery;
} ); // jQuery seems to end here
How is this extra code being added, and how might I avoid it? I'm also using browserSync, but don't think that's related.
I've just checked the source of jQuery and there is a file:
https://github.com/jquery/jquery/blob/3.5.1/src/jquery.js
So what you need to do is to simply exclude it and it should fix the issue :)
This post is in reference to a previous question about NodeJS and requiring a module which injects a function. However, the previous question is in the context of Webpack. I too am trying to integrate d3.js and the d3.slider module, but using RequireJS.
According to the comment left by Nikos Paraskevopoulos a shim is needed. I have not successfully implemented the shim needed for the d3.slider module and was hoping someone could lead me in the right direction. Right now I have
require.config({
paths: {
"d3": "https://d3js.org/d3.v3.min",
"d3.slider": "lib/d3.slider"
},
shim: {
"d3.slider": {
"deps": ["d3"],
"exports": "d3"
}
}
});
require(['d3'], function(d3) {
console.log(d3.version);
d3.select("#time_slider").call(d3.slider());
});
This logs:
3.5.17
TypeError: d3.slider is not a function
I think my problem is in the shim, but I'm not quite sure. Any direction is appreciated.
When I look at the source code of d3.slider I see it calls define. So you do not need a shim for it.
Also, you are not loading it. You should do this:
require(['d3', 'd3.slider'], function (d3) {
console.log(d3.version);
d3.select("#time_slider").call(d3.slider());
});
In the source I see that it installs itself on d3. So you do not need to add a parameter to your anonymous function: once loaded it will be available on the d3 object.
I'm trying to add angular-formly to my AngularJs application using RequireJS. I've added
'apiCheck': '../vendor/api-check/dist/api-check',
'formly': '../vendor/angular-formly/dist/formly',
and added shim;
'formly': {
exports: 'formly',
deps: ['angular', 'apiCheck']
},
But, when I look at the network, it gets both of the libraries by making correct calls. However, it creates another request (probably formly doing this) to get apiCheck from http://localhost:9000/assets/javascripts/api-check.js addess.
So far, I have tried to add apiCheck in shim and removing it from the formly dependencies etc.
How can I avoid this? It does not allow my application to run. Thanks...
I've solved my problem. It turns out that formly looks for api-check and I've defined dependency as apiCheck. Changing main.js like this worked;
'api-check': '../vendor/api-check/dist/api-check',
'formly': {
exports: 'formly',
deps: ['angular', 'api-check']
},
I'm trying to get an app running that uses both AngularJS and RequireJS. I'm having problems getting my OpenLayers lib to work in this setup.
I set the main AMD-modules in the main.js:
require.config(
{
baseUrl: 'scripts',
paths: {
// Vendor modules
angular: 'vendor/angular/angular',
openLayers: 'vendor/openlayers-debug',
other modules.....
},
shim: {
angular: {
exports: 'angular'
},
openLayers: {
exports: 'OpenLayers'
},
other modules....
}
}
);
require(['openLayers',
'angular',
'app',
'controllers/olMapController',
'directives/olMap',
other modules...
], function(OpenLayers) {
return OpenLayers;
}
);
Then in the angular controller I use for the initialisation of OpenLayers, I try to indicate that openlayers-debug.js is a dependency:
define(['openLayers'],
function(OpenLayers) {
controllers.controller('olMapController', ['$scope', function(scope) {
console.log('Loaded olMapController. OpenLayers version: ' + OpenLayers.VERSION_NUMBER);
}]);
}
);
Well, this doesn't work. SOMETIMES the olMapController function is executed, but mostly not. The console then just displays an error stating:
Error: [ng:areq] Argument 'olMapController' is not a function, got undefined
So, I think OpenLayers hasn't finished loading yet, but somehow require thinks it has and continues loading code that depends on OpenLayers, in this case the olMapController. It then can't find its dependency, whereupon Angular returns this error message. Or something like that...? Sometimes something happens that makes OpenLayers load fast enought for it to be present when it is loaded as a dependency. What that is, I can't tell.
I left out other libraries and modules require and define to keep the code readable. I hope the example is still understandable.
Any ideas on what I could do to get openlayers to load well? The error message disappears when I leave the ['openLayers'] dependency out of olMapController.
Thanks in advance for any help.
Best regards,
Martijn Senden
Well, just for reference my final solution. The comment by angabriel set me off in the right direction.
Like i said, I'm using the domReady module provided by RequireJS to bootstrap Angular. This is still being called to early, because OpenLayers isn't loaded yet when angular starts. RequireJS also provides a callback property in require.config. This is a function that is triggered when all the dependencies are loaded. So I used that function to require the angular bootstrap module. My config now looks like this:
require.config(
{
baseUrl: 'scripts',
paths: {
// Vendor modules
angular: 'vendor/angular/angular',
domReady: 'vendor/domReady',
openLayers: 'vendor/openlayers-debug',
etcetera....
},
shim: {
angular: {
deps: ['jquery'],
exports: 'angular'
},
openLayers: {
exports: 'OpenLayers'
},
},
deps: ['angular',
'openLayers',
'app',
'domReady',
'controllers/rootController',
'controllers/olMapController',
'directives/olMap'
],
callback: function() {
require(['bootstrap']);
}
}
);
And the bootstrap module looks like this:
define(['angular', 'domReady', 'app'], function(angular, domReady) {
domReady(function() {
angular.bootstrap(document, ['GRVP']);
});
});
Thanks for the help. #angabriel: I upvoted your comment. It's not possible to accept a comment as an answer, is it? Your initial answer wasn't really the answer to my question, but the comment helped a lot...
Regards, Martijn
Sorry this answer will only contain text as your code is too big for a small example.
I would suggest to write a directive that utilizes head.js to load libraries you need at a specific context. One could also think of a directive that initializes openLayers this way.
I guess your error is a timing problem, because the require.js and angular.js module loading gets out of sync - more precisely there seems to be no sync at all between them.
update
To repeat my comment which lastly helped to lead the OP in the right direction:
You have to decide which framework gives the tone. If you go with requireJS, then require everything and bootstrap angular manually. (Remove ng-app="" from index.html) and do `angular.bootstrap()ยด when requirejs has completed. So the problem most likely is, that angular starts too early.
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?