|
Code Endeavors, LLC
border_tl border_tr
DotNetNuke Blog Minimize

New Video Available Demonstrating New CSS Capabilites in DNNMenu v2.0

With the launch of DotNetNuke 5 getting closer, I figured it was a good time to put together a quick video on some of the new functionality that will be found within the webcontrols.  This video will introduce you to the new ways you can customize version 2 of the DotNetNuke Menu by simply tweaking your css.  It starts out giving a brief overview of where we came from in earlier releases and how we are making strides to improve the ability for both a DotNetNuke skinner and end portal administrator.  Enjoy!


Introducing DNNMultiStateBox

One of the new features coming in Cambrian is an update in the permissions grid.  The current grid supports two states, Allow and Null (not assigned).  The new grid will support three states (Allow, Deny, and Null).  The obvious question here is how do you present this to the user?  The current design allows for a nice compact way to set the permissions within a grid utilizing checkboxes.  The new way will use a new DotNetNuke WebControl that supports multiple states and mimics a checkbox.  The original name I came up with for the control was DNNTriStateCheckbox.  However, while developing this control I soon realized there was no reason I needed to only support 3 states and saw the opportunity to support any number of states and not necessarily look like a checkbox.  So the control is now called DNNMultiStateBox.  It is probably the simplest of all the controls in the Minor Perf Optimization to Caspian Release

While sitting at the airport waiting for my plane to depart to the MVP Summit, I decided to spend a little time optimizing the new ClientAPI (codenamed Caspian) for the Cambrian release.  One of the new features for this release was to allow the output of the ClientAPI and Webcontrols to emit compliant markup (more detail mentioned in this blog).  There was two areas that this affected my code.


Javascript Global Namespaces (the dreaded $ function)

The whole idea of the $ function and who "owns" that "namespace" has become quite muddy.  When I first learned of the use of $ and found that MS was adopting the same notation, I decided to do it as well.  For at the time, I felt that all frameworks simply used it as a quick way to get the reference to a DOM element.  Soon afterwards I learned that frameworks like prototyle use it for much more.


Searching for the "Holy Grail" of Menu Item Customization

For a long time now many skinners for DotNetNuke have felt like customizing individual menu items was like looking for the Holy Grail.  All the menus I have contributed to the community (Solpart and DNNMenu) have always had the ability to customize each menu item.  The problem always was
how do we allow DotNetNuke the ability to customize the items?  The only place the unique menu structure is known is after the portal is created, well out of reach of someone providing a generic skin to fit any site.  Sure there are those portal admins out there that know enough about css to make it work, but there still was a problem in how to access each item directly in css.

I have been considering options for how to overcome this for some time now,  and am currently working on the 2.0 version of the webcontrols which should contain one possible solution.  However, those controls are far from complete so I decided to offer a minor hack along the same lines.

First, let us consider eclayf's idea from the forums, where I borrowed the name of this blog entry from.  The idea is to loop through all menu items and assign a background image to each item based off of the icon assigned.  This allows the background image to be customized by the portal admin.

To try this idea out add the following code to your ascx page using the DNNMenu (not solpart).  I tested with default blue for DNN.

<script type="text/javascript">
    function setupMenuImageCss(id)
    {
       var menu = dnn.controls.controls[id + '_ctldnnNAV'];
       assignImageCss(menu, menu.rootNode);
    }
    
    function assignImageCss(menu, parent)
    {
	    var menuNode = new dnn.controls.DNNMenuNode(parent);
	    var iconCtl = menu.getChildControl(menuNode.id, 'icn');
	    if (iconCtl)
	    {
	        iconCtl.style.display = 'none'; //hide icon
		    var menuCtr = menu.getChildControl(menuNode.id, 'ctr');
		    menuCtr.style.backgroundImage = "url('" + iconCtl.src + "')";
	    }
	    for (var i=0; i < parent.childNodeCount(); i++)
	    {
		    assignImageCss(menu, parent.childNodes(i));
	    }
    }

    try 
    {
        document.execCommand("BackgroundImageCache", false, true);
    } 
    catch(err) {}
    
</script>
<script runat="server">
Private Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.PreRender
        DotNetNuke.UI.Utilities.DNNClientAPI.AddBodyOnloadEventHandler(Me.Page, "setupMenuImageCss('" & dnnNAV.ClientID & "')")
End Sub
</script>

This should cause the icon images to be displayed as the background. 

Note: I noticed that if your skin declares the background-color (as the default blue does), the hover will no longer display the background.  If you change it to not set the background then the image remains.

While this works, it is far from ideal.  For one thing the admin menu item icons are not customizeable.  Probably the biggest shortcoming is you can only customize the image, which happens to meet eclayf's requirements, but not generic enough to implement for DotNetNuke.

The idea I have been toying with is allowing the next version of the menu to support known client-side IDs. My current thought is to allow the skin to decide whether to go this route by providing a "safe" known namespace.  For example, in your skin you would have a property like ClientIDPrefix="jcompany", then on the client each node will be assigned a unique id, prefixed with that text.  So the root would be jcompany__0, jcompany__1, etc.  The child of
jcompany__2 would be jcompany__2_1, jcompany__2_2, etc.   This way it would allow the skinner
to predefine as many levels as he/she sees fit, and as long as the user of the portal doesn't exceed the predefined number, the skin should work as originally intended.  Even if the skinner doesn't provide the level necesssary (something like jcompany__2_2_1_3_5), there is nothing stopping the user from adding the css himself, perhaps copying the value from a class defined higher up.  The only pitfal in this approach is the worry about overlapping prefixes with other controls on the page.

In order to try this concept out add the following code to you ascx file that uses the DNNMenu

<script type="text/javascript">
    function setupMenuIds(id, prefix)
    {
       var menu = dnn.controls.controls[id + '_ctldnnNAV'];
       assignMenuIds(menu, menu.rootNode, prefix, '');
    }

    function assignMenuIds(menu, parent, prefix, id)
    {
	    var menuNode = new dnn.controls.DNNMenuNode(parent);
	    var menuCtr = menu.getChildControl(menuNode.id, 'ctr');
	    var newId = prefix + '_' + id;
	    if (menuCtr)
		    menuCtr.id = newId;

        for (var i=0; i
<script runat="server">
Private Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.PreRender
        DotNetNuke.UI.Utilities.DNNClientAPI.AddBodyOnloadEventHandler(Me.Page, "setupMenuIds('" & dnnNAV.ClientID & "', 'jcompany')")
End Sub
</script>

Then in your css file add something like

#jcompany__0
{
	background: red;
}

#jcompany__1
{
	background: blue;
}

#jcompany__1_0 td
{
	background: green;
}

#jcompany__1_1 td
{
	background: orange;
}

Note:  It is worth noting that in general it is a bad idea to change the ids of a any control, as it most likely will break the control when it does a lookup by its id.  In the DNNMenu's case, those references to the lookup are cached internally, thus this reassignment of ids will work.

Right now this is just an idea I'm toying with. If people like the approach I probably will include it in version 2.0 of the DNNMenu.  Any feedback on this would be welcome.

PrintPrint  
Jon Henning





border_bl border_br
border_bl
border_br
Copyright 2007 by Code Endeavors Please consider supporting the on-going free offerings to the community.  Donate Today. Terms Of Use Privacy Statement