devxlogo

Putting a YUI Face on a Java Web Application

Putting a YUI Face on a Java Web Application

uilding on my previous article Yahoo’s Rich web UIs for Java Developers, which discussed how to use various Yahoo User Interface (YUI) web components for setup and design, this article walks through using YUI to develop a real world application. During the course of the implementation, you will learn how to:

  • Lay out the components
  • Use standard form elements
  • Handle events
  • Understand the YUI DataTable component

The next and final article in this YUI series will cover interacting with the server as well as the YUI DataTable component in detail.

About the Application

The application provides a web interface for storing confidential data such as bank accounts and login credentials for web sites. It also has options for tracking birthdays and appointments. This walkthrough explains how to implement the bank and web site credentials storage. The other two features are left for you to implement. Figure 1 and Figure 2 give an idea of how the application looks at run time.

Pushing the bank button in the upper-left corner will bring up the section to manage bank-related data (see Figure 1). Clicking on the icons of the banks listed allows the user to view and modify details specific to the selected bank.


Figure 1. Listing and Managing Bank Credentials: In this view you can modify various attributes for a bank account, such as account number, credit card account, and ATM PIN.
 
Figure 2. Listing and Managing Web Site Credentials: In this view you can modify various attributes for a web site, such as user name, URL, and password.

The inline panel on the right side of the page displays log messages.

Design: Striking a JavaScript/HTML Balance

Developing a rich user interface (RUI) with JavaScript poses the challenge of determining how much HTML and how much JavaScript to use. Using JavaScript and AJAX for everything (starting from loading the UI elements) and no HTML would impose too many requests on the server. A better strategy would be to keep a HTML page for every feature or module and back the page with JavaScript for the RUI behavior such as animation, drag and drop, sending server requests, and handling the events from the UI elements. This is the strategy the application in this article will employ.

Layout

The screen area for the application is divided into the following four parts (see Figure 1) to achieve the desired functionality:

  • Action Area: This container holds the buttons (“Bank, ” “Web, ” “Birthdays,” and “Appointments”) for the user to choose which entry to manage.
  • Listing: This container holds the list of entries for Bank, Web, etc., depending upon the context selected.
  • Work area: This container occupies the majority of the page. It displays the complete details of the selected entry on the listing panel.
  • Console: This container displays status messages.

To get the desired layout, the HTML markup needs to be defined first. The file /index.html in the source code download for the application does that as follows:

     

The style class of the body should be set to yui-skin-sam, a default skin class provided for YUI. YUI components need this class to work properly; you can customize it to suit the needs of the application. For example, the following definition from the file /css/main.css in the demo application sets the background color of the container rendered by YUI to white:

.yui-skin-sam .yui-layout .yui-layout-unit div.yui-layout-bd {     background-color: #FFFFFF;}

The YUI Layout component is initialized to hook up to the markup defined (see Listing 1 for an example, the JavaScript class YAHOO.widget.Layout in the demo application). A number of things in the class defined in Listing 1 are worth noting:

  • The YAHOO.widget.Layout class is initialized and rendered. The position attribute is passed with a constant to indicate where to position the container. The body attribute refers to the ID of the div defined in the HTML markup.
  • A namespace, devx.yuiapp, is created and the JavaScript class Main is declared. The Main class holds references to all other JavaScript classes created and acts as the entry point class for the index.html page.
  • In the Main class constructor, the init method is registered with onDOMReady for callback. When the index.html page content becomes available, init is called. All the initialization pertaining to the index.html page, such as initializing the buttons, loading data for the current context, and so on, is done in init.
  • Within the init method, various places make references to the Main class using the this keyword. However, the init method is called in a different scope because it is a callback method. To let this refer to the Main class in the callback, the reference of the Main class is passed in the second argument and true is passed in the third argument to onDOMReady.
  • An instance of LogReader is created. This attaches a panel to the page for displaying log messages. A call to YAHOO.log would result in messages printed in this panel.
  • The instance of the Main class is created and assigned to a global variable main.

Click here for more detailed notes and examples for the YUI Layout class, but always employ the following best practices for defining a layout:

  • Use relative positioning (which refers to the CSS attribute position) when adding components or containers from top to bottom, and use absolute positioning if laying out components or containers left to right in the page. Absolute positioning requires you to define the attributes left and top.
  • Load all the page elements during initial load. This makes adding listeners to the UI elements easy. Otherwise, you need to hack around to attach listeners.
  • Link the CSS files Reset, Base, Grids, and Fonts (all part of YUI) in the page to set default style definitions for all the HTML tags. This ensures a consistent look and feel for your application across browsers.

Action Area

To add buttons to the action area panel, you need to define HTML markup and then you should hook up the YUI widget class Button instance. The files /index.html and /js/action_bar.js in the demo application do that as follows:

/index.html
/js/action_bar.jsvar hideAllListings = function () { main.banksListing.hide(); main.webListing.hide(); var bdaysListDiv = YAHOO.util.Dom.get('bdaysListDiv'); bdaysListDiv.style.visibility = "hidden"; var apptsListDiv = YAHOO.util.Dom.get('apptsListDiv'); apptsListDiv.style.visibility = "hidden";}

The demo application uses the YUI DOM class to get the reference of a div definition for hiding out-of-context listings.

var onBankButtonClick = function () {     hideAllListings();     hideAllDetails();                         // Show banks listing & details     main.banksListing.show();     main.bankDetails.show();}     this.banksBtn = new YAHOO.widget.Button("banksBtn");this.banksBtn.on("click", onBankButtonClick, null, this);

The ID of the button input element is passed in the constructor, and the callback method onBankButtonClick is added to listen for click events. Note that when calling the registered method using the scope of the ActionBar class instance, you need the third argument to the on method.

When the user clicks the Bank button, all other listings and details are hidden and the panels pertaining to Bank appear. References to other classes are obtained via the global variable main.

Bank and Web Listing

The demo application in this article uses mock data (retrieving data from the server is saved for the next article in this series). The class BankListing displays the list of persisted banks and listens for events when an entry is selected. Here’s an example from the file /js/bank_listing.js in the demo application:

devx.yuiapp.BanksListing = function() {     // Constructor}devx.yuiapp.BanksListing.prototype.init = function () {     // Test data. This will be fetched from the database     var bankData = {         banks: [             ....         ]     };          ....          this.list = new devx.yuiapp.List('Bank', bankData.banks,                          'banksListDataTableDiv', onBankSelection);     this.list.init();}

Because listing entries are common for any entity (Bank, Web, etc.), a common class devx.yuiapp.List is defined. This reusable class is instantiated for every entity type. Listing 2 provides an example, the /js/listing.js file in the demo application. YUI DataTable is used to represent a listing. Here are some other key points from Listing 2:

  • The column definition, data source definition, and container to render the table to are passed to the DataTable constructor.
  • Listeners are added to the table for highlighting or not highlighting rows when the user hovers the mouse over the table.
  • A custom formatter is written to display an image for a row instead of the URL.
  • The callback method _rowSelectEvent is registered to be invoked when the user selects an entry in the listing. This call will be delegated to the BankListing or WebListing class to open up the details pertaining to that record.

Bank and Web Details

When the user selects an entry, the listing should load details pertaining to that selection. The following code from the /js/bank_listing.js in the demo application accomplishes this for a Bank selection:

var onBankSelection = function (id) {     main.bankDetails.load(id);}

When the user makes a selection in the Bank listing, the method onRowSelection will be called back from the Listing class. The class BankDetails abstracts the data and behavior related to displaying and allowing modifications to attributes such as Bank accounts, credit card details, etc. Listing 3 shows an example, the /js/bank_details.js file from the demo application. The load method is invoked when the user selects an entry in the listing. YUI’s Element class is used to hook up to the input text fields for setting and getting values. The onblur event is registered to validate the input.

Setup and Configuration

To set up and configure the application, download the accompanying source files. You will need to edit them in an IDE using JavaScript and HTML editors. For this example, I use Aptana, an Eclipse plug-in that supports numerous AJAX libraries including YUI. However, I have found that Aptana’s autocomplete doesn’t always work for YUI.

Take the following steps to complete the setup and configuration for the demo application:

  1. Extract the accompanying source files to a folder and point to this folder while creating the Eclipse project. Remember to switch perspective to Aptana while opening the files. In order to enable autocompletion for a JavaScript class, you need to add the file in the References view (see Figure 3).
    Figure 3. Aptana IDE Configured to Work with the Source Files: The Aptana JavaScript and HTML editor is all you need to work with this application example.
  2. Create a folder js-lib/yui where the index.html file will be located. Download the YUI library and copy the build folder to js-lib/yui as well.
  3. Open the index.html file in FireFox. I did not test the demo application against IE, so you might experience some errors if you choose to use that browser.

You are better off retaining the folder structure of the YUI library. Otherwise, some features may not work as expected, especially those relating to look and feel. This is because the style definitions contain relative paths.

Debugging with Firefox and Firebug

Firebug is a very useful Firefox add-on for debugging rich client web applications. Firefox and Firebug together offer the following features:

  • Selecting a div in the HTML tab highlights the screen area in the loaded page.
  • The Console tab displays requests sent and responses received, including header information. Any error in the JavaScript execution is printed here as well.
  • Modification to CSS properties gets reflected instantly in the loaded page, greatly reducing the time you would spend getting the desired look and feel for the application.
  • You can set breakpoints for a JavaScript file and watch the values for variables.
  • You can further analyze a selected element in the HTML tab by opening DOM or Layout tabs. The Layout tab is especially useful for calculating pixels occupied by a UI element. This is important because pixels are allotted to margins and borders, in addition to the actual width and height of the element.

Tips for JavaScript and YUI Programming

Keep the following tips in mind when using JavaScript and YUI for web application development:

  • Be aware of the scope for callback methods. If the scope is incorrect, the this keyword will not reference the intended object. The YUI library event-handling classes have the ability to let you pass the object to which you set the scope. Go through the API documentation to see how this can be accomplished for a widget.
  • Use server-side includes to conditionally include screen parts. This improves the modularity of the application. The demo application renders the containers for all the entities. Instead, UI elements of other entities can be restricted from rendering based on a request parameter to the page. Alternatively, separate pages can be defined for each entity, and common HTML can be included as a file header and footer.
  • Refer to this W3C JavaScript Event Reference to learn the list of supported events.
  • If you are unfamiliar with the concept you are trying in JavaScript or a JavaScript framework, test the application for every change you make. If you fail to test and keep writing code, when an error occurs it will be difficult to backtrack and find the actual cause.
  • Be aware of how to revert a source file to a specific time using Local History in Eclipse. It’s handy to know how to revert if things go wrong.

Take the Next Step

With this article under your belt, you should have the confidence to try JavaScript programming and to use YUI for web application development. You can strengthen your understanding of the concepts presented here by downloading the attached source files and trying to implement the incomplete entities of Birthdays and Appointments. You will need to define the necessary HTML markup, create listing and details classes for these entities, and hook them up to the Main class.

The next and final installment will cover the YUI DataTable in detail and demonstrate how to make AJAX server requests.

devxblackblue

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist