Add a jQuery Plugin or Third-Party JavaScript Library to Your Site

Third-party JavaScript libraries can be a quick and effective way to fill the gap in any JS-powered application. While the SuiteCommerce Advanced includes a number of these libraries (such as jQuery, Bootstrap and Underscore), you may want to include your own third-party libraries.

This article will take you through the steps to adding your own JavaScript library, which roughly follows the same steps of creating your own module.

Note (added July 29, 2016) — for the sake of clarity, this tutorial assumes that the library you want to add is not AMD compatible. If it is AMD compatible then you do not need to follow this tutorial; instead, you can simply add it like you would any other module of code: directory structure, ns.package.json, update distro.json, etc.

Tutorial

For the purposes of this tutorial I have the use case of wanting to add a field to the Profile Information page to capture the customer's preferred delivery time for any orders they place. I have found a jQuery plugin called ClockPicker that provides a neat interface for selecting a time. For the sake of brevity, I'm not going to include the steps for storing the data on the backend as that is out of the scope of the article.

What if you're adding a JS library that isn't a jQuery plugin? At the bottom of this article, I've added additional information about this.

Folder Structure

Once you've found the library you want to add, you will need to create a module folder for it. Like all site-specific customizations, we recommend that you put them in the folder under Modules where you keep your site's customizations. When naming it, it's good to use the name of the library as the folder name and the version of the library as the version number. So, for me, I'm creating a folder called jquery-clockpicker@0.0.7.

In this folder I'm putting the files that I need for the library to work: one JavaScript file and one stylesheet file. Now, for the Sass compiling process to work I'm going to change the file extension on the CSS file provided to .scss and put an underscore (_) in front of the file name. Keep in mind that CSS is still valid Sass, so this isn't an issue, just a nuance of the compiler. Finally, the folder needs a ns.package.json file so that Gulp picks it up; thus the final list of files is simply:

  • _jquery-clockpicker.scss
  • jquery-clockpicker.js
  • ns.package.json

Then you just need to put the right things in your ns.package.json file, e.g.:

{
  "gulp": {
    "javascript": [
      "jquery-clockpicker.js"
    ],
    "sass": [
     "_jquery-clockpicker.scss"
    ]
  },
  "jshint": "false"
}

The only thing in here that you may not have seen with other modules is the "jshint": "false"; this is because one of the Gulp tasks you can run is JSHint, which is a utility that checks JavaScript for errors, and we don't need to run that on well-written third-party JS (but you can if you want).

You may ask why we haven't replicated the folder structure common to the other modules, this is mainly because the jQuery library only has two files that we want to use. We could also modify the source code so that it is in the AMD format, but the flexibility of this method means that we don't have to. One side-effect of this, however, is that we'll have to make some unconventional modifications to our distro.json file.

distro.json

First things first: you need to register your module like you would any other module at the top. This is pretty standard, I'm just adding in "custom/jquery-clockpicker": "0.0.7" to mine.

Now, normally at this point you'd go and add the JavaScript to the dependencies of each application. This time you're not going to do that. If you've spent time looking at the distro.json file, you'll notice that when it comes to jQuery plugins, we treat them a little differently: we have to use shims. If you do a search for "shim" in the file you'll see a number of other jQuery plugins that SCA uses (like jQuery Zoom and jQuery bxSlider); you essentially need to do the same for your jQuery plugin. Therefore, in each application under tasksConfig : javascript : amdConfig : shim I'm adding:

"jquery-clockpicker": {
  "deps": [
    "jQuery"
  ]
}

After that, I need to register the module's Sass as a dependency in the Sass task for each application. If you wish, you may just register them only with the applications you plan to use the library with, but if your aim is to make it available globally then it's simple to register it with them all.

In total, if I add in lines for each application, my new module will be mentioned seven times in distro.json file:

  • Once, at the top, in the modules section.
  • Once for each application when configuring amdConfig.
  • Once for each application when registering the Sass.

Save the file!

View and Template

So the final bit for me to do is to actually use the JavaScript library I've included. I want to add the functionality to my Profile Information page, so I need to complete all the standard steps for overriding a template file.

Once I've done that, I'm going to edit Profile.Information.View.js and add jquery-clockpicker as a dependency but I'm not going to add it as a parameter to the function. Why? This is because it is a jQuery plugin and we have shimmed it into jQuery (i.e., augmented jQuery with the plugin); seeing as jQuery has already been added as a parameter, we do not need to add anything more.

Now, specific to ClockPicker, is a small JavaScript snippet that needs to be run on the page the functionality appears on. This is quite common for jQuery plugins. Seeing as we must never put JavaScript into template files, we need to find a way to inject it into the page after the DOM has loaded. In the initialize function in the view we need to add something like:

var self = this;
this.on('afterViewRender', function()
{
  self.$('.clockpicker').clockpicker();
});

The code within the function is the stuff ClockPicker needs, but it is the wrapper that is most important. First, the variable allows us to keep the context of the object we're instantiating, which is the view. Secondly, the afterViewRender event is when Backbone has finished rendering the DOM; seeing as we would normally put this JavaScript at the bottom of our HTML page, this is the perfect event to use to render some arbitrary JS that manipulates the DOM.

After saving the view, the only thing left to do is to modify the template. Obviously, this part is specific to the library that you're using and there no special tips other than to read their documentation and make sure you include the appropriate data elements, classes, IDs, or any other code that is required for the library to work. I've included the code below, for reference:

<div class="profile-information-row clockpicker" data-placement="top" data-input="clockpicker">
  <label class="profile-information-label" for="clockpicker">Preferred Delivery Time</label>
  <div class="profile-information-group-form-controls">
    <input type="text" class="profile-information-input-large form-control" value="09:30" name="clockpicker">
  </div>
</div>

Note how I'm able to use my own classes and structure, just so long as I include the clockpicker class. Make sure with your choice of library that you include all the relevant parts. A good way to start is to include just the bare minimum to get the JS to work, and then build it out from there.

Test Your Code

After of all this, you will need to stop your local server (if it is already running) and start it again. When you visit the page where your library is called, you should see the changes you made take effect. If you don't, check the console and perform some diagnostics (see 5 Ways to Troubleshoot SCA in the Browser for some tips). Here's what my page looks like:

Summary

So what I've written in the tutorial is clearly not enough to implement the functionality — it's missing the entire backend. But, what we have seen is how easy it is to include a jQuery plugin. It starts similarly to other modules: you create the directory for it in your customizations directory and then add in the files, along with a ns.package.json. Then we covered the nuances of updating the distro.json file for jQuery plugins, namely using shims. Finally we updated the view to include our jQuery plugin and use afterViewRender event to run some code when the view has finished rendering.

You should be able to adapt this article's method for your own third-party JS — not just jQuery plugins but all third-party libraries. For additional help, check out what we've done with the third-party JS that we've included in the SCA product and try to replicate it.

Notes on non-jQuery JS Libraries

OK, so you've got a JS library that isn't powered by jQuery — what do you do? The method for adding it is a combination of the above steps and the steps to adding any other module to your site.

Folder Structure

The first thing you need to do is get the files, create your folder structure, and create the ns.package.json file as normal.

distro.json

Then, when updating your distro.json file, you need to do this like you normally would for a new module. Put a line in the modules object for the location of your module.

Now, if your JS library is AMD-compatible then you can add as a you would normally add any new custom module. If it's not, then you then need to find the section for the application JS that you want to add it to and add it as an entry to amdConfig > paths. As a key-value pair, this should be "[name you want to call it]": "[name of the JS file]". Note the conventions used for the other JS files, namely that you do not include the file extension (.js) in the value of the pair. So, for example, if my module is called SuperGreatLibrary, which contains a minified JS file in it called SuperGreatLibrary-1.0.2.min.js then I would add the following to paths:

"SuperGreatLibrary": "SuperGreatLibrary-1.0.2.min"

For adding any CSS, you can follow the normal steps for adding a custom module.

Using It

After saving and recompiling your code, you can now use your third-party JS library like you would any other module — find the module file that you want to use it in and add it is a dependency. If, however, you want to use it 'globally' then you will need to override a module with a wider scope and include it in that.

So, for example, if you want to have it available throughout your My Account application, override SC.MyAccount.js in MyAccountApplication and add it as a dependency there. Just pay attention, though, to the list of dependencies in the define statement and include it in the right place. In some files (including SC.MyAccount.js) the define statement will register some modules as dependencies but does not give them names; thus, if you were to add your JS library to the end of the statement, you would encounter an error as the ordering is wrong.

Further Reading