I am using RequireJS for my Dependency-Management and scrollReveal.js (github-repo) for creating nice effects.
But scrollReveal, for some reasons seems not to work.
Here is some code:
require.config({
...
paths: {
'sreveal': "assets/vendor/scrollreveal.min"
}
...
});
And in my common.js, I use it like this:
define([
'jquery',
'sreveal'
], function ($, sreveal) {
...
});
Usally, this plugin works by setting up a data-attribute for the elements which should reveal.
By using this script without RequireJS, it work's perfectly.
I also tried to init scrollReveal like this:
window.scrollReveal = new scrollReveal();
No result.
Hope you have any experience with this.
ScrollReveal is AMD-compatibile but you need to configure paths element correctly to link its name (which is "scrollReveal") with script's location on your filesystem:
require.config({
// ...
paths: {
'scrollReveal': 'assets/vendor/scrollreveal.min'
}
// ...
});
And then require use it via:
define(['jquery', 'scrollReveal'], function ($, sreveal) {
console.log('ScrollReveal loaded?', sreveal);
});
You could have a look at this answer, I tried to explain how to deal with this kind of problems in practice.
Related
I'm working on an application that combines ember.js and jquery-mobile.js
In order to make those two play nice with each other, I need to load JQM after Ember is initialized. So I use the following code in my main file, app.js:
require.config({
baseUrl: 'resources/js/',
waitSeconds: 200,
paths: {
text: 'lib/require/text',
ember: 'lib/ember-1.5.1.min',
jquery: 'lib/jquery-2.1.1.min',
mobile: 'lib/jquery.mobile-1.4.2.min',
handlebars: 'lib/handlebars-1.3.0.min',
},
shim: {
'ember': {
deps: ['handlebars', 'text', 'jquery']
}
}
});
define('app', [
'jquery',
'app/many/files',
'ember'
], function($,
ManyFiles) {
$(document).bind('mobileinit', function() {
$.mobile.ajaxEnabled = false;
$.mobile.pushStateEnabled = false;
$.mobile.linkBindingEnabled = false;
$.mobile.hashListeningEnabled = false;
$.mobile.ignoreContentEnabled = true;
});
App = Ember.Application.create({
ready: function() {
require(['mobile']);
}
});
// Initialize stuff...
}
(As you can see, jqm is loaded only when the ember application is ready)
This works great, but when I build all the files into a single minified js file, I run into this problem: As soon as the code requires JQM, I see an http call on the network tab which goes to grab jquery-mobile.js
Of course this is an unpleasant process. The only solution I can think of is to load JQM along with all the other dependencies but not execute it. Then, the code can execute JQM instead of requiring the file.
However I am not experienced on require.js and I have no idea on how to do that. Any help is appreciated. Other methods to accomplish the same thing are also appreciated
Thanks
EDIT:
Why does JQM needs to get loaded after Ember?
Because JQM add wrappers, classes and events on the DOM that interfere with ember... and things get really bad
After a lot o fiddling I found out an answer to my problem:
...
App = Ember.Application.create({
ready: emberInit
});
// Initialize stuff
}
function emberInit() {
require(['mobile']);
}
It seems like the require statement was too nested for it to work normally (maybe a bug?)
NOTE:
While trying to find an answer to my problem I found out about a functionality of require.js that I would like to share with people that might have a similar problem and bump into this thread:
Apparently you can set a callback on the require configuration to run when all dependencies are loaded, like that:
require.config({
deps: ['jquery', 'handlebars', 'ember', 'socketio'],
callback: function () {
// Do stuff when above dependencies load
},
});
which was not EXACTLY what I needed, but others might find helpfull
I am using require.js with knockout on a website and would like to use the simpleGrid example from this link http://knockoutjs.com/examples/grid.html however I cannot include kncokout.simpleGrid.3.0.js with Require.
I have tried wrapping the plugin with
define(['jQuery', 'knockout'], // Require knockout
function($, ko) {
});
This does not work it seems the problem occurs with the templates.
Any help appreciated
In your require config, you should create a path to the simpleGrid library and use the shim to tell it that it depends on Knockout so that your libraries are loaded in the correct order. Here's an example:
var require = {
paths: {
'jquery': 'lib/vendor/jquery-2.0.3',
'ko': 'lib/vendor/knockout-3.0.0',
'koSimpleGrid': 'lib/vendor/knockout.simpleGrid.3.0'
},
shim: {
'koSimpleGrid': {
deps: ['ko']
},
}
};
And then you could copy paste the view model code from the example inside of a define like this:
define(['jquery', 'ko', 'koSimpleGrid'], function ($, ko) {
// VIEW MODEL GOES HERE
});
I agree the problem seems to be with the code that writes the grid template. Essentially, because requirejs loads modules asynchronously, document.write() can't be used - writing of the document has finished by the time a module executes. This StackOverflow answer explains it well I think.
I got round it by instead creating and appending the required script tag templates using dom methods:
templateEngine.addTemplate = function(templateName, templateMarkup) {
var scriptTag = document.createElement('script');
scriptTag.type = 'text/html';
scriptTag.id = templateName;
scriptTag.text = templateMarkup;
document.getElementsByTagName('body')[0].appendChild(scriptTag);
};
My amd version is in this gist.
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?
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.