简体   繁体   中英

Using D3.JS and the sankey plugin in a require.js module

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()

FF控制台截图

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:

  • I'm using this inside a splunk html dashboard, this is maybe important...
  • I don't want the client code to import the dependicies (with about 100 plugins to come, this would be a pain)
  • When I just copy the content of the sankey.js into my module, everything works fine

/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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM