Multiple Navigation Slots

I am trying to set up an additional level of navigation for our site (4th level). This navigation section is displayed in a new div within the page content area. This div contains a special right hand slot that gets populated with callout content (picture, file links, contact information, etc…) and should be shared with the new navigation section.

What I am trying to do is set a variable from the leftnav macro script that will interpreted by the right slot macro to add the div to the page if fourth level navigation is needed or the right slot has contents to display.

Left navigation trigger:

#macro(thirdlevel $node)##
#getProps($node)##
#if ($landing_page != '#')##
li class="thirdlevel">
a class="$axis" href="${landing_page}">$title /a>
/li>
#if($submenu)##
#set($hasFourthLevel = 'True')##
#end##
#end##
#end##

Right slot/navigation code:

#initslot("erauRightSlot" "")##
#if($sys.currentslot.relresults.size() > 0 || $hasFourthLevel == 'True')##
div class='secondary_content'>
#slot("erauRightSlot" "" "" "" "" "")##
#slot("rffNav" "div id='fourthlevelNav'>" "" "" "/div>" "template=erauSnNavRight")##
/div>
#end##

My problem is that the “$hasFourthLevel” variable is not defined when it is read by the page template since it does not reside in the leftnav macro. Is there a way to do this or possibly an alternative method?

Hi Steve

It’s all to do with the “visibility” of the variable. As the variable is set in the left hand macro the if statement is unaware of this. What you need to to is set the variable outside of the macro eg the global or page template eg

#set($hasFourthLevel = 'false')

#thirdlevel 
#set($hasFourthLevel = 'true')
#end

if ($hasFourthLevel == 'true')

#end

Cheers
James

In my experience in 6.5.2 you cannot:
[ul]
[li]Access a variable set up in the global template in any code run by the page template (in its source, in macros called by it, or the source of snippet templates assembled via slot calls in the page template.)
[/li][li]Initialise or modify variables in the source of a page template and be able to see the value in the global template or any snippet templates. For example, you can set up a variable called $foo and give it a value, say “bar” in a page template’s binding, then use that variable in the global template. But if you set $foo to “baz” using the #set macro in the source of the page template, it’ll still have the value “bar” when evaluated in the global template, or any snippet templates.
[/li][/ul]

I’ve found the following to be a handy little reference when creating variables/bindings…

When a user previews a page…

[ol]
[li] The dispatch template is called
[/li][li] This calls the page
[/li][li] The page then calls the global template
[/li][li] The global template then calls the navigation
[/li][/ol]
In essence…

The global template can see page bindings, but the page cannot see global template bindings. Navigation can see global template bindings. I guess much of the same applies to variables in templates.

I think this has been discussed in the forum previously, but I just want to amplify slightly what David Rowe said.

The assembler creates a “map” of bindings by evaluating the JEXL expressions in the bindings tab. When it calls the Velocity template, it makes a COPY of this map. This means that variables you define with #set in your Velocity code don’t change the bindings map, and are not passed along to the next template.

Bindings you define in the bindings tab do get passed through, and the sequence is as David described it.

It is possible, of course, to explicitly modify the bindings map with statements like:

$sys.assemblyItem.Bindings.put("$somename", "somevalue")

After you execute this, $somename will evaluate in templates called from this template.

I hope this helps clarify how variables work.

Dave

How can I test for the existence of a 4th level node submenu without actually putting it into a slot and displaying it on the page? My problem is that if the slot contains items in the right slot or 4th level navigation is present, then display the div, otherwise do not display the div.

From the responses it looks like I need to put the right navigation slot on the page twice in order to accomplish this, once before the div (to test if 4th navigation exists) and once within the div? When I do this I get a bunch of extra white space from the erauSnNavRight template. Is there any better way of doing this? It seems like such a waste to run this script to create the left navigation, to create breadcrumbs, to create the top nav, and also to create the right nav. At what point will this strain the publishing engine?

Proposed solution (genericPage right div section):


#slot("rffNav" "div id='fourthlevelTEST'>" "" "" "/div>" "template=erauSnNavRight")##
#initslot("erauRightSlot" "")##
#if($sys.currentslot.relresults.size() > 0 || $hasFourthLevel == 'True')##
div class='secondary_content'>
#slot("erauRightSlot" "" "" "" "" "")##
#slot("rffNav" "div id='fourthlevelNav'>" "" "" "/div>" "template=erauSnNavRight")##
/div>
#end##

erauSnNavRight

#pagetop()##
#macro (getProps $node)##
	#set($title = $node.getProperty("rx:displaytitle").String)##
	#set($landing_page = $node.getProperty("nav:url").String)##
	#set($submenu = $node.getNodes("nav:submenu"))##
	#set($axis = $node.getProperty("nav:axis").String)##
	#set($indentclass = $axis.toLowerCase())##
#end##
#macro(rootlevel $node)##
  ## This template builds top image and starts the ULs
  #set($submenu = $node.getNodes("nav:submenu"))##
  #if ($node)##
  #foreach ($navon in $submenu)##
  #firstlevel ($navon)##
  #end##
  #end##
#end##
#macro(firstlevel $node)##
  ## this macro processes the first level navons
  #getProps($node)##
  #if ($landing_page)##
    ## don't process this nav if there is no Landing page
    #if ( $submenu )##
		#foreach ($navon in $submenu)##
			#secondlevel ($navon)##
		#end##
	#end##
#end##
#macro(secondlevel $node)##
  #getProps($node)##
  ## this template processes the second level navons. Notice we are only processing two levels of navons.
  #if ( $landing_page)##
	#if ( $submenu )##
    	#foreach ($navon in $submenu)##
			#thirdlevel($navon)##
		#end##
    #end##
  #end##
  #end##
#end##
#macro(thirdlevel $node)##
   #getProps($node)##
  #if ($landing_page && $axis == "SELF" || $landing_page && $axis == "PARENT")##
	#if ( $submenu )##
		ul>
    	#foreach ($navon in $submenu)##
			#fourthlevel($navon)##
		#end##
		/ul>
	#end##
  #end##
#end##
#macro(fourthlevel $node)##
   #getProps($node)##
  #if ($landing_page)##
    li class="fourthlevel">##
      a class="$axis" href="${landing_page}">$title/a>
    /li>
  #end##
#end##
  body>
	#rootlevel($nav.root)##
  /body>
/html>

[QUOTE=dbenua;7318]It is possible, of course, to explicitly modify the bindings map with statements like:

$sys.assemblyItem.Bindings.put("$somename", "somevalue")

[/QUOTE]

Thank you Dave. That will save me having to create dozens of snippet templates for every conceivable way of displaying an image in a page (with/without captions, with/without links to larger versions, with/without borders, using the full size if no thumbnail version exists, etc, etc.)

Actually, there are a few tweaks needed. The first parameter to the put() method must be in single quotes, otherwise it will expand the $somename variable, and hence search for a keyname in the map equal to the value of the binding. Also, the put() method returns the previous value associated with the key, or null if there was no mapping for the key, so you need to enclose it in an #if statement. Hence, this is an example that will allow me to decide for each image in a page template, whether the snippet template that assembles the image should add a hyperlink to a larger version of that image:

#if($sys.assemblyItem.Bindings.put('$addzoomlink', true)) #end

Put that on the line above the call to the slot macro and $addzoomlink can be used in the snippet template for images to decide whether to add a-tags around the img-tag. I could have done this before, in the bindings, but then all images in each page would have to either all have zoom links or all not. Now I can, for example, add a zoom link for the “main” image in the top-right of the page, but no zoom links for all the other images (or vice versa.)

This is definitely something useful to add to the documentation (apologies if I missed it, but I couldn’t find this in the 6.5.2 manuals.)