APEX & JavaScript, the modular way

On the 28th of July, I presented this topic at Kscope16. It was a great conference and if you ever have the chance to visit, definitely do so.

This approach is useful when you have to deal with a lot of JavaScript code in your application. The main goal is to create reusable components, which help you to speed up development and keep things nice and tidy. Why?

  • Hide implementation details of external JavaScript libraries/ plugins
  • Single point of definition for all code
  • Reuse same components in other projects/ applications
  • Easier to understand for colleagues and future developers

Please visit https://github.com/mennooo/apex-modular-js to explore my demo project. I will explain the purpose below.

Using JavaScript in APEX

Say we want to send a message to the client using JavaScript when a button is pressed. APEX does not yet (5.0) give us an easy way to do this. I’ve found a nice external plugin called pNotify, which fulfils all my needs.

The easiest way to go is loading the JavaScript and CSS files on my page and paste the code to trigger the popup message in a dynamic action that’s fires on a button click. But there are a few things I don’t like about this approach:

  • This is not much effort for one page, but doing this over and over again is a waste of time.
  • Colleagues need to know all these steps too
  • Global namespace pollution
  • If I would like to use another plugin in the future, I must change all of my pages.

Let me explain global namespace pollution first. If I load the pNotify JavaScript file on my page, it will add a PNotify function to the window object. In fact, every JavaScript object (in this case a function) will be added to the window object if you declare it outside a JavaScript function. This way it’s available anywhere I use JavaScript: on page level, template level, dynamic actions, plugins and external JavaScript files. I just add this piece of code:

new PNotify({
    title: 'Regular Notice',
    text: 'Check me out! I\'m a notice.'
});

The downside is that the object name PNotify may conflict with another variable, which might be used by another library. In case of PNotify the chances of this happening would be rare. But think about the $ variable which is a shortcut for jQuery. The $ variable is also used for example by prototype.jszepto.js and mootools.

That is a reason why APEX gives us the possibility to use apex.jQuery instead.

Another downside is that using PNotify as a function name is not that self explanatory as for instance:

message.info({
    title: 'Regular Notice',
    text: 'Check me out! I\'m a notice.'
});

Now the chances are much bigger that my colleagues and future developers who will work on the same project will know what this function does.

Moving to a modular approach

Knowing all these downsides to the simple approach, let’s see how we can improve things. This is how I would like things to look:

  • kscope.message.info
  • kscope.message.error
  • kscope.message.warning
  • kscope.message.success
  • etc..

In this example kscope is my namespace, message is my module and the rest are public module functions. Inside my message module, PNotify may still be used, but it’s not exposed to the public.

I have added only one object to the global namespace. All my modules will be placed under the kscope namespace. It eliminates almost every chance of conflicts with other libraries.

Secondly I may change my message module by using a different plugin instead of pNotify without changing any line of code where the module is actually used.

It is similar to how the APEX JavaScript API is build up:

  • apex.server.plugin
  • apex.server.proces
  • apex.util.escapeCSS
  • apex.util.escapeHTML
  • etc..

In the sample project, there are two kinds of reusable JavaScript components: modules and widgets. The difference is that a widget is bound to an HTML element; it improves it into something more sophisticated. APEX uses a lot of widget, for instance the Interactive Report widget and a menu widget. A module is not bound to an element but executes some code. For example the apex.server module.

Structuring module development

I like to build my modules in separate files. This gives my colleagues and me a clear overview of which modules are available. It’s also a lot easier working in smaller files to find possible bugs.

I want to reuse my modules in other applications too. In one application I might need two modules, in another one maybe ten. Therefore there must be a repository of available modules.

This is where things get a bit more complicated.

What we need to manage module development is a Node.js project. Node.js allows you to use JavaScript as a programming language outside the browser.

We need it for a few tasks:

  1. Import external JavaScript plugins like pNotify in our modules
  2. Bundle all required modules per application into one file to load in our APEX pages
  3. Upload these bundled module files to our webserver (not included in sample project)

It won’t explain all steps in order to create the Node.js project in this blogpost. I’ve created a project on GitHub that you can download and install. All information to install, configure and use it is described there:

https://github.com/mennooo/apex-modular-js

Let’s hope this may help you out!

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

About Menno Hoogendijk

Oracle Apex Developer @iAdvise