Dynamic Toolbar

Creating a Dynamic Menu

Very often toolbars need to display dynamic content in menus. In most cases the contents of the menu are determined by the response of a server. This tutorial will take you through two different approaches to achieve that.

Approach A

The first approach is the longest but it will also give you greater control over the process. It goes through the following steps:

1.  Get a fresh copy of the server data, if needed;
2.  Hook the “popupshowing” event for the dynamic menu; and
3.  On “popupshowing” clear the contents of the menu, go through the local copy of the server data and insert the corresponding elements in the menu.

The first thing you will need is the menu. You can create one like this inside the toolbarbutton XML:

<toolbarbutton label="Menu Test" type="menu">
<menupopup onpopupshowing="mytoolbar.testMenuShowing(this)">
</menupopup>
</toolbarbutton>

The first node is a toolbar button that will contain the menu. The menupopup node inside is the actual menu we will build dynamically. As you can see, it has no contents.
The “onpopupshowing” inline handler is set to call a function in your toolbar namespace:

mytoolbar.testMenuShowing = function(event) {
// Add event handler data here.
}

This function will be called every time the menu is about to show. The “event” parameter contains the Event object for the event that just occurred. Among other values, this object will contain a reference to the menupopup object that is about to show.

Before filling up the event handler function, we need a place to store a local copy of the data that comes from the server. It is usually a good idea to pre-fetch it, so the user will not have to wait when the menu is being displayed. To this extent we will create an array property inside the toolbar’s namespace:

mytoolbar.testMenuData = new Array();

We also need a way to actually retrieve this data. Let’s assume the data will be an array of strings formatted in JSON and it can be obtained by making an HTTP request. One simple way to fetch it would be:

mytoolbar.fetchTestMenuData = function() {
mytoolbar.framework.download(
"http://www.mydomain.com/myfeed.json",
function(url, code, response) {
if (code == 200) {
mytoolbar.testMenuData = eval(response);
mytoolbar.rebuildTestMenu = true;
}
});
}

Here we have added a new function named “fetchTestMenuData()”. You can call this function any time you need to refresh the contents of your local data cache.

The function uses a call to the “download()” function in the framework. This function will make an asynchronous request to the server. The URL is the first parameter. The second parameter is a function that will be called once the request is complete. The “code” parameter is the HTTP response code returned by the server. In this case, we only check for “200”, which means success. The last parameter, “response”, is the actual contents of the feed, in this case it would be the array of strings in JSON. By doing an “eval” and assigning the resulting array to the local copy we have. The last step is to set a flag that signals there is new information. This way we will know the contents of the dynamic menu have to be rebuilt.

At this point we can go back to the “popupshowing” event handler function, where we will fill the contents of the menu. The finished function would look like this:

mytoolbar.testMenuShowing = function(event) {
if (!mytoolbar.rebuildTestMenu)
return;
var menu = event.target;
menu.removeAll();

var data = mytoolbar.testMenuData;
for (var i = 0; i < data.length; i++) {
var item = mytoolbar.framework.createElement("menuitem");
item.setAttribute("label", data[i]);
menu.appendChild(item);
}
mytoolbar.rebuildTestMenu = false;
}

Let’s look in more detail at this function. First, it will see if the menu needs to be rebuilt. If not, the function exits immediately.

If there is new data, the menu is cleared. This is achieved by calling the “removeAll()” method on the menu. Also note how the menu object was retrieved from the “target” property in the event.

Next, the function does a loop on the data array. For every string in the array a new element will be created. The “createElement()” function of the framework is used for that. The type of the element being created is “menuitem”.

For each new item, the “label” attribute is set to the corresponding string in the data array. The “label” attribute determines the text the menu item will show on screen.
Then the item is inserted into the menu by calling the “appendChild()” function.

Once the loop finishes, the flag that signals there was new data is set to false. It will remain like this until “fetchTestMenuData()” is called again.

Approach B

The second approach takes advantage of a prebuilt functionality in all DTX elements. It turns out that the contents of any element (like the menu) can be defined by an XSL transform. A dynamic menu could be easily built by providing an XML feed and an XSL file to the menu element:

<toolbarbutton label="Menu Test" type="menu">
<menupopup
feed="http://www.mydomain.com/myfeed.xml"
cachefile="myfeed.xml"
templateinterval="60"
template="content\\mymenu.xsl">
</menupopup>
</toolbarbutton>
If the XSL template is defined like this:
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet version="1.0">
<xsl:output method="xml" />
<xsl:template match="/">
<menupopup>
<xsl:for-each select="node()/*">
<menuitem label="{@name}" />
</xsl:for-each>
</menupopup>
</xsl:template>
</xsl:stylesheet>

We will end up with a menu that contains an item for every node in the XML feed. The node’s name attribute will be used as the label for the menu item.

The XSL file needs to be local. The XML feed, which can be either local or remote, will be fetched asynchronously by the toolbar. As soon as the results arrive, the feed is transformed and the element is automatically rebuilt.

If you are interested in this powerful feature, you should also look into the “cachefile” and “templateinterval” attributes found in any DTX element. They can be used to control how often the toolbar will be hitting the server for an updated feed.

 
Dynamic Toolbar Home | Privacy | Contact Us©2010 Visicom Media Inc. All rights reserved.