Managed nav in the global template, without autoindex?

For clarity on this topic, I’m going to lay out what I need first, then try to explain my thoughts on solving it.

Our site’s main staple, is a content type called “Topic”. It’s pretty much the bread and butter of our operation. In the Content Explorer, these topics are organized in folder structures according to categories and other things we feel are important distinguishing features. Due to the large number of topics though, and the need for a person to rapidly navigate to the appropriate topic, we have implemented an alphabetical listing in our global template. To do this, we have created one autoindex for each alphabet letter (A - Z + #), we also have one to contain everything that starts with a number. Currently the location scheme to provide a simple path to the file, like A.html, B.html, etc. These autoindex lists are publishing correctly, and work great.

So our current problem is that in the global template, we have a navigation region which contains all of the links to these alphabetical lists, each of these links are currently hard coded to point at one of the alphabetical lists, but these pages do not exist during preview, and therefore these links do not work. I would like to convert them to managed navigation, but I just can’t seem to see a clear way to do this.

I think a basic slot will not work because this has to be in the global template, and I can’t see a way to populate a slot with these items. Typically you would edit a single content item, and populate the slot, but this action would populate that slot ONLY for that one content item, and we have hundreds of content items.

A typical managed nav slot would not work here, because these items are arranged structurally in a way that is NOT alphabetical, and re-arranging them into an alphabetical structure is not an option. My understanding of managed nav slots is that they function on folder structure.

An auto slot MIGHT work, but my query would have to specifically name the content items that I wanted, I could sort the content items alphabetically. The only problem I can foresee is that in addition to letters a-z, I need one listing for all topics that start with a number rather than a letter, and it needs to be last in the list, how can I guarantee that this will happen? Currently this numeric list is denoted with a # symbol, which sorts BEFORE the letter A. Another problem with this approach is that the content type for these alphabetical lists is “autoindex” and the autoindex content type is used for more than just these alphabetical listings, so I would need to build the query to only find a specific list of content items.

Abandoning the idea of slots altogether, I thought I might be able to simply use $rx.location.generate() to generate the correct path. This is the simplest and most desirable to me, because the alphabet is finite, and therefore will not be gaining new letters any time soon. Once I have built this functionality it is unlikely that it will change, so a slot is overkill. Also, this is a great solution because it will solve some other navigation issues that are similar in nature, such as a link in the header to the FAQ page. The only problem with this solution is that $rx.location.generate() requires a content item to be passed to it, and I only have a content ID. I can’t seem to find any functions that accept an ID and return the full content item.

So I apologize if that was a bit long winded, but really I guess what I’m asking is: What is the best practice for embedding links into your global template, which point to specific content items?

Thanks,

-Jason

Quick update:

Using this:

#set($guid = $user.psoObjectFinder.getGuidById(‘991’))##
#set($alphaItem = $user.psoObjectFinder.getNodeByGuid($guid))##
$alphaItem

I was able to retrieve the node for content item 991. $alphaItem now contains:

com.percussion.services.contentmgr.data.PSContentNode@110f2b0[sys_id=991,name=CLTTopic - A Index,depth=0,type=AutoIndex]

which is the correct content item (the “A” alphabetical listing) but calling $rx.location.generate($alphaItem)
does not work… it just puts the command into the page as a string… Anybody have any ideas on how to get this node to render after using the PSO tools to retrieve it?

Thanks,

-Jason

Hi Jason

The way to do this through navigation is to create a folder that contains all the indexes then create a navigation templates that just looks inside that particular folder. I tend to use the syntax [foldername] so that in the other navigation templates i exclude all folders which start with a [.

Here’s a template that shows this in action:

#macro(rootlevel $node)
	#set($submenu = $node.getNodes("nav:submenu"))
	
	#foreach($node in $submenu)
		#set($name = $node.getProperty("rx:sys_title").String)
		#if($name.indexOf("[indexes]") > -1)
			#firstlevel($node)
		#end
	#end
#end

#macro(firstlevel $node)
  #set($submenu = $node.getNodes("nav:submenu"))
  #foreach($node in $submenu)
		#landinglink($node)
	#end
#end

#rootlevel($nav.root)

You could also use the same principal to create an auto index of index items (this is not uncommon) by using the jcr:path in the query eg

SELECT rx:sys_contentid, rx:sys_folderid FROM rx:Topic WHERE jcr:path = '//Sites/YourSite/[foldername]'

Hope this helps

Cheers
James

Thanks James,

We are using this principle for some of our more regular navigation, but in this particiular case, it might be difficult to do this.

My alphabetical listing pages are of the type Autoindex, and there are other “autoindex” items in the same folder. Moving them to a new folder would cause them to publish to a new location, which could have adverse affects. While a location scheme might fix this, it still does not address the issue of getting them in the correct order.

Also, it will not address the needs of “one-off” links, such as creating a link to my FAQ page, etc…

I did find something that will work though:


#macro(generateDefaultLocation $contentID)
	#set($guid = $user.psoObjectFinder.getGuidById($contentID))##
	#set($contentNode = $user.psoObjectFinder.getNodeByGuid($guid))##
	#set($template = 'cltPgAutoIndexTopicAlpha')##
	#set($itemPath = '//Sites/CLT/Topics/')##
	#set($filter = $sys.assemblyItem.getFilter().getName())##
	#set($siteID = $sys.assemblyItem.getSiteId().longValue())##
	#set($contextID = $tools.number.toNumber($tools.list.get($sys.params.get('sys_context'), 0)))##
	$rx.location.generate($template, $contentNode, $itemPath, $filter, $siteID, $contextID)##
#end

This works, because the six member signature of location.generate accepts a node rather than an assembly item, and therefore works with the node I get from the psoObjectFinder. However, I would like to abstract this macro one step further, and make it work for any content item, but to do that, I need to figure out how to get the default template, and the item path from the node I already have. I’ll just have to keep digging to see if I can find it. I know this is really a “Dirty Harry” sort of way to get things done… but it seems like the most effective way to deal with my needs.

OK, here is a generic version, capable of handling any content item. I could never find a way to discover the default template, but I figured in most cases I’ll want to pass that in anyway.


#macro(generateDefaultLocation $contentID $template)##
#if($template.length() > 0)##
#set($guid = $user.psoObjectFinder.getGuidById($contentID))##
#set($contentNode = $user.psoObjectFinder.getNodeByGuid($guid))##
#set($itemPath = $user.psoFolders.getParentFolderPath($guid))##may get sketchy results if item has more than one location
#set($filter = $sys.assemblyItem.getFilter().getName())##
#set($siteID = $sys.assemblyItem.getSiteId().longValue())##
#set($contextID = $tools.number.toNumber($tools.list.get($sys.params.get('sys_context'), 0)))##
$rx.location.generate($template, $contentNode, $itemPath, $filter, $siteID, $contextID)##
#end##
#end##

During a normal preview, it works fine, but when doing a publish preview (getting the publish URL from the content list, then viewing that document in my browser) I see that the location.generate call winds up EMPTY. Looking in the console log, I get a whole pile of errors like this:

2009-03-26 14:35:43,163 ERROR [PSGeneratePubLocation] Problem while generating a publishing location for variant 500 and contentid 991
com.percussion.extension.PSExtensionException: $sys.pub_path + $sys.template.prefix + $sys.item.getProperty(‘rx:letter’).String + $rx.loc

and that content ID belongs to the item I was trying to build the link for. When I individually output the value of each of the set variables, they are all correct. so this message has to be coming from the location.generate method. Anybody have any ideas why this is happening? The above error looks like it comes from my location scheme for those items… but I havn’t changed the location scheme.
Thanks,

-Jason

You definitely do NOT want to use the six parameter signature of $rx.location.generate.

The proper way to do this is to take $sys.assemblyItem and clone it, then use the setNode() method to set the node of the new item.

You don’t need to find the default template, as $rx.location.generate will do that for you if you pass it your cloned assembly Item.

Dave

Dave,

Thanks for the info. I tried this:


#macro(getDefaultLocation $contentID)
#set($guid = $user.psoObjectFinder.getGuidById($contentID))##
#set($contentNode = $user.psoObjectFinder.getNodeByGuid($guid))##
#set($clonedItem = $sys.assemblyItem.clone())##
$clonedItem.setNode($contentNode)##
$rx.location.generate($clonedItem)##
#end

and again, I get a successful preview, but when previewing using the publish URL (from the content list preview)… I still get a blank stare. How can I be sure that the node I am getting is the right one?

-Jason

Sorry to be so chatty, but I think I found a clue… but I have no idea what it means:

In my normal preview, using the code below, everything is working fine, every link shows up correctly.

When previewing with the publish settings, one link generates correctly while the others fail. I have 28 links of the type “Autoindex”, one link of type “Generic”, and one type “Other”. The Generic link is working correctly in both previews. All three of these types default to a dispatch templates (to be clear, each of these three content types has it’s own dispatch template) which of course re-directs them to another template.

Any ideas what might make a difference here?

Thanks,

-Jason

[QUOTE=jlloyd;6866]For clarity on this topic, I’m going to lay out what I need first, then try to explain my thoughts on solving it.

snip snip snip

So I apologize if that was a bit long winded, but really I guess what I’m asking is: What is the best practice for embedding links into your global template, which point to specific content items?

Thanks,

-Jason[/QUOTE]

Jason,

You should have a look at the #prop_slot macro, which you can find over in the Code & Snippets forum.

See http://forum.percussion.com/showthread.php?t=2562

You can place your slot with the A - Z links in it on either the NavTree item or the “Home Page” (that is, the landing page of the NavTree) and all items in the site will inherit the same values for that slot. You don’t have to worry about auto-indexes or special code in your template.

Sorry I didn’t read the whole thing the first time through, or we could have skipped the discussion about cloning of assembly items (although that is still useful in other situations).

Dave

Thanks Dave! This helped a lot. In a strange twist of fate, it appears that at one point this was already set up, as these slots (and the correct content items) already existed on my root nav. I suspect that these have been in place since BEFORE our upgrade to 6.5, meaning that they predated even the velocity technology. Was this technique ever used in pre-velocity systems?

At any rate, this seems to be working well for me, with only one minor, yet notable snag. When calling prop_slot, I had to name the appropriate tempalte for my links, because I do not want the default template in this case. Normally I can do this simply with a string like “template=‘someTemplateName’” but in this case, I had to create a map for it to accept the template name, like this: $rx.string.stringToMap(“template=someTemplateName”). Failure to do so would result in the typical “barf” screen with the message:

The template specified by “cltSnAutoindexAlphaLink” and content type id 301 was not found.

Thanks again for the help Dave!

[QUOTE=jlloyd;6902]Thanks Dave! This helped a lot. In a strange twist of fate, it appears that at one point this was already set up, as these slots (and the correct content items) already existed on my root nav. I suspect that these have been in place since BEFORE our upgrade to 6.5, meaning that they predated even the velocity technology. Was this technique ever used in pre-velocity systems?
[/QUOTE]

Yes, this technique goes back to the beginning of Managed Nav. Of course, in 5.x systems, you needed to write some custom XSL templates to walk through the Nav Tree XML. Stephen’s Velocity macro makes this much much simpler.

[QUOTE=jlloyd;6902]
At any rate, this seems to be working well for me, with only one minor, yet notable snag. When calling prop_slot, I had to name the appropriate tempalte for my links, because I do not want the default template in this case. Normally I can do this simply with a string like “template=‘someTemplateName’” but in this case, I had to create a map for it to accept the template name, like this: $rx.string.stringToMap(“template=someTemplateName”). Failure to do so would result in the typical “barf” screen with the message:

The template specified by “cltSnAutoindexAlphaLink” and content type id 301 was not found.

Thanks again for the help Dave![/QUOTE]

That’s interesting, we’ll have to look into that one. Of course, using the stringToMap function is reasonable enough workaround for now.