Friday, October 3, 2014

More Fun Creating Dojo widgets and MVC

Here is another article in my "Fun with Dojo" series.

Dojo traditionally has been considered slow.  One reason is that Dojo loads alot of modules before it instantiates the page.  Dojo with AMD helps reduce the number of modules when it first loads but not the number of modules.  This is great.  However, one thing that I really dislike are Dojo Dijit widgets.  They are heavy, slow, and require a lot of modules to be loaded.

We like the Bootstrap widgets because they are lightweight. So instead of using Dijits that are built into XPages we created our own lightweight Dojo Bootstrap widgets that utilized the most minimal amount of required Dijit modules and dependencies.

One of the things that we had to figured out was what bare bone modules that we needed beside dijit._Widget in order to create our own widgets and include them in the loading process.  When we were using Dojo 1.53, we created a custom loader with all the required modules contained in a single file.  Rather than including _TemplateMixin and _WidgetsInTemplateMixIn and other mixin modules, we did everything using our own code within the buildRendering lifecycle.  This help reduce the additional modules that was required.
<div id="happy" class="user">
 <button class="icon"><i class="fa fa-user fa-lg"></i></button>
</div>

However, this approach eliminated a very power module.  In the example above, you can get a handle to the button node of the widget by using:

var btnNode=dojo.query('button',this.domNode)[0];

or

var btnNode=dojo.query('.icon',this.domNode)[0];

For users not familar with Dojo "this.domNode" is a handle to the widget, "this" being the widget itself.  Please note that "this.domNode" does not exist until it goes through the buildRendering lifecycle.

This is how we were getting a handle since we did not need all the stuff that was in the module dijit/_TemplatedMixin since we were calling buildRendering directly.  This worked fine but this approach added more code then we wanted for the widget.

So we took another look at how we could utilize what was included with Dojo, but at the same time not load stuff that we did not need. Within _TemplatedMixin, there is a call to another core module, dijit/_AttachMixin.  This module creates attach points and events to get a handle to different parts of the widget DOM and events. So in our previous example, rather than using dojo.query all you have to do is add the attribute "data-dojo-attach-point" to the DOM fragment and run
this._attachTemplateNodes(this.domNode) during the buildRendering lifecycle.

<div id="happy" class="user">
 <button class="icon" data-dojo-attach-point="btnNode">
  <i class="fa fa-user fa-lg" ></i>
 </button>
</div>

So your widget code will be:
define("mywidgets/button",[
 "dojo/_base/declare",
 "dijit/_WidgetBase",
 "dijit/_AttachMixin",
 "dojo/dom-class"
],function(declare,_WidgetBase,_AttachMixin,domClass){
 return declare([_WidgetBase,_AttachMixin]),{
  buildRendering:function(){
   this.domNode=this.srcNodeRef;
   this._attachTemplateNodes(this.domNode);
  },
  postCreate:function(){
   this.inherited(arguments);
   domClass.add(this.btnNode,'blue');
  }
 });
});

So now we have a handle to the button node using "this.btnNode". Simple and easy. A view/controller in Dojo can just be a Dojo widget with Dojo widgets inside. Therefore you can extend the same process if you are using Dojo for your MVC framework.  This will be the topic of another future blog.

"this.srcNodeRef " is the reference to the DOM fragment on your HTML page that represents the widget.

Thursday, October 2, 2014

The Good, Bad, and Ugly about AMD in Dojo

We were testing iPhora Touch 2 with the attendees of MWLUG 2014 in the MWLUG portal and as usual, the interface had issues even after having outside users provide feedback before we rolled it out.  When you are so focused on the creation process it hard to see issues until it is seen by fresh pair of eyes.  So we are working on a new faster and improved interface for iPhora Touch. This is the evolution of any product.

Since we are using a JavaScript/JSON Restful API approach most of the changes will be on the front end and only minor changes to the back end which is great.  In theory we can swap out different interfaces with little impact on the back end.  This is where the newer AMD approach for Dojo comes into play. The use of AMD in Dojo allows us to modularize the UI components even more than what we had.  Therefore, we have been upgrading all the iPhora widgets from Dojo 1.53 to Dojo 1.10.0 and at the same time upgrading from Bootstrap 2.32 to 3.2 and the latest version of Fontawesome.  The View/Controller of the MVC framework becomes no more than a Dojo widget.  This will be the subject of upcoming blogs.

The AMD approach with Dojo has many advantages, but it also has a number of things that I do not like about it.  For example below is a simple set of code for reading a cookie and adding it to a DOM node and adding a class to a div tag using Dojo.

HTML
<div class="data-display"></div>

Dojo without AMD
dojo.require('dojo.cookie')
var c = dojo.cookie('info');
var node=dojo.query('.data-display')[0];
node.innerHTML=c;
dojo.addClass(node,'show');


Dojo with AMD it becomes
require([
 "dojo/cookie",
 "dojo/query",
 "dojo/dom-class"
],function(cookie,query,domClass){
 var c=cookie('info');
 var node=query('.data-display')[0];
 node.innerHTML=c;
 domClass.add(node,'show');
});
As you notice the amount of code for Dojo with AMD can quickly add up and if you miss a module path/declaration you get an error that won't make sense.  So you need to be careful in defining the path/declaration pair.

But like all good developers, I decided to create a new feature with my development tool to use a template to create my code.   This is where my mustache function comes in handy.  Below is an example of my code template that I have created.



As a result, all I have to do is have my compiler create the Dojo/Bootstrap widgets from the declaration tags, for example <ux:ipField id="hello"/> and assign the appropriate required modules to the assigned mustache tags and do a simple LotusScript find and replace.

However, one critical advantage of AMD is that you can create your own module and include or replace an existing module relatively easily. For example, we needed to replace the Dojo MVC JsonRest module "dojo/store/JsonRest" with our own "iphora/JsonRest" since it does not meet our requirement in how we are doing REST services. We copied the JsonRest.js code modified it and then placed into our iphora directory and now it is loading our module.

require([
 "dojo/cookie",
 "dojo/query",
 "dojo/dom-class",
 "dojo/store/JsonRest"
],function(cookie,query,domClass,jsonRest){
 var c=cookie.get('info');
 var node=query('.data-display')[0];
 node.innerHTML=c;
 domClass.add(node,'show');
});

require([
 "dojo/cookie",
 "dojo/query",
 "dojo/dom-class",
 "iphora/JsonRest"
],function(cookie,query,domClass,jsonRest){
 var c=cookie.get('info');
 var node=query('.data-display')[0];
 node.innerHTML=c;
 domClass.add(node,'show');
});

So we just point the path to our module.  No other changes in the code are required. 

Another disadvantage with the AMD module approach is that you need to be extremely careful if you are trying to create a compressed build of your own modules to reduce the number of http request during the loading process.

With Dojo without AMD, you can easily just concatenate all the modules into one single script file and load that script as part of the page instantiation process. However, Dojo with AMD requires you to create a build using an elaborate process that utilizes a package.json.  This is similar to how npm in nodejs does their builds.  More information can be found in this article.

http://dojotoolkit.org/documentation/tutorials/1.8/build/

Dojo with AMD is more powerful then ever but it just takes a little more work and can be fun!

Wednesday, October 1, 2014

Why an Ideal MVC Framework Fails

One of the "Next Big Things" these days is the use an MVC framework for developing Web applications. There are a number of MVC frameworks out there including Backbone, Ember, and the rapidly growing Angular. 

Ideally these MVC frameworks are great, hook things together and any changes to the model (data) and all the views are updated based on the controller code. If there is changes to the model, the data is automatically updated on the server. This is the ideal case.

However, it assumes one critical thing, you have the access rights to CRUD data on the server. This is an extremely dangerous assumption.

In our iPhora security model, we assume the opposite and you do not have access rights to any data on the server. We do not trust anything and any request. We assume that you are trying to hack and inject. Your authorization is checked during each request. We looked at using Angular since it is the hot stuff of the MVC world and everyone seems to be using it. We also looked briefly at Backbone. However, these required us to hack and patch the code to do what we wanted it do. As a result, it would be hard to maintain in the future when new versions of Angular or Backbone comes out.

Since we have been using Dojo for awhile, we looked at a couple of Dojo-based MVC frameworks including Dojorama and the Dojox/MVC. These two also assumes an ideal MVC approach which is not what we wanted. Also Dojox/MVC is heavy.

Most of the MVC frameworks works well for simple applications and even more complexity applications. But for our iPhora applications like iPhora Touch, within one session, the user access rights and roles will vary constantly depending of the state and application the user is accessing. 

One thing that all these MVC frameworks lack is good documentation not on how to use it but documentation regarding the core architecture and functionality. You have to go through all the code and test and sometimes it is trial and error and assumptions. What a pain.

So we decided to create our own MVC framework using Dojo. The newer AMD approach for Dojo lends itself to the MVC approach.  Dojo already has core methods to handle MVC including dojo.store, dojo.stateful, dijit.watch/unwatch, and dojo.store.observeable. Also, don't forget the powerful dojo.subscribe and dojo.publish. We used the Dojorama project as a guideline and starting point. This MVC project is a good demonstration of the power of Dojo.

So where are we? Our initial MVC architecture is completed and we have modified our development tools to handle the new MVC approach. But, we expect more changes to come as we test.  The base core code is almost complete and will be ready for a test during the next couple of days. Our existing page-based JSON Restful services API will require some minor changes that are relatively easy to make. We are half way done in updating our existing iPhora Dojo/Bootstrap widgets to Dojo 1.10/Bootstrap 3.2 with MVC-based hooks. So stay tune for more updates.

CollabSphere 2022 Presentation: COL103 Advanced Automation and Cloud Service Integration for your Notes/Nomad Applications

Our presentation for CollabSphere 2022. Learn how to quickly add workflow automation into Notes/Nomad applications using No-code tools that ...