If you have decided to capitalize on VMware's Open Source email and collaboration software, Zimbra Collaboration Suite 6.0, you might be struggling a bit to find in-depth tutorials on Zimlet development that give you the information you need to take advantage of Zimbra's rich AJAX web interface. This is normal with any new software release, particularly with a platform that supports a complex and rich API for plug-in and app development. To help make the power of the ZCS 6 API available to the general development community, we'll be enhancing some of the basic tutorials and providing more advanced knowledge of some of the common features you will want to implement in one of your Zimlets. This article will focus on creating a Tab Applications that provides real world functionality in the Main Content, Toolbar, and Overview areas.

If you are new to Zimlet Development or have absolutely no idea what Zimbra is, we recommend visiting the <a href="http://www.zimbra.com/about/" target="_blank">VMWare Zimbra website</a> and reading the <a href="http://wiki.zimbra.com/index.php?title=ZCS_6.0:Zimlet_Developers_Guide:Introduction" target="_blank">ZCS 6.0 Developers Guide</a> before reading the tutorial. A good starter guide on the basic's of a Tab Application can be found at <a href="http://blog.zimbra.com/blog/archives/2010/01/adding-tab-applications-to-the-zimbra-web-client.html" target="_blank">Adding Tab Applications to the Zimbra Web Client</a> While we will be briefly going over some of the basics, we are going to assume that you have a basic understanding of Zimlet development, the structure of a Zimlet package and an in-depth understanding of JavaScript, HTML, XML and CSS.

To illustrate a real world example, we'll be using code segments from one of our Zimlets, built for the purpose of displaying the weekly schedules of our engineers and technical consultants. The names have been changed to protect the innocent
<h2>Zimbra Definition File</h2>
The first step in defining your Zimlet Definition File, an XML file that defines the core behavior of the Zimlet and the resources included in the Zimlet package. If you wanted to implement your Zimlet as a content or panel Zimlet or create context menus, you would do so with XML elements in your Zimlet Definition File. The concept of the file is very similar to an Android Manifest file for any Droid developers out there. A complete reference of the file's structure can be found at <a href="http://wiki.zimbra.com/wiki/ZCS_6.0:Zimlet_Developers_Guide:Zimlet_Definition_File_Reference" target="_blank">Zimlet Definition File Reference</a>.

With a Tab application, implementation is done in the JavaScript code itself and thus, we only need to list our files and resources that are in the Zimlet package in our definition file
<pre>&lt;zimlet name="com_schedule_example" version="1.3" description="Example of a Schedule Zimlet"&gt;
    &lt;include&gt;com_schedule_example.js&lt;/include&gt;
    &lt;includeCSS&gt;master.css&lt;/includeCSS&gt;
    &lt;handlerObject&gt;com_schedule_example_HandlerObject&lt;/handlerObject&gt;
    &lt;resource&gt;logo.png&lt;/resource&gt;
&lt;/zimlet&gt;</pre>
A few notes about our definition file...
<ul>
	<li>The name attribute is the unique name of the Zimlet. Zimbra follows the same naming convention as Java does for it's packages. Your final zip file and the definition file itself will both share this name.</li>
	<li>Version is the version of the Zimlet itself.</li>
	<li>Description will show up on the Preferences-&gt;Zimlets tab after the Zimlet has been installed</li>
	<li>com_schedule_example.js is our main Javascript file where the bulk of our Zimlet's logic is defined. You are free to break apart your source code into multiple files, each of which can be defined with their own &lt;include&gt; element. We can't confirm the order in which these JavaScript files are loaded at runtime, but operating off the assumption that it's done in the order of the elements has caused no problems in any of our Zimlets.</li>
	<li>The handlerObject is the "main" function of the Zimlet and is a JavaScript class where all the Zimlet's life-cycle events are implemented. It is contained in com_schedule_example.js</li>
	<li>Resource elements define any external files needed in your Zimlet (images, plain text, binaries, etc).</li>
</ul>
<h2>Zimbra Configuration File</h2>
The Zimlet Configuration File, config_template.xml, defines specific global and host properties that affect the operation of your Zimlet. For the purposes of this tutorial, we don't need any special configuration settings, so we will not be providing any example code, but this is, none the less, a very important file. A complete reference of the structure of the file can be found at <a href="http://wiki.zimbra.com/wiki/ZCS_6.0:Zimlet_Developers_Guide:Zimlet_Configuration_File_Reference" target="_blank">Zimlet Configuration File Reference</a>
<h2>Creating the Handler Object</h2>
As mentioned previously, the HandlerObject is where all the Zimlet life-cycle events are defined along with their corresponding logic. To create our HandlerObject, we open up our com_schedule_example.js file and implement a class using the same name defined in our definition file.
<pre>function com_schedule_example_HandlerObject() {

}</pre>
This class's subclass will be ZmZimletBase so we have access to all the API methods.
<pre>com_schedule_example_HandlerObject.prototype = new ZmZimletBase();
com_schedule_example_HandlerObject.prototype.constructor = com_schedule_example_HandlerObject;</pre>
Now that we have defined our HandlerObject, we need to implement the three main events of a Zimlet's lifecycle: init, appLaunch, and appActive.
<h2>Event: init</h2>
The init function is the equivalent to the OnCreate event in other platforms and is triggered once during loading of the Zimbra Desktop. This method is where we create our Tab Application via the createApp method. We store the app name returned by the method as a class property for access later on.
<pre>com_schedule_example_HandlerObject.prototype.init =
        function() {
            this._AppName = this.createApp("Schedule", "tabIcon", "Display the Engineer and Technical Consulting schedules");
        };</pre>
A few notes about the arguments of createApp....
<ul>
	<li>The first argument is the name that will appear in the tab for the application</li>
	<li>The second argument is the CSS Class that will define the icon in our tab. "Img" will be prefixed to the CSS Class at runtime so the actual CSS Class will be "ImgtabIcon".</li>
	<li>The final argument defines the message displayed in the tool-tip when you hover over the tab itself.</li>
</ul>
We'll also take a moment to define our "tabIcon" class in our master.css stylesheet to wrap this up...
<pre>.ImgtabIcon { background: url("logo.png") no-repeat 0 0; width: 16px; height: 16px; overflow: hidden; }</pre>
...so we get a nice professional looking tab...

<a href="http://egroup.jasonmangone.com/wp-content/uploads/2011/12/blog_11.png"><img class="aligncenter size-full wp-image-5576" src="http://egroup.jasonmangone.com/wp-content/uploads/2011/12/blog_11.png" alt="Example of Tab" width="569" height="38" /></a>
<p style="text-align: center">Figure 1: Example of a Tab</p>

<h2>Event: appLaunch</h2>
The appLaunch event is similar to the OnLoad event in other platforms and is triggered the first time the Tab application is clicked. The event arg, appName, informs the method which Zimlet is triggering the event. We use it in a switch statement to call our logic for only our Zimlet.
<pre>com_schedule_example_HandlerObject.prototype.appLaunch =
        function(appName) {
            switch (appName) {
                    case this._AppName: {
                            this._createMainContent();
                            this._createToolbarContent();
                            this._createOverviewContent();
                    }
            }
        };</pre>
Inside our case statement, we call three method, each responsible for creating the content for a different part of the anatomy of a Zimlet.
<p style="text-align: center"><a href="http://egroup.jasonmangone.com/wp-content/uploads/2011/12/zimlet-tab-anatomy.png"><img class="size-full wp-image-5575 aligncenter" src="http://egroup.jasonmangone.com/wp-content/uploads/2011/12/zimlet-tab-anatomy.png" alt="Anatomy of a Tab Application" width="784" height="496" /></a></p>
<p style="text-align: center">Figure 2: Anatomy of a Tab Application</p>
Detailed explanation of the methods will be provided later.
<h2>Event: appActive</h2>
The appActive event is a combination of OnPause and OnStart events in other platforms. It is triggered both when the tab for the application is selected and unselected. Like appLaunch, it receives the app name as an event arg, but also a boolean value which informs us of whether or not the Zimlet is active.
<pre>com_schedule_example_HandlerObject.prototype.appActive =
        function(appName, active) {

            switch (appName) {
                case this._simpleAppName: {

                    if (active)
                        this._createMainContent();

                break;
                }
            }
        };</pre>
In our Zimlet, the main content is retreived via a web service, so every time the Zimlet is activated, we want to call the web service and refresh the content. To do this, we check to ensure the Zimlet calling the event is our own and than check to see if the Zimlet is active. If it is, we recreate the main content using our createMainContent method.
<h2>Creating the Main Content</h2>
Creating our Main Content is relatively simple. We get the ZmZimletApp object for our Zimlet and call the setContent method with a string of HTML as an argument. In the context of our Scheduling app, we make a call to a SOAP client that returns a string of HTML representing the schedule. For the sake of brevity, we won't go into the details of the SOAP client, but you have our personal assurance that it works!
<pre>com_schedule_example.prototype._createMainContent =
        function() {
            var app = appCtxt.getApp(globalAppName);
            var html = this._callSOAPClient();
            app.setContent(html);
        }</pre>
<h2>Creating Buttons in the ToolBar</h2>
Now, it's time to add Buttons to our ToolBar and things will get a bit more complicated. The logic for accomplishing this will be defined in our createToolbarcontent method that we called during appLaunch. Unlike the dynamic content of the Main Content area, the Toolbar buttons will be static and unchanging for the duration of the Zimlet's life-cycle and do not need to be called during appActive.
<pre>com_schedule_example.prototype._createToolbarContent =
        function() {

        }</pre>
The step in creating buttons in our Toolbar is to get the ZmZimletApp object and the ZmToolBar object itself from ZmZimletApp.
<pre>var app = appCtxt.getApp(appName);
var toolbar = app.getToolbar();</pre>
For the context of our scheduling Zimlet, we need two buttons, one that changes the date range for the schedule to a previous 3 week period and another that changes it to the next 3 weeks. To begin we will, create the previous button.
<pre>var prev_button_params = {
     id: 'com_egroup_schedule_prev',
     text: 'Prev 3 Weeks',
     image: 'leftArrowIcon',
     tooltip: 'View the Schedule for the next 3 weeks.'
}

var prev_button = toolbar.createButton(prev_button_params, prev_button_params);</pre>
First, we define a hash of our parameters for the buttons. We are using a few basic ones. A detailed list can be found at <a href="http://files.zimbra.com/docs/zimlet/zcs/7.1.2/jsdocs/symbols/ZmToolBar.html#createButton" target="_blank">ZmToolBar. </a>A few notes about this...
<ul>
	<li>ID is an unique identifier for retrieving the button object via the API</li>
	<li>Text is the display text of the button</li>
	<li>Image is the CSS Class which defines the icon, identical to the tabIcon class we created for our App. "Img" is also prefixed to these CSS Classes, making the actual class name at runtime ImgleftArrowIcon</li>
	<li>Tooltip is the message displayed when hovering the button.</li>
</ul>
The params must be supplied as an argument twice to the createButton method. We don't fully understand the reasoning behind this or if their is any distinction between the two param arguments. What we can tell you is that omitting one of the arguments will cause a runtime error and including the same set of params as both arguments successfully creates a working button.

Now, that we have our button created, we need to add a listener event so something magical happens when it is pressed. This is done via assignment of an AjxListener object

<pre> var prev_button_listener = new AjxListener(this, this._eventPrevThreeWeeks);
prev_button.addSelectionListener(prev_button_listener):</pre>
The first argument in the AjxListener consructor determines which object will call the provided method. In this case, it is the HandlerObject. The second argument is the actual method that is called when the listener is triggered. In our example, it's a custom method called eventPrevThreeWeeks. Finally, we call addSelectionListener so the AjxListener is called when the button is selected.
<pre>com_schedule_example.prototype._eventPrevThreeWeeks=
        function() {
             // Normally, this event would make an SOAPClient call to update our Main Content area with a new schedule that represented the previous three week
             // period, but for the sake of staying on topic, we've removed that code.
        }
