I'm trying to build a requirejs module giving client code the options to render stuff with d3.js . The first plugin I want to use is a sankey diagram . My module so far:
define(['d3'], function(ignore) {
console.log("bef", d3);
require(['sankey.js']);
console.log("aft", d3);
d3.sankey();
return {
...
d3: d3,
renderSankey: function(options) {
...
}
}
The sankey.js script uses the global d3
variable and adds the function sankey()
. (I tried both btw, define(['d3'], function(ignore)
and define(['d3'], function(d3)
, exactly the same result). The error: TypeError: d3.sankey is not a function
, no matter if I try to call it directly as the code shows or like this.d3.sankey()
in the renderSankey
function.
The console output says (both times, before and after the require(...)
call:
sankey: d3.sankey()
No matter what I try, it won't work. I feel like I missed something JS specific about shadowing, but why is there a sankey function, when I console.log
the object and a row later, when I try to call I get an error? What am I doing wrong?
info:
/edit: Here is the Require configuration (given by the Splunk Dashboard)
require.config({
baseUrl: "{{SPLUNKWEB_URL_PREFIX}}/static/js",
waitSeconds: 0 // Disable require.js load timeout
});
The require
call you are using to load sankey
is asynchronous. It will launch the loading of sankey
but by the time require
returns, sankey
is not loaded. You should change your code to:
define(['d3', 'sankey'], function (d3) {
d3.sankey();
I take it that d3
also leaks the symbol d3
in the global space but AMD modules should not rely on global symbols unless these are part of the runtime environment (eg window
, document
).
You also need to set your RequireJS configuration to make sankey
dependent on d3
because the define
above does not by itself ensure that d3
will load before sankey
. So you need this in your configuration:
shim: {
sankey: ['d3']
}
This makes sankey
dependent on d3
. (Note that shim
can only be used to affect the loading of files that are not proper AMD module. sankey
does not call define
to register itself, and thus is not a proper AMD module, and we can use shim
for it.)
Also, module names should generally not have .js
in them so when you want to load the plugin, load it as sankey
, not sankey.js
.
Okay, I think @Louis and I just misunderstood each other. This may be caused by my own stupidity, since I wasn't aware that a configuration of require.js can be done anywhere (and not only once in the root file). How ever, to still get the Splunk specific part I post this answer (instead of accepting Louis'):
I added a new app to my splunk environment to (a viz app). I actually configure the dependencies first (in the by other splunk apps loadable d3-viz module):
require.config({
paths: {
'd3': '../app/D3_Viz/d3', // d3.js
'sankey': '../app/D3_Viz/sankey', // sankey.js
'XYZ': 'all the paths go here'
},
shim: {
'sankey': ['d3'],
'XYZ': ['d3'],
// all the dependecies go here
}
});
define(['splunkjs/ready!', 'jquery', 'd3'],
function(mvc, $, ignore) {
var d3Vis = {
...
renderSankey: function(options) {
// load dependencies dynamically
require(['sankey'], function() {
// actually render things
});
},
renderXYZ: function(options) {
require(['XYZ'], function() {
...
});
},
...
}
}
return d3Vis;
All my dependencies can be configured in the viz-app (and not in the client code using the app, this has been my fundamental missunderstanding of require.js); the only thing to do is loading the app/viz as a whole (in this example in a HTML dashboard:
require([
"splunkjs/mvc",
"splunkjs/mvc/utils",
"splunkjs/mvc/tokenutils",
"underscore",
"jquery",
"splunkjs/mvc/simplexml",
"splunkjs/mvc/headerview",
"splunkjs/mvc/footerview",
...
"../app/D3_Viz/viz"
],
function(
mvc,
utils,
TokenUtils,
_,
$,
DashboardController,
HeaderView,
FooterView,
...
d3Viz
){
... splunk specific stuff
// No dependencies have to be configured
// in the client code
d3Viz.renderSankey({...});
}
);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.