Adding Menu Items to a Popup Object

After the XSL transformation builds a menu bar that appears in each application screen, it must populate each menu with items for the user to select. Menu items appear inside an ActiveX control, the Popup control, that appears when the user clicks the menu name. The following code fragment uses nested loops to assign a control to each menu name and populate it with items specified in <menuitem> elements in the *menu.xml file.

The code starts with a pattern match; the recursive descent operator (//) gets the values inside any elements named topmenu. Next, the <xsl:for-each> element selects any menu element that has child elements named menuitem. The code assigns a Popup control for each of these menu elements, using the <xsl:attrib> element to assign the control an ID value of topNavigator, and appending the child number, decremented by 1, to create a unique ID for each control associated with a menu. The following code fragment illustrates this process:

<!-- Apply template to get the value select(//topmenu/@rooturl) through function -->
 <xsl:apply-templates select='//topmenu' />    
     
 <!-- BUILD INDIVIDUAL MENUS -->
 <xsl:for-each select="//menu[menuitem]">
        <OBJECT CLASSID="clsid:7823A620-9DD9-11CF-A662-00AA00C066D2" CODEBASE="http://activex.microsoft.com/controls/iexplorer/iemenu.ocx#Version=4,70,0,1161" WIDTH = "1" HEIGHT= "1" ALIGN = "baseline" BORDER = "0" TYPE = "application/x-oleobject">
            <xsl:attribute name="ID">topNavigator<xsl:eval>childNumber(this)-1</xsl:eval></xsl:attribute>

Here is the HTML that results from the preceding block of code:

<OBJECT CLASSID="clsid:7823A620-9DD9-11CF-A662-00AA00C066D2" CODEBASE="http://activex.microsoft.com/controls/iexplorer/iemenu.ocx#Version=4,70,0,1161" WIDTH="1" HEIGHT="1" ALIGN="baseline" BORDER="0" TYPE="application/x-oleobject" ID="topNavigator0">

After the XSL generates the <OBJECT> element, which creates an instance of the Popup object, the XSL executes an inner loop to populate the object with menu items. The <xsl:element> element now generates <PARAM> elements, which will contain as values the arguments passed to the Popup object. The <xsl:attribute> element assigns to the value of the name parameter a string concatenated from "menuitem[," the decremented child number, and a closing bracket (]), which creates an index value starting with 0. Another <xsl:attrib> element adds a "value" attribute, which will contain the actual menu name (the itemname attribute), which is retrieved from each <menuitem> element in the *menu.xml file. The decode function (an inline JavaScript function in menu.xsl) contained in the <xsl:eval> element then converts the ASCII value of each item to its Unicode equivalent. The following code fragment illustrates this process:

            <xsl:for-each select="menuitem">
                <xsl:element name="param">
                  <xsl:attribute name="name">menuitem[<xsl:eval>childNumber(this)-1</xsl:eval>]</xsl:attribute>
                  <xsl:attribute name="value"><xsl:eval>decode(this,'itemname')</xsl:eval></xsl:attribute>
                </xsl:element>
             </xsl:for-each>   
         </OBJECT>

After populating the Popup control with the names of the menu items, the XSL generates script to handle click events for each item. The <xsl:element> element generates a <SCRIPT> element, assigns it VBScript as the LANGUAGE attribute, and then names an inline function for the Popup control, appended with the menu item's index number, which is generated by the expression childnumber(this)1. The function takes as a parameter a value that coincides with the index number of each menu item.

The code then uses the <xsl:choose> and <xsl:when> elements to test if it is building the Build menu. If it is, it writes inline script into the resulting HTML file that opens a new window. This window is used by the event handler for each language option to indicate the status as the application builds localized HTML files. The call to window.open passes in parameters that add the appropriate language folder to the HTTP query string and change the value in getrootNode to this URL.

 <xsl:element name="SCRIPT">
          <xsl:attribute name="LANGUAGE">VBScript</xsl:attribute>
          
           function topNavigator<xsl:eval>childNumber(this)-1</xsl:eval>_click(ByVal x)
           select case x
             <xsl:choose>           
              <xsl:when test="@name[.='Build']">
                 <xsl:for-each select="menuitem"> 
                     case <xsl:eval>childNumber(this)</xsl:eval>:
                       window.open "<xsl:eval>getrootNode</xsl:eval><xsl:value-of select='@url' />?langFolder=<xsl:value-of select='@itemname' />","Building","status=yes,resizable=yes,top=200,width=400,height=200"
                 </xsl:for-each>  
              </xsl:when>

For menus other than Build, the XSL builds a Select Case statement and assigns to each menu item's index a dynamically built URL that is returned when a user clicks the item. The URL is an attribute in each <menuitem> element in the *menu.xml file. The following code fragment illustrates this process:

              <xsl:otherwise>
                 <xsl:for-each select="menuitem"> 
                     case <xsl:eval>childNumber(this)</xsl:eval>:
                        top.location.href = "<xsl:eval>getrootNode</xsl:eval><xsl:value-of select='@url' />"
                 </xsl:for-each>                 
              </xsl:otherwise>
             </xsl:choose>
            end select
           end function
       </xsl:element>