Ctools now supports Require.js – But… what about jQuery plugins?

Great news from the Pentaho Community Dashboards front. As of the current version (15.06.30), there’s support for Require.js, which greatly streamlines the javascript downloaded when rendering a dashboard, cleans up the global scope and provides a proper management of modules and dependencies. I won’t bother you with the details, you can read more about it in Pedro Alves’s post.

This is truly a game changer when it comes to developing CDF/CDE dashboards. We have to write our code better, with a proper architecture in place to make all the pieces talk to each other, we need to use the proper methods to set or get parameter values, to run custom functions in pre-execution or post-execution code snippets, etc.

This is not a bad thing, far from it. But it doesn’t come without its challenges. We’ve started playing with the new require.js framework here at Ubiquis and we’ve learned useful tricks already.

Here’s one: remember how easy it was to upload that myAwesomeJqueryPlugin that you found on some github repository and allowed you to implement that super-duper feature on your dashboard? Well, it won’t work anymore. Not without a bit of work, at least. Here’s why: your typical jQuery plugin is a function of the type

(function ($) {
// your awesome code goes here
})(jQuery);

But now it will fail. The reason is that $ is no longer defined in the global scope. It’s still exposed and you can access it as usual from within any component’s internal methods, but not when you’re loading your jQuery plugins.

So, after some reading we got to a very interesting Stack Overflow post (see , that pretty much solves the problem. We just need some tweaks on the plugin code to make it require friendly:


(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module depending on jQuery.
define(['jquery'], factory);
} else {
// No AMD. Register plugin with global jQuery object.
factory(jQuery);
}
}(function ($) {
// your awesome code goes here
})(jQuery));

(note that the whole jQuery plugin is passed as a parameter to the factory function)

And there you have it, you can continue to use all the jQuery plugins you want, which are now loaded as require.js modules.

3 Comments

  1. Andrew

    Hi,

    Loved the post but I have been struggling with a similar problem for weeks now and just cannot resolve it. I’m sure it is simple but really need your help if you could please offer me a moment of your time.

    So I am upgrading a dashboard to requireJS and I have a UI that uses a minified jquery file that comprises of three functions. It is structured like this:

    // nanoScrollerJS
    !function(a,b,c){
    ….
    }(jQuery,window,document);

    // metisMenu.js
    !function(a,b,c){

    }(jQuery,window,document);

    // main UI function that uses above two plugins
    !function(n){

    }(jQuery)

    None of these are AMD-ready.

    I have tried wrapping them in require([‘cdf/lib/jquery’], function(jQuery){ ……}) but my navigation menus just wont work. I tried wrapping the three functions in your plugin code above but had no luck with that either. I then tried using domReady like so: require([‘cdf/lib/jquery’, ‘Plugins/domReady/domReady’], function(jQuery, domReady){…}) as I thought that require was not waiting for the DOM but again no luck.

    I have a few questions for you please:

    1 – Would you wrap each of my three functions in their own AMD plugin code as you detailed above?
    2 – Would you then save them as separate files in the Pentaho repository and require them in together in one function within CDE? Or are you entering the code above directly into CDE as a code snippet?
    3 – How comes you do not use the CDF jquery ‘cdf/lib/jquery’ when using with the code above?

    Really hope that you can help me, I will be forever grateful!

    Thanks,
    Andrew

    • Nelson Sousa

      You’re getting very quickly away from the bits of jQuery and require I actually understand, so bear with me…

      1. I would try wrapping each function as a separate plugin, just because it seems easier.
      2. Yes, each function will go separately into it’s js file in the repo.
      3. Because this worked 🙂

  2. Andrew

    Thanks for getting back to me so quickly. You and me both are quickly far from the bits of jQuery and require that we understand :). I tried splitting into three js files and wrapping them in the code but keep having issues with how jQuery is defined as it doesnt recognise the n.fn function and so on.

    Will keep having a fiddle but beginning to lose hope with this one!

Leave a Reply