Click here to Skip to main content
15,868,016 members
Articles / Web Development / CSS
Article

Yet Another Drop Down Menu WebControl

Rate me:
Please Sign up or sign in to vote.
4.18/5 (11 votes)
23 Mar 2005CPOL9 min read 176.8K   5K   106   19
UI Navigation using JavaScript, WebControl and XSL & XML.

Yet__Another_Drop_Down_Me.gif

Introduction

This article will show a nice & simple cool Web control for drill down menu with diverse client side behaviors and functionality and it will also show some few nice and handy options on the server side. The next section explains a little bit the urge for this kind of UI components and also raises a few points regarding situations when we should use those kinds of controls and when we shouldn't.

As long as the Web exists, developers want to make a rich UI client within their Web applications. UI components like hierarchy trees, drill down menus and so on spread their charm on us and sometimes on our customers. We are all used to see it in WinForms and we like to see it also in our Web applications - why not? if to ask...

There are several why not answers that even a non UI expert, like me, can raise.

  • Web applications are stateless and sometimes this fact itself makes it harder to achieve a rich client, where state should be maintained between round trips from client to the server.
  • Rich UIs means lots of client scripts to achieve UI interactions with the end user which are sometimes hard to debug and require additional skills.
  • Lots of scripts can eventually influence the page loading time.
  • When designing a Web application, our customer's feedback and our UI experts recommend keeping the UI simple (this golden rule is true for everything). E.g., display simple flat links instead of drill down menu - let the user see his options and don't hide it within "hidden places" - like it is in drill down menu. Simple UIs will be much more user friendly UIs. All wishes that our customers will find our applications easy to use and use it. Eventually we will be able to sale our future releases and everyone will be happy.

There used to be other problems like IE compatibility, slow network connections and lacking the necessary set of script languages features - but thanks god, they were over.

OK, before I'll start to drill down into the drill menu bits, I would like to point that my version base on the great XML & XSL & JS code was originally written by Dan Wahlin and I got his permission to add my enhancements (I'm not the only one). You can find the original bits at Dan's web site on XML which is recommended for anyone who is interested in .NET and specifically with XML for ASP.NET.

The drill down menu major feature list

  1. It is possible to configure the location of the menu files – CSS, JS, XSL and XML. Our options are:
    1. within our Web application, Web folder.
    2. within aspnet_client web folder which is usually located under wwwroot folder.
    3. within a site which is not defined on port 80 but on another port.
  2. Support for permissions check - two levels of permission behaviors.
    1. low level restriction – HTML visually disable menu item(s) which the user not allow to activate.
    2. strict restriction - omit from the client any of the item(s) which the user should not know about (will not be part of the client rendered HTML).
  3. Webcontrol server events.
    • OnMenuItemClick
    • OnPrePermissionCheck
    • OnPreRender

      The last two events enable to change the rendering results by subscribing to those events and add custom rendering logic.

  4. Different levels of caching.
    1. Application level (when no permission checks should be done) – the rendered HTML menu will be saved on the Cache object.
    2. User session cache - with or without enforcing permission checks.
    3. No cache mode.
  5. RTL/LTR support.

    All files can be located in language specific direction folder.

  6. Client onClick event handler enhancements.
    1. You can open a clicked menu item link in a new window (dialog or regular), open it in the same page or within an IFrame.
    2. Developers can attach custom client functions that will take place before the menu client logic flow occur. The custom function can override the default behaviour by returning "skip" value which will indicate the menu default function to be skipped. The plug in client side functions are:
      • customOnClick
      • canNavigate – This function can be used to check isDirty flag on the current entry forms and act accordingly.
  7. The following additional custom client side functions can be attached:
    • clientParamsGetFunction

      This function will be called by the menu internal onclick function in order to get additional parameter values that will be used/send in the further steps.

    • clientWindowGetStyleFuncName

      Configure to open a new window (dialog or simple) when menu is clicked. We can attach a function that will return the window display style settings (size, show toolbar etc.).

    • clientWindowAfterCloseEvent

      After a window close, we will call this function if it is defined and send to it any parameter values we got from the window and from the other steps (see clientParamsGetFunction).

  8. PostBack can be done on the current page or within IFrame page when we configure the menu to load pages within IFrames. The function signature that will trigger postback within IFrame loaded pages:
    C#
    menu_doPostback( gCurrentMenu, key, gDefaultLink, url, args);

    Arguments' purposes:

    • gCurrentMenu – not implemented.
    • Key – the clicked menu key. Can be used when we don't want to obligate to specific link like in cases when we are working with UIP Application Block.
    • gDefaultLink – a global link value which we pre-define in menu XML root element metadata. We can use global link when we are working with MasterPage mechanism.
    • url – the URL we pre-define for the menu item.
    • Args – a string delimiter value/pair arguments(&).
  9. Client caching using IFrames.

    When configure the menu items to use IFrames without settings the Postback to true, we achieve client side caching by using IFrames. The moment a menu item is clicked and IFrame mode is on, we check in the client browser if we had already created the IFrame that would hold the clicked menu link page. In case we already have it, we set its display style to visible, otherwise we create it and load it from the server.

It is recommended to use the IFrame configuration when you have pages whose load time is not acceptable and that after they load they can be displayed without the need to go back to the server (E.g. page with huge XML & XSL that enable different filtering and display on the client).

Actually, there are more different configuration options and there is also a way to combine different options and get a mixed behavior.

I download ZIP file including the code of the Web control and 6 simple samples about different ways you can configure the menu metadata XML.

Menu global settings

C#
public struct MenuSettingsType
{
    public string name;
    public bool forcePermission;
    public bool ommitNotAuthMenus;
    public string defaultLink;
    public string customCSSFile;
    public string customJSFile;
    public string customXSLFile;
    public bool recheckPermissionsOnPostBack;
    public bool triggerPostBack;
    public string appFolder;
    public string port;
    public string frameDivHolderID;
    public string customOnClick;
    public bool customOnClickIsInFrame;
    public bool canNavigateIsInFrame;
}

Most of the settings are optional. The following settings can be overridden by specific menu item settings.

C#
public string defaultLink;
public bool triggerPostBack;
public string frameDivHolderID;
public string customOnClick;
public bool customOnClickIsInFrame;
public bool canNavigateIsInFrame;

Menu Item Metadata

C#
//the name (id) of your menu (mandatory)
public const string EL_NAME= "name";
//comma delimiter roles that can access this menu item content (optional)
public const string EL_PERMISSIONS="permissions";
//check the user permissions for this menu item (optional)
public const string EL_FORCE_PERMISSIONS="forcePermission";
//the display name of this menu item (mandatory)
public const string EL_CAPTION="caption";
//the tooltip (optional)
public const string EL_TOOL_TIP="toolTip";
//the mode the menu item will be display (optional)
public const string EL_DISABLED="disabled";
//the default message for tooltip for not authorized user (optional)
public const string EL_ACCESS_DENIED_MESSAGE="accessDeniedMessage";
//not implemented
public const string EL_VISIBLE="visible";
//is the menu clicked should trigger a postback - true/false (optional)
public const string EL_TRIGGET_POSTBACK="triggerPostBack";
//the target link the menu item point to (optional)
public const string EL_LINK="link";
//the valid value: PostBack, Window, Frame (mandatory)
public const string EL_CLIENT_OPEN_TARGET_TYPE="clientOpenTargetType";
//the DIV where the IFRAMES will be located in IFRAME mode
//(mandatory in IFRAME MODE)
public const string EL_CLIENT_FRAMES_DIV_ID="clientFramesDivHolderName";
//your function name that provide additional parameters
//and will be called after a menu item was clicked and before the menu
//item will start its internal logic (optional)
public const string EL_CLIENT_PARAMS_GET_FN="clientParamsGetFunction";
//dialog or window. default is dialog. (optional)
public const string EL_CLIENT_WINDOW_TYPE="clientWindowType";
//the name of your function that will be triggered after a window will be
//closed when menu item open a window (optional)
public const string EL_CLIENT_AFTER_WIN_CLOSE_FN="clientWindowAfterCloseEvent";
//your function name that will be called before a window will open
//and will be use to get the window preferences string (optional)
public const string EL_CLIENT_GET_WIN_STYLE_FN="clientWindowGetStyleFuncName";
//when working in IFRAME mode and you want to use single IFRAME with
//postback to this IFRAME loading page (see attach sample)
//the clientTargetFrameName value should point to your single IFRAME (optional)
public const string EL_CLIENT_TAGET_FRAME_NAME="clientTargetFrameName";
//your custom on menu item click handler (optional)
public const string EL_CLIENT_CUSTOM_CLICK_FN="customOnClick";
//this settings specify where your custom on click function located (optional)
public const string EL_CLIENT_CUSTOM_CLICK_IN_FRAME="customOnClickIsInFrame";
//this settings specify where canNavigate function located (optional)
public const string EL_CLIENT_CAN_NAV_IN_FRAME="canNavigateIsInFrame";

The mandatory elements are:

C#
//the unique name (id) of the menu
public const string EL_NAME= "name";
//the display name
public const string EL_CAPTION="caption";
//There are three types: PostBack or Window or Frame
public const string EL_CLIENT_OPEN_TARGET_TYPE="clientOpenTargetType";

When you are working in frame mode you have to supply a DIV id that will contain the frames (clientFramesDivHolderName). You also have to set with this DIV to your default IFrame.

The XML size depends on the different elements you are using. Most of the menu items metadata elements are optional. Its also depend on the behavior configuration you need - using PostBack to the same page, using IFrame – with postback to IFrame or without and eventually when using windows mode.

The web control, server side functionality

As already mentioned, there are three server side events you can subscribe and change the final results.

C#
public delegate void MenuItemClickedHandler(MenuItemClickedEventArgs e);

public delegate void MenuItemRanderHandler(XmlNode item, out bool skipItem, 
                                           out string xmlAdditionalAttr);

public delegate void MenuItemCheckPermissionHandler(XmlNode menu, 
       string permissions, bool forcePermissions, string caption, 
       string originalToolTip, out bool skip, 
       out bool enable, out string toolTip);

MenuItemClickedEventArgs - includes the following arguments:

  • NextMenu - value which is the menu that was clicked by the user.
  • CurrentMenu – the current display menu (not implemented).
  • AdditionalArgs – hash table name/value of the parameters a user added on the client in a custom client side function.

The MenuItemCheckPermissionHandler event will be fired when forcePermissions will be set to true. There is also internal permission check within the which I have removed and replaced with TODO word. This is the place where you can add your default permission checks using entLib relevant components or other components.

The menu element definition within ASP.NET page

ASP.NET
<?XML:NAMESPACE PREFIX = CC1 /><CC1:DDMENU id=DDMenu1 
dir=ltr MenuName="FramesAndPostBackToFrame"
MenuXMLFileName="FramesAndPostBackToFrame.xml"
MenuXMLRelPath="menu" runat="server">
</CC1:DDMENU>

When using Frame mode you need to add the DIV element where the default IFrame definition is located. The DIV id should be defined within the Menu XML metadata. The Frame ID should be the same as the Menu name element of the default menu item and which also defined within the menu XML metadata.

Important

When working with single IFrame (the default) and postback to IFrame loaded page (like I did in the attached sample), you need to use the menu item element called clientTargetFrameName and set its value to the name of the default, single IFrame.

Samples code files attached

    The sample includes RTL / LTR samples.

  • MenuRTLWithFrames.aspx – right to left display with IFrames cashing.
  • MenuRTLUsingCustomJSFuncs.aspx – right to left display using custom client plug in functions that were configured within the menu XML file.
  • MenuLTRWithPostbacks.aspx – left to right display that shows how to use the server side click event + triggering postbacks for each client menu click.
  • MenuLTRWithFrames.aspx – same as # MenuRTLWithFrames.aspx with left to right display.
  • MenuLTRFrameAndPostBackToFrame.aspx – using a single frame scenario with postback to a function that located within the IFrame loaded page.

Few remarks

  • When you define a global link for all the menu items and you would like that specific menu item located on the first level and the one that has no child will be clickable – you need to define it for the link. This is a known behavior.
  • There are a few of the annoying JavaScript debug alerts in the demo in order that it will be easier to follow the onclick function.
  • The menu onclick functionality with the XML on the client side can be re-used in different UI components and not just in the DDMenu.
  • You are welcome to report any bugs or any feedback regarding the menu in case you decide to use it.
  • You are welcome to add your enhancements to the control and share it with us.

Summary

The article mostly explain the different ways to configure the DDMenu web control. The demo code I added to the ZIP file is simple and straightforward and can assist to understanding how the Web control can configure and work.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
Israel Israel
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 1 Pin
Kailash_Singh26-Sep-11 20:11
professionalKailash_Singh26-Sep-11 20:11 
QuestionTabstrip Pin
filisgreate200022-May-08 6:32
filisgreate200022-May-08 6:32 
GeneralPort to VS2005 Pin
Jim Franz11-May-06 3:47
Jim Franz11-May-06 3:47 
GeneralOmit Some Menu items Pin
vijaybhosale18-Dec-05 23:02
vijaybhosale18-Dec-05 23:02 
QuestionIE6 Z-Order Pin
kesm1-Dec-05 0:28
kesm1-Dec-05 0:28 
QuestionRe: IE6 Z-Order Pin
winx17-Jan-06 22:10
winx17-Jan-06 22:10 
QuestionCan i use this menu to open context menu for each item of datagrid Pin
Amin J. Ismaili27-Oct-05 2:51
Amin J. Ismaili27-Oct-05 2:51 
Generaltransform.Load(xslPath, resolver); Pin
Member 223708220-Sep-05 14:38
Member 223708220-Sep-05 14:38 
QuestionHow to disable some menu item? Pin
Member 22487344-Sep-05 16:16
Member 22487344-Sep-05 16:16 
AnswerRe: How to disable some menu item? Pin
Guy S.5-Sep-05 8:58
Guy S.5-Sep-05 8:58 
GeneralRe: How to disable some menu item? Pin
Member 22487345-Sep-05 9:30
Member 22487345-Sep-05 9:30 
QuestionDisable Cache? Pin
Jonathan Merriweather25-Mar-05 7:39
Jonathan Merriweather25-Mar-05 7:39 
AnswerRe: Disable Cache? Pin
Guy S.25-Mar-05 7:50
Guy S.25-Mar-05 7:50 
QuestionMain menu images? Pin
Jonathan Merriweather24-Mar-05 5:52
Jonathan Merriweather24-Mar-05 5:52 
AnswerRe: Main menu images? Pin
Guy S.24-Mar-05 11:34
Guy S.24-Mar-05 11:34 
GeneralArticle formatting Pin
nsimeonov22-Mar-05 12:10
nsimeonov22-Mar-05 12:10 
Could you please split the line of code after "The menu element definition within ASP.NET page" into 2 shorter - on smaller browser windows the article doesn't wrap and I have to scroll to read it... especially on the smaller monitor... on the 20" one it's just fine but on the smaller I have to scroll all the time Frown | :(
GeneralRe: Article formatting Pin
Guy S.23-Mar-05 9:08
Guy S.23-Mar-05 9:08 
GeneralRe: Article formatting Pin
nsimeonov23-Mar-05 9:16
nsimeonov23-Mar-05 9:16 
GeneralRe: Article formatting Pin
Guy S.23-Mar-05 9:33
Guy S.23-Mar-05 9:33 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.