Sorry for posting another "how do you use * with require.js" question, but I can't seem to get dust.js working in my require project. I've googled around and other people are definitely getting dust to work with require. My configuration is fairly standard, but I can't find anyone having the same problems as I'm seeing.
I'm using the version of dust 0.3.0 from here:
https://github.com/akdubya/dustjs/blob/master/dist/dust-core-0.3.0.js
here is my config:
requirejs.config({
//exceptions:
paths: {
'jquery' : 'lib/require-jquery.1.9.1',
'jquery.mockjax' : 'lib/jquery.mockjax.1.5.1',
'dust' : 'lib/dust.0.3.0'
},
//Shims are required for jQuery plugins.
shim: {
'jquery.mockjax': {
deps: ['jquery'],
exports: 'jQuery.fn.mockjax'
},
'dust': {
exports: 'dust'
}
}
});
this is how I include dust in my module:
define( function( require ) {
var _d = require('dust')
, _template1 = require('text!template/basicmodal.html');
function render(key,callback){
var compiled = _d.compile("Hello {name}!", key);
_d.loadSource(compiled);
_d.render(key, {name: "Fred"}, callback);
}
return {
render : render,
If I set a breakpoint within the render function I can see that _d does contain the dust object, but for some reason it doesn't have all its methods. In particular its 'compile' method is missing which causes my code to fail.
Does anyone with a better understanding of dust know what I might be missing here?
Please see if using https://github.com/akdubya/dustjs/blob/master/dist/dust-full-0.3.0.js instead helps you.
Dust is now supported by Linkedin. If you want to compile some dust template, maybe this might help you https://github.com/linkedin/dustjs/wiki/Dust-Tutorial#compiling-a-dust-template.
I am not an expert in JS but it could be useful to use Backbone in addition to dust + require.
Chek out this (I don't have enough reputation to put more links) : http://weatherlabs.com/2012/10/12/backbone-underscore-and-dust/
You can precompile the template and have it wrapped in a define call using this npm module:
https://npmjs.org/package/grunt-dust-require
Related
I'm trying to use the Shipping Time JS plugin on my Magento 2 website, it requires both moment.js and jQuery in order to work however it's not working. I'm getting a ReferenceError: moment is not defined in shiptime.js on line 49 which is the following:
try {
if (moment === undefined || $ === undefined ) throw Error("please include jquery & moment.js");
} catch (e) {
console.log(e);
}
==============
My require.js
This is what my requirejs-config.js looks like, it's sitting in app/design/frontend/##/##/requirejs-config.js:
var config = { // eslint-disable-line no-unused-vars
packages: [{
name: 'momentjs',
location: 'js/',
main: 'moment'
}],
map: {
'*': {
'menu': 'Magento_Theme/js/disable-menu',
'shippingtime': 'js/shiptime'
}
},
shim: {
'momentjs': {
deps: ['jquery']
},
'shippingtime': {
deps: ['jquery',',momentjs']
}
}
};
jQuery is loaded elsewhere and is definitely being loaded (I have various other jQuery libraries which are all working).
==============
Debugging
I initially thought the moment.js/shiptime.js files weren't being loaded in however they are when I check both the source and the network panel. To further test this, I did the following to see if moment.js would output anything:
require(['momentjs'], function (moment) {
console.log(moment().format('LLLL'));
});
This does output the date in the console so moment.js is definitely loading, this is my code for the shiptime.js file which isn't working and gives me the error I mentioned above:
require(['jquery', 'shippingtime', 'momentjs'], function (moment) {
jQuery(document).ready(function () {
jQuery(function($) {
jQuery('.shipping-time').shipTime();
});
});
});
Any advice would be greatly appreciated!
It's been a while since I've worked with requirejs but since no one smarter has chimed in yet I'm happy to help you keep troubleshooting. Using jQuery with requirejs can be tricky, especially with a large and complex platform like Magento.
Without being able to see all of your code I would consider and investigate the following:
Are you initializing jQuery properly in a no-conflict way if necessary
Are you using require() vs. define() where and as intended
Are you versed in the challenges unique to Magento when using requirejs
Have you reviewed and followed the recommendations regarding the complexities of using moment with requirejs
Here is some corresponding reading on each:
On No-Conflict
require() vs define() plus other good insights
On Magento 2 with RequireJS
On complexities of Moment and RequireJS
https://momentjs.com/docs/#/use-it/require-js/
https://github.com/requirejs/requirejs/issues/1554#issuecomment-226269905
One last thing to try:
In your final code example you pass moment to the function but not jQuery. Have you tried something along these lines:
require(['jquery', 'momentjs', 'shippingtime'], function($, moment) {
$(document).ready(function() {
$('.shipping-time').shipTime();
});
});
My library use kriskowal/Q promises library and now I'm trying to load (with requirejs) application that use my library so I put all paths and shims and my requirejs.config section looks like this:
requirejs.config({
baseUrl: './',
catchError: false,
paths: {
beril: '../engine/build/src/bundle',
lodash: 'bower_components/lodash/lodash',
three: 'bower_components/three.js/build/three',
q: 'bower_components/q/q',
},
shim: {
lodash: {
exports: '_'
},
three: {
exports: 'THREE'
},
q: {
exports: 'Q'
},
beril: {
deps: ['lodash', 'three', 'q'],
exports: 'beril'
},
}
});
After this I suppose variables THREE, _ and Q to be defined in global space.
Now I'm loading and runinng application with this simple line:
require(['beril', 'js/stepbystep/' + $stateParams.page + '/app'], (beril, app) => app());
but then I'm getting error: ReferenceError: Q is not defined even though I can see in Chrome's network inspector that Q library have been loaded.
Also all the rest dependencies (THREE and _) are defined. Seems like requirejs`s shim does not work for this library. Can it be or am I missing something?
So what am I'm doing wrong and how should I deal with this situation?
I found solution and it was to add init function to my library's shim and then add Q as global object manually so my shim section now looks like this:
shim: {
lodash: {
exports: '_'
},
three: {
exports: 'THREE'
},
q: {
exports: 'Q'
},
beril: {
deps: ['lodash', 'three', 'q'],
exports: 'beril',
init: function(lodash, three, q){
window.Q = q;
}
},
}
however I don't clearly understand why it does not work without this and are there better ways to deal with this situation.
There are a few problems with your configuration. For one thing, you have unnecessary shim configurations. I installed lodash just now (with bower install lodash) and searched its code. It calls define. So you must not set a shim for it. RequireJS won't give you an error but you will get undefined behavior. The same is true of Q: it calls define so, no shim for it. Last I checked, THREE needs a shim.
The fact that Q calls define is also why it does not leak the symbol Q into the global space. It acts like a well-behaved AMD-module.
Ok, so how can we get Beril to find Q? Your solution works but I find it slightly iffy. The problem is that init is executed after the shimmed module is loaded. As long as Beril refers to Q only in the body of functions to be executed later, it will work. And I guess this is how Beril works now. However, if a new version of Beril needs to refer to Q when the file that contains Beril is first executed, it will fail because Q does not exist yet.
One way to work around the problem that is future-proof is to use map and some glue. Keep your shim for beril but remove the init. Define a module named q-glue:
define(['q'], function (Q) {
window.Q = Q;
return Q;
});
And declare this map in your configuration:
map: {
beril: {
q: "q-glue"
}
}
This says "when q is requested from beril load q-glue instead." By doing this, window.Q will be defined before Beril is loaded.
I take it you are the author of Beril. I urge you to make your library AMD-compatible so as to spare users of your library having to go through configuration pains to get it working with AMD-loaders (like RequireJS).
It worked for me after I downgraded to version 0.9 up until 1.0.1 as mentioned in the readme. The current version 2.0.2 has significant braking changes as mentioned by Kris Kowal here.
I didn't have the need to set the global variable as the older version checks the environment and does so if loaded before require.
You need to add q to require()...
require(['beril', 'q', 'js/stepbystep/' + $stateParams.page + '/app'], (app, beril, q) => app());
JustGage uses Raphael, which as is well-discussed here, is not AMD compliant (and so doesn't work with Require.js).
I have not used Require.js before, nor done a lot of JS, so I am battling to get my head around this. There has been a lot of trial and error ;)
Using the approach suggested here, I have split the Raphael modules out into separate files and included them separately, as well as making a guess as to what to do for JustGage.
require.config({
paths: {
//other links removed
'eve': 'vendor/eve/eve',
'raphael-core': 'vendor/raphael/raphael.core',
'raphael-svg': 'vendor/raphael/raphael.svg',
'raphael-vml': 'vendor/raphael/raphael.vml',
'raphael': 'vendor/raphael/raphael.amd',
'justgage': 'vendor/justgage/justgage.1.0.1.min'
},
shim: {
'eve': {
exports: "eve"
},
'raphael': {
deps: ['eve'],
exports: "Raphael"
},
'justgage': {
deps: ['raphael'],
exports: "JustGage"
}
}
});
But the instructions then say "After the above configuration, you can start using Raphael like other require-js modules" which is not so helpful ;)
I think I need to do something in main.js?
In my cshtml page I have
require(["raphael", "justgage"], function(JustGage) {
$(function() {
var a = new JustGage({
id: "pvgauge",
value: #Model.GaugeValues.PV,
min: #Model.PVGauge.MinValue,
max: #Model.PVGauge.MaxValue,
title: "Personal Volume",
label: "PV",
levelColors: gaugeSettings.levelColors,
levelColorsGradient: gaugeSettings.levelColorsGradient,
showInnerShadow: gaugeSettings.showInnerShadow,
shadowSize: gaugeSettings.shadowSize,
labelFontColor: '#7ACE30',
titleFontColor: gaugeSettings.titleFontColor,
valueFontColor: gaugeSettings.valueFontColor
});
});
});
Now this at least finds JustGage, but now gives the error 'Raphael' is undefined.
(I have also tried just doing a script include directly in the cshtml file but get the error 'Mismatched anonymous define() module: function (eve) {')
Is my understanding correct that Require.js means things are not in global scope? And JustGage is expecting Raphael to be in global scope?
Any help on getting JustGage working? Or recommendations for an equivalent library for "speedo"-type gauges that will work with Require.js?
almost there, you need add it to the function as well, so it's available to JustGage.
require(["raphael", "justgage"], function(raphael,JustGage) {
If justgauge is a module then you should load the dependency in the module, as it will be looking in that module for raphael, however as you've already loaded it, it should work,
it's easier to keep track of your dependencies and load them where needed,
define(['module' , "pathto/raphael"], function (module, raphael) {
This worked for me:
require('eve');
window.Raphael = require('raphael');
require('justgage');
I recently tried to use the gulp Gist posted here:
Everything builds fine, but in the browser I get an error in the generated templates.js file:
global.Handlebars = require("handlebars");
module.exports = Ember.TEMPLATES["index"] = Ember.Handlebars.template(function anonymous(Handlebars,depth0,helpers,partials,data) {
The error claiming, basically, that 'module' is undefined...
I'm getting a strong feeling that I'm missing something extremely trivial here.
Thanks in advance
Because this causes the file to be wrap in some shim javascript:
'templates': {
path: 'public/js/templates.js',
exports: 'Ember.TEMPLATES'
},
Remove it and you'll be fine.
And requiring Ember in the prebundle is useless if you are also requiring it from your code.
I'm having issues trying to load ckeditor via requirejs (I've tried converting the main ckeditor js file into individual modules but that has just caused all hell to break loose) and so I'm now checking to see if there is a very simple way to do this that I've missed.
I know requirejs allows you to load normal js scripts so maybe just loading the ckeditor.js file (un-edited, so it's still an IIFE/self-executing function) - would that work with requirejs or if you're using requirejs for loading modules, does the entire project then need to be module based?
Any help appreciated.
Kind regards,
Mark
Alternatively, you can create a RequireJS shim to load things in the correct order, and alias proper RequireJS module names to the CKEditor distribution files.
This means your module still declares it is dependant on CKEditor, which is a lot nicer than having it just show up by magic.
require.config({
shim: {
'ckeditor-jquery':{
deps:['jquery','ckeditor-core']
}
},
paths: {
"jquery": '/javascript/jquery-1.7.1/jquery.min',
'ckeditor-core':'/javascript/ckeditor-3.6.4/ckeditor',
'ckeditor-jquery':'/javascript/ckeditor-3.6.4/adapters/jquery'
}
});
then in a module you can depend on ckeditor-jquery (or ckeditor-core for that matter, if you don't need the jQuery integration) and know it'll be available:
require(
[
"jquery",
"ckeditor-jquery"
],
function( _jquery_ ) {
$('#editorContent2').ckeditor({
customConfig : '',
skin:'office2003'
});
}
}
Another way to do that:
var require = {
"shim": {
"path/foo/ckeditor/ckeditor": { "exports": "CKEDITOR" }
}
};
define(['moduleX', 'path/foo/ckeditor/ckeditor'], function (x, ckeditor) {
ckeditor.editor.prototype.fooFunc = function() {
};
});
OK, it seems I answered my own question here.
Instead of trying to break ckeditor down into modules I just used RequireJs to load the script in it's entirety.
require(['require', 'dependancy-A', 'dependancy-B', 'dependancy-C'], function(require, A, B, C){
// this = [object DOMWindow]
// CKEDITOR_BASEPATH is a global variable
this.CKEDITOR_BASEPATH = '/ckeditor/';
require(['/ckeditor/ckeditor'], function(){
// Code to create a new editor instance
});
});
```