Display Menu starting from certain node

Topics: General
May 31, 2011 at 10:06 AM

Suppose I have Webpage structure like this

Root
  ComanyInfo
    Topic1Sub1
    Topic1Sub2
  Products
    Topic2Sub1
      Topic2Sub1Sub1
      Topic2Sub1Sub2
    Topic2Sub2
...

How can I wire up a menu starting from a certain node? I want two menus on my page: One in the head of the page, showing the menu structure from CompanyInfo, and the other in the main body of the page, showing the menu structure from Products. I'm not sure, if modifying e.g. the Composite.Navigation.Distributed XSLT-function for my purposes is a proper solution? Does anybody know a "better" way or has any tips?

Thanx steschu

Coordinator
May 31, 2011 at 11:48 AM

Hello,

I think that It is better to create your own XSLT function which will have input parameter e.g  StartPageFrom, but the Composite.Navigation.Distributed can be used as an base example.

Consider to create next XSLT:

Input parameters:

1) StartPageFrom, type = DataReference<IPage>

2) ShowStartPage, type = Boolean

Function Calls:

1) Composite.Pages.SitemapXml

Template:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:in="http://www.composite.net/ns/transformation/input/1.0" xmlns:lang="http://www.composite.net/ns/localization/1.0" xmlns:f="http://www.composite.net/ns/function/1.0" xmlns="http://www.w3.org/1999/xhtml" exclude-result-prefixes="xsl in lang f">
  <xsl:param name="startPageFrom" select="/in:inputs/in:param[@name='StartPageFrom']" />
  <xsl:param name="sitemap" select="/in:inputs/in:result[@name='SitemapXml']/Page[@isopen='true']" />
  <xsl:param name="showStartPage" select="/in:inputs/in:param[@name='ShowStartPage']" />
 
  <xsl:variable name="root" select="$sitemap/Page[@Id=$startPageFrom]" />
  <xsl:template match="/">
    <html>
      <head>
         <link rel="stylesheet" type="text/css" href="myNavigation.css" /></head>
      <body>
        <ul id="MyMenu"> 
          <xsl:choose>
            <xsl:when test="$showStartPage = 'true'">
              <xsl:apply-templates mode="Page" select="$root" />
            </xsl:when>
            <xsl:otherwise>
              <xsl:apply-templates mode="Page" select="$root/*" />
            </xsl:otherwise>
          </xsl:choose>
        </ul>
      </body>
    </html>
  </xsl:template>
  <xsl:template mode="Page" match="*">
    <xsl:if test="@MenuTitle != ''">
      <li>
        <a href="{@URL}">
          <xsl:if test="@iscurrent='true'">
            <xsl:attribute name="class">selected</xsl:attribute>
          </xsl:if>
          <xsl:value-of select="@MenuTitle" />
        </a>
        <xsl:if test="count(./*)&gt;0">
          <ul>
            <xsl:apply-templates mode="Page" select="./*" />
          </ul>
        </xsl:if>
      </li>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

Then you can call this function and specify start page from which to show menu. You can do other customization of this function.

Jun 22, 2011 at 5:31 PM

Hi Inna,

First of all thanx for your help and coding - your example helped me to understand Composite.Navigation.Distributed better and how things work with the /in:inputs/in:result[@name='SitemapXml'] function call result.
After trying around a bit, I came to the following solution - which is only a simple modification using Composite.Navigation.Distributed as the base. Here you go:

1. Create a new XSLT Function e.g. Composite.Navigation.DistributedStartNode and copy the template code from Composite.Navigation.Distributed into it. Make sure to create all InputParameters and FunctionCalls as well, exactly as they are in Composite.Navigation.Distributed.

2. Modify the InputParameter:
  i) Create a new Parameter StartPage, type = DataReference<IPage>
 ii) Set the default value of the already existing parameter Level to 0 (since it always has to be 0 - so set the default value and you don't have so the specify the parameter in your function call)

3. Modify the Template:
  i) Add a xsl:param in the beginning of the code (e.g. in line 8)
   <xsl:param name="root" select="/in:inputs/in:param[@name='StartPage']" />

 ii) Go to line 16 and change
   <xsl:apply-templates mode="Level" select="/in:inputs/in:result[@name='SitemapXml']"> into <xsl:apply-templates mode="Level" select="/in:inputs/in:result[@name='SitemapXml']//Page[@Id=$root]">

Call the function (here in a ASP .NET master page):

<rendering:function id="fnNavColumn1" runat="server">
  <f:function xmlns:f="http://www.composite.net/ns/function/1.0" name="Composite.Navigation.DistributedStartNode">
    <f:param name="Parent" value="True" />
    <f:param name="Childs" value="True" />
    <f:param name="Expand" value="False" />
    <f:param name="NavigationId" value="NavigationMenu" />
    <f:param name="StartPage" value="2acf3ee2-0c38-4a46-8210-f025fddf389f" />
 </f:function>
</rendering:function>

The functions works just a the Composite.Navigation.Distributed function, but "moving" the starting point to the start page.

Cheers, steschu