Creating An Admin Toolbar

In mojoPortal content management system we have always tried to make it easy to get to common administrative tasks by providing links for users who are in roles with edit permissions. The idea has always been to try and make the links unobtrusive so they don't impact the page layout because for the most part we want to be seeing the page pretty much as visitors who do not have edit permissions will see it.

In the early days pretty much all of the skins had little icons for the links like this:

administration icons

Once the user was familiar with the icons it was very easy but sometimes for new users it was confusing, they might not notice the icons or not know what they are for, perhaps they are not very web savvy and don't know that mousing over the icon would show a tooltip with more information about the link. Over time based on community feed back a consensus emerged that text links are more user friendly than these icons because it is very clear what the link is for even for non web savvy users. The challenge became where to put them to make them not impact the page layout or get in the way of content. Typically each skin had them in a div positioned absolutely somewhere on the page, many of them were in the top right corner, sometimes in the header, it just depended on the skin design. You can still use icons in your skin by setting this property on the StyleSheetCombiner:

<portal:StyleSheetCombiner id="StyleSheetCombiner" runat="server" UseIconsForAdminLinks="true" />

By default this is now false, so links are used.

administration links

In preparing for the 2.3.3.4 release one of the new features was to add a link for easy access to the File Manager for users in roles allowed to use it. This brought the number of links on the page to a point where it was becoming difficult to show them without impacting the look of the design. To solve this I got the idea to have a toolbar or menu of some kind that could be collapsed out of the way. After searching a bit I found this blog post with a nice hideable toolbar. The author was using it for a toolbar for social web site sharing links, but it seemed to me a good solution for administrative links as well. The example shows how to add a sub menu to the toolbar so you could make a custom one in any skin and add your own additional menu links, but for the included skins, my goal was to show all the administration links on the tool bar itself so no extra clicks are needed to get to each item. So, as of mojoPortal version 2.3.3.4 many of the included skins now have this toolbar:

administration links in a toolbar

Note that it is entirely a skinning thing, you can present these administration links any way you like, you do not have to use this toolbar and you could remove it from any included skin and do your own thing if you come up with something you like better. Some have suggested it should go on the top of the page, it is positioned by CSS so you could do that if you want to, but for most of the included skins putting it at the top would cover up other important things and keeping the tool bar at the bottom is a better way to avoid impacting the page layout. I've been using the toolbar on this site for a while now and I have grown to like it and it feels right to me that it is on the bottom of the page and not up in the more important areas of the page fold.

Now in order to implement this toolbar I had to make some changes. Historically, the mojoBasePage would inject the administration links into the ContentPlaceHolder named pageEditLayout in the layout.master, it was usually wrapped in a div like this:

<div class="editpanel">
<asp:contentplaceholder ID="pageEditContent" runat="server"></asp:contentplaceholder>
</div>

and the div was positioned absolutely wherever it best fit on the page for the given skin design. All the logic of which links to show was handled by the mojoBasePage.

Clearly, this was a problem because it did not enable one to place the individual administration links where we wanted them and to wrap them individually in other html markup which is what we needed to put them in a toolbar like this. So the solution was to implement separate controls for each of these administration links so they could be placed directly wherever we want in the layout.master file of the skin and wrap them in other html markup. For backward compatibility with existing skins the logic has been changed to look for the administration links in the master page and only add them if they do not exist. This requires using specific ids on the controls so we can find them, so if you want to add the individual links into your layout.master, you need to use these exact same ids:


<portal:AdminMenuLink id="lnkAdminMenu" runat="server" />
<portal:FileManagerLink id="lnkFileManager" runat="server" />
<portal:NewPageLink id="lnkNewPage" runat="server" />
<portal:PageEditFeaturesLink id="lnkPageContent" runat="server" />
<portal:PageEditSettingsLink id="lnkPageSettings" runat="server" />
<asp:ContentPlaceHolder ID="pageEditContent" runat="server"></asp:ContentPlaceHolder>

You do still need to keep the pageEditContent contentPlaceholder in the layout.master somewhere, we still load the workflow dropdown there if workflow is enabled on the page.

Now the new administration links have their own internal logic to show and hide themselves according to user permissions. However I still had one problem left, since the toolbar is just plain html it would still render in the page even if none of the links were visible, it would just be an empty tool bar. A way to hide the whole thing was needed if none of the administration links were visible. So I created <portal:AutoHidePanel which I could wrap around the whole thing. This is just a simple control that inherits from <asp:Panel, what it does is look for child controls that inherit from WebControl (like the admin links), it looks at all its child controls and if there are no WebControls with their visible property set to true then it makes it's own Visible property false. It doesn't care about the other literal html that it may contain so it doesn't matter if that stuff is visible or not, it only cares if it has at least one visible WebControl contained within it.

So, the final solution that you will see in most of the included skins is achieved by first adding the CSS for the toolbar by adding this in your style.config file:

<file cssvpath="/Data/style/jqtoolbar/style.css" imagebasevpath="/Data/style/jqtoolbar/">none</file>

Tip: put it near the top above your main style.css so you can override anything you like from your main style.css file.

Then remove any existing edit panel and pageEditContentPlaceholder and put this in your layout.master just before the <portal:GoogleAnalytics control near the bottom:

<script type="text/javascript">
$(document).ready(function(){
 $("span.downarr a").click(function() {
 $("#toolbar").fadeOut();
    $("#toolbarbut").fadeIn("slow");
});
$("span.showbar a").click(function() {
$("#toolbar").fadeIn();
$("#toolbarbut").fadeOut("slow");
});
$("span.downarr a, span.showbar a").click(function() {
return false;
});
});
</script>
<portal:AutoHidePanel ID="ah1" runat="server">
<div id="toolbarbut">
<span class="showbar"><a href="#">show bar</a></span>
</div>
<div id="toolbar">
<div class="toolbarleft">
&nbsp;
</div>
<div class="toolbarright">
<span class="downarr">
<a href="#"></a>
</span>
<portal:AdminMenuLink id="lnkAdminMenu" runat="server" />
<portal:FileManagerLink id="lnkFileManager" runat="server" />
<portal:NewPageLink id="lnkNewPage" runat="server" />
<portal:PageEditFeaturesLink id="lnkPageContent" runat="server" />
<portal:PageEditSettingsLink id="lnkPageSettings" runat="server" />
<asp:ContentPlaceHolder ID="pageEditContent" runat="server"></asp:ContentPlaceHolder>
</div>
</div>
</portal:AutoHidePanel>

It is really very little javascript for showing and hiding the toolbar with jQuery. If you look at the original example of this tool bar from the blog post linked above, you will see he had more stuff there to support his sub menu and social links. I pared it down to just the minimal needed.