Skip to main content

Creating Twitter Bootstrap Widgets - Part IIIA - Using Dojo To Bring It Together


Creating Twitter Bootstrap Widgets - Part I - Anatomy of a Widget
Creating Twitter Bootstrap Widgets - Part II - Let's Assemble
Creating Twitter Bootstrap Widgets - Part IIIA - Using Dojo To Bring It Together

Note:  With a customer deadline coming up and with all the work that MWLUG 2013 requires, I haven't had the time to devote to writing this series.  So I took most of today to complete this part. As I was writing this part of the series, I realized that I should talk about creating widgets using Dojo in general. So I split this part into part A and B because it was getting way too long.

Welcome to part three of my five part series "Creating Twitter Bootstrap Widgets". In the first two parts, we talked about how Bootstrap widgets can be assembled using a consistent framework of standard HTML elements with CSS3 styling.  In part three, we will connect together our combo box widget using Dojo and make it functional.  

As XPages developer you should be familiar with Dojo as the underlining Javascript library.  XPages widgets are mostly Dojo widgets, Dijits.  To create a dojo widget we should be familiar with dojo.declare and dijit._Widget ( dijit._widgetBase for 1.7 or higher).  If you are familiar with these two features of Dojo, then you should wait for Part IIIB which I will publish next week.  

dojo.declare
Since JavaScript does not support a Class system Dojo simulates an object oriented class structure using dojo.declare which we will use to create our Bootstrap combo box widget.  In my opinion, this is one major reason to use Dojo which goes beyond the standard JavaScript Prototype.  With dojo.declare you can creating superclasses that other classes can inherit and use. Remember that I mentioned that Bootstrap widgets are like the RISC of widgets. With dojo.declare you can look at a Bootstrap widget as a collection of simpler widgets each with it only superclass.  Therefore in reflecting with the RISC approach, we want to create a number of reusable core superclasses that we can use to create our combo box widget.  For more information about using dojo.declare go to: http://dojotoolkit.org/reference-guide/1.6/dojo/declare.html.


dijit._Widget
The other important class of Dojo that we need to understand in creating our Bootstrap widget is dijit._Widget.  It handles the widget lifecycle from creation, startup to destruction.  In addition, it handles the registration of the widget and make it available to be reference in our code.  So if our widget has the id  of "myWidget", we can reference it after it has been instantiated using dijit.byId('myWidget'). I attempted to create my own widget registration classes so that I would not need to include all the overhead of dijit._Widget, but that experiment turned into a complex mess and I went back to dijit._Widget.  Maybe in the future I will try again.  I just do not like loading extra stuff if I do not need it.  A widget lifecycle includes:

Creation and Start Up:
  • constructor()
  • postscript()
  • create()
  • postMixinProperties()
  • buildRendering()
  • postCreate()
  • startup()
Destruction:
  • destroy();
  • destroyDescendants();
  • destroyRecursive();
  • destroyRendering();
  • uninitialize();
When creating your own Bootstrap widgets, the most important dijit methods are constructor, postCreate and startup.  Majority of the time when I create my own widgets, I just use postCreate. 

The skeleton HTML of our combo box Bootstrap widget is:

<div class="input-append dropdown">
 <input type="text" class="input">
 <button class="btn" type="button">
  <span class="caret"></span>
 </button>
 <ul class="dropdown-menu">
 </ul>
</div>
Note: I changed the DOM node as described in part II.  I changed the class "span3" of the input to "input-medium' and remove the class "span3" from the ul tag which provide the same alignment with less code.  

One important part of the widget life cycle is to define the HTML DOM of the widget. This is done in the life cycle "buildRendering."  You can define our Bootstrap widget skeleton DOM HTML in the widget js file, in a HTML template, or directly as part of page HTML DOM.  

Dojo provides a helper class , dijit._Templated, that allows you to define a key variable "templateString" as the DOM representative of the widget.  You can defined it directly


templateString = '<div class="input-append dropdown"><input type="text" class="input-medium"><button class="btn" type="button"><span class="caret"></span></button><ul class="dropdown-menu"></ul></div>';
or from a template file that you have as part of your file structure.
templateString: dojo.cache("myNameSpace", "templates/combobox.html")

By using the dijit._Templated, dijit._Widget will automatically use the templateString in the buildRendering() cycle for the widget.

If you are using a HTML template to define the templateString, you will also need to use dojo.provide to tell Dojo where the HTML template and js file are located. In addition to using a templateString to define the structure of our widget you can also define the widget DOM directly in the buildRendering() method or just have the complete widget DOM reference in the HTML page itself and get a handle the widget DOM node.

Creating the Bootstrap Combo Box Widget Classes

That all said, I like having the complete widget DOM skeleton as part of the HTML DOM so when the page loads there is no additional overhead of loading the dijit._Templated superclass.  Our iPhora Application Designer engine automatically places the complete Bootstrap widget DOM skeleton into the HTML DOM of the page.   Also in our case, we do not declaratively create the widget, so there is no need to perform a buildRendering. 

Since we will be using dijit._Widget to build our widget, we need to use dojo.require('dijit._Widget') to load the superclass when we load the page.  

In creating our combo box, Dojo will need to:
  • Get a data source that will define the dropdown list
  • Build the list nodes inside our UL dropdown node from a data source
  • Connect the different sub nodes to different events that can happen
  • Define setters and getters to our widget so that we can interact with the widget

There are several events that we expect to happen in a combo box:
  • Click on dropdown button to open or close the dropdown menu
  • Click somewhere else in the body to close the dropdown menu when the dropdown menu is opened.
  • Click on the dropdown menu to select the value and close the dropdown menu
  • Click on the input field to open and close the dropdown menu.

In order to have the widget understand the different events, you will need to define in your widget skeleton  the events for different parts of widget DOM using dojoAttachEvent.  When you are creating your widget class using dojo.declare, you need to define each event handle as a private method, for example _onSelectDropDown within your widget class.

dojo.declare('myComboBox',[dijit._Widget,dijit._Templated],{
    .
    .
    .
    _onSelectDropDown:function(){
       .
       .
       .
    }
});



In our case it will be dojoAttachEvent="onClick:_onSelectDropDown".  So our widget HTML DOM skeleton will look like:

<div class="input-append dropdown">
<input type="text" class="input" dojoAttachEvent="onClick:_onToggleDropDown">
<button class="btn" type="button" dojoAttachEvent="onClick:_onToggleDropDown">
<span class="caret"></span>
</button>
<ul class="dropdown-menu" dojoAttachEvent="onClick:_onSelectDropDown">
</ul>


Adding dojoAttachEvent in the widget DOM for events is consider best practice, but Richard never follows what is considered the normal anyway.  I prefer to use dojo.connect or in the case of dojo.declare, this.connect.  Why, since we are programmatically creating the widgets (because it is slightly faster) rather than declaratively, we are not using dojo.parse .  For a good discussion about best practices in creating custom Dijits go to this series:

http://dojotipsntricks.com/2011/04/23/custom-dijit-best-practises-part-1/
http://dojotipsntricks.com/2011/04/23/custom-dijit-best-practises-part-2/


Our combo box widget can be split up into three core widgets that can be reused. Therefore, we will first create a three superclasses using dojo.declare that we can reuse with other widgets in the future along with our combo box widget class:
  • Input Class called 'demoInput'
  • List Class called 'demoList'
  • Dropdown Class called 'demoDropDown'

Next time, we will go through the creation of each the classes and add them as superclasses to our combo box class to complete our widget class and demo it using our newly created classes.

Comments

Popular posts from this blog

Creating Twitter Bootstrap Widgets - Part II - Let's Assemble

Creating Twitter Bootstrap Widgets - Part I - Anatomy of a Widget Creating Twitter Bootstrap Widgets - Part II - Let's Assemble Creating Twitter Bootstrap Widgets - Part IIIA - Using Dojo To Bring It Together This is two part of my five part series "Creating Twitter Bootstrap Widgets".   As I mentioned in part one of this series, Twitter Bootstrap widgets are built from a collection standard HTML elements, styled, and programmed to function as a single unit. The goal of this series is to teach you how to create a Bootstrap widget that utilizes the Bootstrap CSS and Dojo. The use of Dojo with Bootstrap is very limited with the exception of Kevin Armstrong who did an incredible job with his Dojo Bootstrap, http://dojobootstrap.com. Our example is a combo box that we are building to replace the standard Bootstrap combo box. In part one, we built a widget that looks like a combo box but did not have a drop down menu associated with it to allow the user to make a select

The iPhora Journey - Part 8 - Flow-based Programming

After my last post in this series -- way back in September 2022, several things happened that prevented any further installments. First came CollabSphere 2022 and then CollabSphere 2023, and organizing international conferences can easily consume all of one's spare time. Throughout this same time period, our product development efforts continued at full speed and are just now coming to fruition, which means it is finally time to continue our blog series. So let's get started... As developers, most of us create applications through the conscious act of programming, either procedural, as many of us old-timers grew up with, or object-oriented, which we grudgingly had to admit was better. This is true whether we are using Java, LotusScript, C++ or Rust on Domino. (By the way, does anyone remember Pascal? When I was in school, I remember being told it was the language of the future, but for some reason it didn't seem to survive past the MTV era).  But in the last decade, there a

The iPhora Journey - Part 4 - JSON is King - The How

  The iPhora Journey - Part 1 - Reimagining Domino The iPhora Journey - Part 2 - Domino, the Little Engine that Could The iPhora Journey - Part 3 - Creating an Integrated UI Framework The iPhora Journey - Part 4 - JSON is King - The Why The iPhora Journey - Part 4 - JSON is King - The How As we mentioned yesterday, in reimagining Domino, we wanted Domino to be a modern web application server, one that utilized a JSON-based NoSQL database and be more secure compared to other JSON-based NoSQL platforms. A Domino document existing within a Domino database is the foundational data record used in iPhora, just as it is with traditional Domino applications. But instead of just storing data into individual fields, we wanted to store and process the JSON in a Domino document.  However, text fields (AKA summary fields) in Domino documents are limited to only 64 KBytes, and that is a serious limitation. 64 KBytes of JSON data does not even touch what the real world typically transfers back and fo