In the first article we dissected a DDRMenu XSL structure. In the second article I explained a number of use cases to learn some new XSL and give you ideas about what else is possible using XSL in conjunction with the DDR menu in DotNetNuke. Now we will use all we have learned in the two previous articles to build a basic mega menu from scratch and later extend it with other features.
The menu we will create will be a modified version of the one that is included in http://dnnddrmenutemplates.codeplex.com/ because we are going to do a few things that I used to do using jQuery, but this time we’ll do them with pure XSL which will give us the ability to parameterize the menu for easier implementation
In this entry I will only explain the necessary XSL for the menu. The CSS and JavaScript will be included with the menu. This article just discusses the XSL used to render the correct HTML output for the CSS and JavaScript to work its magic.
At this point in the series you should know enough XSL to understand this article so I am not going to paste all the code in its entirety anymore. If you are interested in seeing the full section of code you can download the files associated with this article. In this specific entry I will only paste the code that may not yet look familiar because it hasn’t been discussed in one of the earlier articles.
Initial setup: define the variables we are going to use/reuse
2
]]>
]]>
Explanation:
We want to reuse a few elements so we will define these at the top of the document. We would like to be able to specify, in the skin, the number of columns that the mega-menu will render. In order to give us this control at the skin level we simply need to define the necessary values here in the XSL so that we can override them in the skin. This gives skin designers a great deal of flexibility and power while at the same time saving them from having to know XSL.
Because we are defining html code and elements as well we put these in a CDATA element
Setting up the menu
Explanation:
Because we need to have a different html base on the level of the menu element and this is not easily read out of the menu, we are going to do this ourselves by defining the "level" param. Initially we will set this as 0 and we add one to this with each subsequent call to get its children.
Setting up the rest of the menu
We have defined the menu and now the real work begins by setting up the child menu items, the column setups, etc. I will explain this step by step to make this clearer.
Defining the columns
Explanation:
Now this is where it gets interesting We are going to subdivide our child blocks into rows of the same number of columns as defined in the "subMenuColumns" parameter. This may look complicated because we are using some techniques that were not yet mentioned in the previous articles, but let me explain this sequentially.
First, we see if the element is the first or the last element. If the current element is the first element then we need to start a row. As you can see we use the predefined html element defined in the "startRow" parameter.
You may wonder why we do it like this and not work with the html itself. The reason is that an XSL needs to be valid and every start tag has to have an end tag. We need not worry because the end result will be valid html rather than the direct XSL I use in this technique. To XSL it is just a parameter and is not recognized as a not open or closed html element. We use "disable output-escaping" because we want the html as we have defined it in our parameter. If we did not do this XSL would just see it as an empty element and show nothing.
Now if it's not the first or the last of the child element we need to determine if we need to close of the row and start with a new row or do nothing and continue on to process the next child element. We are going to do this using the modules
Using this function in XSL defined as "mod" we check if we can do a division of the child element 1 2 3 4 etc with the number of columns as defined in "subMenuColumns" without having anything left. Example 2/2 = 1 4/2 = 2 but 5/2 = 2 leaving one so the first two divisions will result as true while the last one will be false.
So if the "position()" divided by the "subMenuColumns" doesn’t leave any remainder then it is true (in XSL defined here as 1 ) then we need to close of our row element and start a new one.
Then we just continue with our normal menu setup and at the end do the same setup again only this time checking if the element is last and then closing the row or of mod when the condition is true and then end the started row element.
Our XSL setup is done now we need to reference it in our skin
We now have the XSL done (you can download the menu folder at the bottom of this article reference it in your skin as above and play with it).
Now the fun part for DotNetNuke skinners… In order to set the XSL param in our skin we simply need to pass it as a dnn:templateargument
With all these 3 articles combined you should have a good basic understanding of XSL and how to use it to create any kind of menu setup you can imagine. Now you should be able to go and see what else you can do with XSL and how to use it to add even more functionality to your DDRmenu's. Get to know as much about XSL as possible and I’m sure you will find creative ways to use it in your DotNetNuke skins and portals.
This will come in handy not only when templating your next DDRMenu but also in templating the output of other modules such as the Reports module or one of my favorite free modules of all time the Forms & List module. In fact I will start a new article series soon about recreating various modules’ functionality using just the Forms & List module.
You now have a basic mega menu that you can extend yourself for example by adding a background image to each section mega menu by using the technique of getting the pageicon of our previous article or by highlighting special tabs using one of the techniques of one of the use cases in our previous articles as well. Combine any of these and your next DDRMenu will look great and work even better.
If you want a more advanced/versatile MegaMenu you can always get mine from the DotNetNuke store. The one I’ve linked to below has lots of options and functionality all coded in about 600 lines of XSL. This menu is helpful to help you learn a trick or 2 more or to simply use it as is because the MegaMenu setup offers us a great variety of options out of the box.
http://store.dotnetnuke.com/home/product-details/2dnn_megamenuxtreme
Download Article File: Mega2DNN.zip