How to create own theme?

This tutorial shows how it's simple to create nice looking menu with MenuBox and integrate it with DotNetNuke.

There are a lot of nice scripts around and really well-written tutorials how to create a shiny navigation with jQuery and CSS. "Sexy Drop Down Menu w/jQuery & CSS" by Soh Tanaka is one of them. To do not reinvent the wheel let's use this menu as basis for our theme and integrate it with DotNetNuke.

How the final menu looks like

Step 1.

Download a theme skeleton (Download) and unpack it to any location. It contains a set of files and includes jQuery javascript library (you can use your favorite one).

Picture 1. Menu skeleton after unpacking

Rename the folder name to your unique name, say SexyDropDownMenu. After that, open skin.xml and change following information as shown in listing:

<skin>
  <skin_id>SexyDropDownMenu</skin_id>
  <skin_image>skin_preview.png</skin_image>
  <template_name>My First Menu Template</template_name>
  <description>This is my first menu template for MenuBox.</description>
  <version>1.0</version>
  
  ...
  
</skin>

skin_id should be the same as folder name. All other information is optional. You can change skin thumbnail image, its name and description. This data will be shown in Admin Panel of MenuBox after theme installation.

Step 2.

Prepare all necessary files for navigation: JavaScript, CSS and HTML. To make it more modular, original sources have been changed: JavaScript initialization went to separate file, CSS styles went separate file as well and hardcoded ID for navigation was changed to specific class name. You can download the final result and test it on your local computer. It looks the same as original and works the same way.

Picture 2. Menu sources after unpacking

Step 3.

Integrate all menu parts to Menu skeleton.

The all menu sample content is shown in Picture 2. It contains style.css files in css folder and dropdownmenu.js in js folder. The menu structure is defined in index.html and looks like

<ul class="topnav">
	<li><a href="#">Nav Link 1</a></li>
    <li>
        <a href="#">Nav Link 2</a>
        <ul class="subnav">
            <li><a href="#">Sub Nav Link</a></li>
            ...
        </ul>
    </li>
	...
</ul>

3.1 Adding CSS files to menu theme.

In order to add CSS styles to your menu you need to copy them to CSS folder (or any other actually) and register it in skin.xml. There is <css> section where you need to add all your CSS files:

<css>
    <root_css_class>myMenu</root_css_class>
    <files>
      <file unique="true" unique_name="main-styles">
        <path>css/styles.css</path>
      </file>
    </files>
</css>

So, it's already defined in the template and you don't have to modify the xml configuration file. But if you need to register more than one file, just add one more file reference in files section under <css> like this:

<css>
    <root_css_class>myMenu</root_css_class>
    <files>
      <file unique="true" unique_name="main-styles">
        <path>css/styles.css</path>
      </file>
	  <file unique="true" unique_name="my-theme">
		<path>css/mytheme.css</path>
	  </file>
    </files>
</css>

Important: The files will be added to the page in order they are defined in xml configuration.

<root_css_class> tag defines main root css class for menu. If you take a look at HTML menu prototype (index.html in DropDownMenuSources), you'll see class="topnav", so this is it. It will be automatically added to menu during generation (more on this in HTML templates section).

<root_css_class> is optional and you can just hard code CSS class. (This tag is used by ThemeFactory to prevent collisions in CSS class names).

As you might notice, file element has 2 attributes: unique and unique_name. They define a strategy how resources will be used if there is more than one menu on the page with the same theme. So, let's say you added a menu with the same themes to top and bottom sections. In the simples case, both of them will include javascript and css resources independently. But why do we need to make 2 additional requests (to get js and css files) to server if browser has already cached them after first inclusion? With this attributes you are able to control this behavior. Add unique="true" and unique_name="unique_name_for_script" and it will be included only one time if different menus use the same script.

3.2 Adding JavaScript Files.

This menu uses jQuery library and it's already included in Menu Skeleton. Just copy additional dropdownmenu.js file to js directory and register it in skin.xml.

<js>
    <files>
      <file unique="true" unique_name="jquery-132-min">
        <path>js/jquery-1.3.2.min.js</path>
      </file>
      <file unique="true" unique_name="my-dropdownmenu">
          <path>js/dropdownmenu.js</path>
      </file>
    </files>
</js>

JS section of configuration file is absolutely the same as CSS except the fact that it defines JavaScript resources.

3.3 Adding additional resources

Copy images folder from menu sources to menu skeleton folder. There is no need to register resources like images and others. They will be used from CSS files and path are relative from css folder. In other words, if you need to add images in your css file, use following paths: "../images/yourimage.png".

3.4 Defining HTML structure

The menu structure is defined by following diagram.

Picture 3. Menu structure

The orange rectangle is a wrapper around menu or top menu html element, container. The blue elements are the nodes of menu and they can be nested.

The wrapper (orange rectangle) is defined by html/WrapperTemplate.aspx. If you recall the menu structure, it looks like

<ul class="topnav">
	<li><a href="#">Nav Link 1</a></li>
    <li>
        <a href="#">Nav Link 2</a>
        <ul class="subnav">
            <li><a href="#">Sub Nav Link</a></li>
            ...
        </ul>
    </li>
	...
</ul>

In our case the top UL element is a wrapper (orange box), all inner LI and inner UL are "blue boxes". Let's modify html/WrapperTemplate.aspx to reflect this structure.

<%@ Control Language="C#" AutoEventWireup="True" CodeBehind="~/HtmlTemplate/WrapperTemplate.ascx.cs"
    Inherits="CodingStaff.Modules.MenuBox.WrapperTemplate" %>
<%@ Register TagPrefix="uc" TagName="NodeItem" Src="NodeTemplate.ascx" %>
<ul class="<%= CssClass%>">
    <asp:repeater runat="server" id="Menu">
        <ItemTemplate>
            <uc:NodeItem runat="server" Node="<%# Container.DataItem %>"></uc:NodeItem>
        </ItemTemplate>
    </asp:repeater>
</ul>

As you see from previous listing, there is only one top level UL element (wrapper, orange box in diagram) with defined class. The class should be "topnav" and it has been defined in <root_class_element> in skin.xml earlier (you can just use hard coded parameter right in html structure) and will be automatically passed to template via CssClass variable.

asp:repeater tag is used to render all inner nodes with another template - html/NodeTemplate.aspx. NodeTemplate is responsible for rendering inner nodes for menu at different levels. In menu skeleton it looks like

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="NodeTemplate.ascx.cs" Inherits="CodingStaff.Modules.MenuBox.NodeTemplate" %>
<li class='<%=(IsActive ? "current" : "") %> <%=(IsLast ? "last" : "") %> <%=(IsFirst ? "first" : "") %>'>
    <a href="<%= Node.NavigateURL %>"><%= Node.Text %></a>    
    <% if (HasChildren)
     {%>
         <ul class="subnav">
             <asp:PlaceHolder runat="server" ID="phChildNodes"></asp:PlaceHolder>
         </ul>
   <%} %>
</li>

A node is represented by LI element (as in our menu as well). You are able to add specific classes for active, last and first elements. For filling element by data Node object is used. This is an object of DotNetNuke.UI.WebControls.DNNNode and all available field you can see at picture 4.

Picture 4. Node element properties

If menu element has inner nodes, they will be rendered with the same NodeTemplate in inner UL. For our menu inner UL element should have subnav class.

<% if (HasChildren)
 {%>
     <ul class="subnav">
         <asp:PlaceHolder runat="server" ID="phChildNodes"></asp:PlaceHolder>
     </ul>
<%} %>

The final result you can download by clicking the link below. Simply install this theme to MenuBox in admin panel and make it as active. That's it. More information how to install the theme you can find in Installing theme tutorial.





* If you find any problems or errors in this tutorial, please let us know at support@codingstaff.com

Powered by Coding Staff
All rights reserved. Terms of Use. Privacy Policy