Albeit very flexible, writing an <a> tag inside every item can sometimes become a pain. For items that open URL-s, writing normal link tags makes sense, because they ought to work in any browser, even text-mode browsers. However, for items that execute JavaScript code dynamically, a more appropriate method can be used, starting with version 2.4 of DynarchMenu.
While still uses plain HTML syntax in order to setup handlers, unified action handlers allow you to catch events in a single function, and pass to that function enough arguments to help determining what item has been clicked.
Defining the menu is plain easy, as usual:
<ul id="menu" onclick="master_handler(this)"> <li>Item 1</li> <li>Item 2</li> <li> Item 3 <ul> <li>SubItem 3.1</li> <li>SubItem 3.2</li> </ul> </li> </ul>
As you can see above, we defined a normal list with items that apparently define no actions. However, there's one special bit: the definition of an onclick handler in the toplevel UL element. This handler calls a function defined by you, and passes to it one parameter: “this”. Contrary to what might seem obvious, “this” won't pass a reference to the UL element, but to an action object used internally by DynarchMenu. This action object has properties that help to uniquely identify the clicked item. Following there is an example of function that simply displays the item label:
function master_handler(action) { var menu_item = action.info; alert(menu_item.label); }
We first determine the menu item object and then display its label by using the label property. The item object contains lots of interesting properties and methods that allow you to enable or disable it, show or hide it, change its label or icon (if an icon is present), etc. Read more about it.
The “action” object additionally contains a “params” property which is a reference to the LI element associated to the item. This is useful if you want to pass additional properties to your action handler. For instance:
<script type="text/javascript"> function my_handler(action) { var li = action.params; alert(li.title); }; </script> <ul id="menu" onclick="my_handler(this)"> <li title="We can pass this">Item 1</li> <li title="And this too">Item 2</li> </ul>
The above code shows how you can retrieve the “title” attribute from the LI tag associated with the clicked menu item. Using what Microsoft calls “expando properties” we can push this even further:
<script type="text/javascript"> function my_handler(action) { var li = action.params; var arg1 = li.getAttribute("arg1"); var arg2 = li.getAttribute("arg2"); alert("arg1 = " + arg1 + "\narg2 = " + arg2); }; </script> <ul id="menu" onclick="my_handler(this)"> <li arg1="We can pass this" arg2="fubar">Item 1</li> <li arg1="And this too" arg2="baz">Item 2</li> </ul>
The technique above allows you to pass multiple parameters to your action handler; as you can see in the example, we passed 2 arguments that are not defined in the HTML standard (“arg1” and “arg2”). This makes pages that will not validate; our opinion is that it shouldn't matter all that much, but yours might vary.
Yes! :-) You can. Here's the (obvious) example:
<ul id="menu" onclick="master_handler(this)"> <li> <a href="http://www.dynarch.com/">Item 1</a> </li> <li>Item 2</li> <li> <a href="javascript:alert('foobar')">Item 3</a> </li> </ul>
The above menu defines 3 items. “Item 1” will open the URL, “Item 3” will display “foobar” and “Item 2” will go through the default handler which can do anything. So, the golden rule is, items that define actions will behave as usual, and items that don't define actions will go through the master handler, if present.
We'd say it does, and DynarchMenu supports it. Here's an example:
<ul id="menu" onclick="master_handler(this)"> <li>Item 1</li> <li> Item 2 <ul onclick="secondary_handler(this)"> <li>SubItem 2.1</li> <li>SubItem 2.2</li> <li>SubItem 2.3</li> <li onclick="third_handler(this)"> SubItem 2.4 <ul> <li>SubItem 2.4.1</li> <li>SubItem 2.4.2</li> <li>SubItem 2.4.3</li> </ul> </li> </ul> </li> <li>Item 3</li> </ul>
The above menu shows some possible combinations. As you can see, there's a “master_handler” assigned to the toplevel UL. That will be called for “Item 1”, “Item 2” and “Item 3”, because it's the “closest”, so to say, handler above them.
However, there's also a “secondary_handler” defined in the submenu of “Item 2”, which will get called for “SubItem 2.1”, “SubItem 2.2” and “SubItem 2.3”.
“SubItem 2.4”, as you can see, defines a “third_handler”, which will get called for “SubItem 2.4.1”, “SubItem 2.4.2” and “SubItem 2.4.3”. Note that this time the handler is defined on a LI element, instead of UL, but even so, the LI that defines it (2.4) won't trigger any handler because an item that has a submenu will not go through the unified handlers.
So the above example should clear any confusion: the “onclick” attribute can be defined on any UL or LI element involved in the menu. When an item that doesn't define an action in the classical way is clicked, the chain of elements is parsed backwards and the first onclick hander found will be called. And that's all there is to it.