Using CodeMirror.js in another module

Im trying to use the CodeMirror js library in another module and something strange happens.

I load all the js files like in the toplevelview:

    $this->provideJsFile('vendor/codemirror/codemirror.js');

    $this->provideJsFile('vendor/codemirror/mode/yaml.js');

    $this->provideJsFile('vendor/codemirror/addon/dialog/dialog.js');
    $this->provideJsFile('vendor/codemirror/addon/search/searchcursor.js');
    $this->provideJsFile('vendor/codemirror/addon/search/search.js');
    $this->provideJsFile('vendor/codemirror/addon/search/matchesonscrollbar.js');
    $this->provideJsFile('vendor/codemirror/addon/search/jump-to-line.js');
    $this->provideJsFile('vendor/codemirror/addon/fold/foldcode.js');
    $this->provideJsFile('vendor/codemirror/addon/fold/foldgutter.js');
    $this->provideJsFile('vendor/codemirror/addon/fold/indent-fold.js');

after that I load other markups:

    $this->provideJsFile('vendor/codemirror/mode/markdown.js');
    $this->provideJsFile('vendor/codemirror/mode/xml.js');
    $this->provideJsFile('vendor/codemirror/mode/meta.js');
    $this->provideJsFile('vendor/codemirror/mode/htmlmixed.js');
    $this->provideJsFile('vendor/codemirror/mode/css.js');
    $this->provideJsFile('vendor/codemirror/mode/javascript.js');

and css:

    $this->provideCssFile('vendor/codemirror/codemirror.css');
    $this->provideCssFile('vendor/codemirror/addon/dialog/dialog.css');
    $this->provideCssFile('vendor/codemirror/addon/search/matchesonscrollbar.css');
    $this->provideCssFile('vendor/codemirror/addon/fold/foldgutter.css');

  • If the toplevelview module is enabled the CodeMirror.modes contains only the yaml markdown from the toplevelview (toplevelview has only yaml markup)

  • If I disable the toplevelview module my markups (markdown.js) work as expected.

  • If I load markdown.js without codemirror.js, even if codemirror.js gets loaded by toplevelview, the browser tells me that CodeMirror is not defined.

One workaround is putting the markdown.js and xml.js content in the rendered function of the module.js but that looks pretty dirty.

How can I achieve a coexistance of two identical javascript libraries?

Thanks in advance and

Best Regards
Nicolas

What about making toplevelview a dependency of your module?

Then you would not need to provide the identical parts.

Or, detecting that toplevelview is enabled, and only then just the stuff you need?

does the module.js magic takes care of module dependecies as well?

if I provide a file in my module named “custom” that need something provided by the module toplevelview like

 $this->provideJsFile('vendor/codemirror/mode/markdown.js');
 $this->provideJsFile('vendor/codemirror/mode/xml.js');

which requires

    $this->provideJsFile('vendor/codemirror/codemirror.js');
  

markdown.js doesnt work because it CodeMirror.js code is not loaded yet.

No.

This does: Why AMD?

As of Icinga Web v2.9 at least. Though, only a limited implementation is available.
Because of this, each third party library that needs to be integrated, must be slightly adjusted first.

You’ll find a similar line in every supported library:

typeof define === "function" && define.amd

which needs to be changed to:

typeof define === "function" && define.icinga

This manual step is required to ensure that only compatible libraries are loaded to not break the UI.

First this was implemented for libraries such as the ipl. Though, modules can also use this. However, there are still some limitations in that case but they shouldn’t affect you.

After you’ve adjusted the codemirror library, you just have to wrap your module.js inside such a wrapper:

define(["vendor/codemirror/codemirror"], codemirror => {
    // …module.js content
});

But, no guarantee. I didn’t check whether codemirror is compatible or not.