6

I'm facing the problem of integrating with and , and i found an easy solution using require's shim. Using the shim i can export a variable, and i can also define dependencies:

d3: { exports: 'd3' },
nvd3: {
  exports: 'nv',
  deps: ['d3']
},

In this way, i simply install d3 and other packages with bower, and include them with require, and it is really quick and clean.

Nonetheless, i faced the following problem: there are probably some clashes between the global d3 variable and the local one (the one injected in the requiring modules). It is a d3 / require / nvd3 integration problem related to transitions and selections. I don't fully understand the problem, but i can already make some considerations.

  • jquery has the same problem with require, and they provide the noconflict method to fix it
  • many libraries have this behavior, they export a global symbol, but as far as i know there is no ready fix from requirejs for the general problem
  • the problem is fixed if i rename all global references to d3 into d3 source to another name. I still have d3 in the injected module, but it is not conflicting anymore

As far as i can see, all d3 functionalities work this way, but one of the nvd3 charts has transitions broken probably because a selection or dispatcher is overwritten. It requires deep understanding of d3 internals to spot precisely the error, but probably a simple yet correct handling of the global symbol will clear the whole tally of similar problems.

Probably, due to the way requirejs handles shim dependencies, the global d3 symbol is exposed to nvd3. The same symbol, anyway, is not available to requiring modules, and will be overwritten somehow if injected (included in the module dependencies).

I tried also to wrap d3 in a module and properly return a local d3 variable, but looks like the problem still persists.

I also asked help about this on this d3 group discussion which hosts some previous posts about d3 and modules.


I added a test case here: https://github.com/danse/requirenvd3

danza
  • 11,511
  • 8
  • 40
  • 47

3 Answers3

1

The problem doesn't appear to be your RequireJS configuration but rather the fact that you're using d3.v3 and not d3.v2. I downgraded d3 in your test case, and the transitions worked fine. (The popups are still all off to the side, which I don't think they should be, but that doesn't seem to be what you are presently concerned about.) It's my understanding that nvd3 has a few problems with d3.v3, this probably being one. Also, note the version of d3 in ddotsenko's jsFiddle. That could explain why his solution didn't work when you implemented it using your own d3.v3 library.

neverfox
  • 6,680
  • 7
  • 31
  • 40
  • yes, this is it, i also received a pull request on the repository confirming what you are saying, and there is an issue (closed!?) on the github project. about ddotsenko fiddle, it actually worked also with d3.v3, because it is just showing that we are able to import the object, not that nvd3 will work. Thanks – danza Mar 18 '13 at 11:30
0

First, you can bypass shim You don't need it to return anything for plain-JS. Just use globals.

Loading Angular from CDN via RequireJS is not injected

Second, while shim is semi-useful for declaring dependencies for scripts, you can do them explicitly as well:

require(['path/to/d3.min'], function(){
    // nesting to insure d3 loads before nvd3
    require(
        [
            'path/to/mylogic' // <- AMD module
            ,'path/to/nvd3.min' // <- actually a plain JS file
        ]
        , function(mylogic /*, we ignore what nvd3 returns */){
            window.nv // is available for you
        }
    )
})
Community
  • 1
  • 1
ddotsenko
  • 4,926
  • 25
  • 24
  • I had some problems with globals. Is it possible that normal globals are hidden, and it is necessary to access them into `window`? Maybe this is just basic javascript knowledge, i expected `d3` to be on the global scope but the requiring modules cannot access it. Your answer is interesting. The most interesting part is the nesting trick. Why should this work better than a `shim` dependency? Are not shims intended exactly for this purpose? So i would expect them to use either this same logic within the `require` source code, or a better one. Why should one try to bake his own solution? – danza Mar 08 '13 at 11:04
  • `shim` vs. nested `require` - you trade flexibility in building parts. RequireJS config is one for the whole app. When you just use nested `define/require` calls, especially if they use relative resources you can reuse the component in any AMD set up without needing to alter config. In the end, it's just a matter of taste, but my taste tells me to stay the hell away from turning config into large data tree. – ddotsenko Mar 12 '13 at 05:00
  • thanks, your answer is definitively useful, but i would need someone who has some direct experience with nvd3 and d3 on require, because i need to understand better what's going wrong. i mean even if i'm importing their symbols this should not lead to any conflict, as long as the shim is configured correctly. anyway, let's wait, probably your answer will be the best – danza Mar 12 '13 at 10:05
  • i tried to implement your solution (`ddotsenko` branch on the test case repository above), but it did not fixed the problem – danza Mar 12 '13 at 15:53
  • i appreciate your effort, but the fiddle does not prove fixing this problem. this is a problem with nvd3 animations, the github repository shows how to reproduce the error – danza Mar 15 '13 at 19:35
0

Look at what I do in this main.js file (using "depend" requirejs plugin) and then in other files that require something that should be exported to a global variable I do:


    define(['d3'], function (d3) {
        // Code here ...
    });

The depend plugin is really nice and allows you to setup hierarchical loading via depend!plugin[dependancy1, dependancy2] ("plugin" loads after "dependancy1" and "dependancy2" have loaded.

elydelacruz
  • 145
  • 5
  • thanks, but for this purpose i would prefer the ddotsenko approach or the shim, since they allow to not specify the dependencies each time you are defining a module! – danza Mar 12 '13 at 15:55
  • tryed (`require("depend!nvd3[d3]");`), not fixing the problem – danza Mar 15 '13 at 19:44
  • You have to download and include the depend plugin. See https://github.com/jrburke/requirejs/wiki/Plugins#wiki-script – elydelacruz Mar 20 '13 at 16:15
  • Also you should include these in the define like so: – elydelacruz Mar 20 '13 at 16:15
  • define(['depend!nvd3[d3]'], function (nvd3) { – elydelacruz Mar 20 '13 at 16:16
  • this is what i did, and it did not fixed the problem. why are you writing a new comment for each line? you can include a newline hitting Ctrl+Enter. This will not appear on the comment but i prefer a less formatted comment rather that receiving three notifications for the same content. Anyway, the solution is up there. this was not related to `require`, but to `nvd3` incompatibilty – danza Mar 22 '13 at 15:49
  • Ok, thanks for Ctrl+Enter tip, and my fault but if the solution is already there rate it then! Lol! – elydelacruz Mar 24 '13 at 01:04
  • there is already the green mark on the left, that means that i choosed it as the solution ... anyway ... rated! :) – danza Mar 26 '13 at 17:42