Skip to content

PopupMenu 2.x

AlexanderLitus edited this page Aug 14, 2014 · 8 revisions

TOCSTART

TOCEND

PopupMenu is a component that displays a set of actions in a pop-up box for a user to choose from, and is often used as a context menu. The PopupMenu component can be attached to any component to appear when any particular event occurs in that component. A PopupMenu can be configured to have sub-menus to represent complex hierarchies of actions. A user can either use keyboard or a mouse to select an item in a PopupMenu.


Online Demo

Key Features

Basic Usage

The simplest way to create a PopupMenu component is to place the <o:popupMenu> tag into a component to which the PopupMenu should be attached. This will make the PopupMenu to be shown when the user clicks the right mouse button over the parent component (that is the menu is attached to the parent's "contextmenu" event by default). The parent component's event which should invoke the popup menu can be customized using the event attribute of the <o:popupMenu> tag. Popup menu's items are specified by placing one or more <o:menuItem> tags into the <o:popupMenu> tag.

Here's a simple example of declaring the PopupMenu component for a <h:panelGroup> component:

<h:panelGroup id="itemView" ...>
  <o:popupMenu>
    <o:menuItem value="Select Item" onclick="selectItem();"/>
    <o:menuItem value="Unselect Item" onclick="unselectItem();"/>
    <o:menuSeparator/>
    <o:menuItem value="Update This View" action="#{MyBean.updateView}" render="itemView"/>
    <o:menuSeparator/>
    <o:menuItem value="Show Main View" action="#{MyBean.showMainView}"/>
  </o:popupMenu>
  ...
</h:panelGroup>

As you can see from the example above, using <o:menuItem> is very similar to using ordinary command components such as <h:commandButton> or <h:commandLink> – the text displayed in the item is specified with the value attribute, and you can define the menu item activation event handler in different ways:

  • Pure client-side event handling using the onclick attribute.
  • Ajax event handling using the built-in render and execute attributes.
  • Server-side event handler with form submission using the action attribute.

You can turn on the Ajax mode and configure the button to reload the specified set of components instead of reloading the whole page by specifying its render attribute. This attribute is specified as a space-separated list of component Ids in the same way as the render attribute of the Ajax component. Specifying this attribute will also make action and/or actionListener specified for the button to be executed during the Ajax request as well. If the Ajax mode is turned on for the button it doesn't submit data for form's components for processing on the server by default, so if you'd like to include some particular components into the Ajax request, for their data to be available during action execution or be saved through bindings, you can specify the execute attribute. Like the action attribute, this attribute is specified as a space-delimited list of component Ids in the same way as for the Ajax component.

The separator between menu items can be specified with the <o:menuSeparator> tag.

Besides using the PopupMenu component with mouse, it allows item navigation with Up/Down keys, sub-menu navigation with Left/Right keys and item selection with the Enter key.

Among the other frequently-used ways of customizing the PopupMenu are the possibilities to add sub-menus, place the icon besides a menu icon, and specify a non-text item content. Sub-menu can be added just by placing another <o:popupMenu> tag inside of the appropriate <o:menuItem> tag. The iconUrl attribute specified for the <o:menuItem> tag lets you specify the icon that should be displayed in the menu's indent area to the left of the menu item. And finally, in cases when you need to specify a more sophisticated item's content than just plain text, which might be required to fulfill some specific design requirements, you can skip using the value attribute, and specify any components that should be displayed in a menu item as child tags for the <o:menuItem> tag. Here's an example that shows declaring a menu with sub-menus, icons besides menu items, and the content of the root items displayed with images instead of text.

<o:popupMenu>
  <o:menuItem>
    <o:graphicImage url="icons/new.png">
    <o:popupMenu>
      <o:menuItem iconUrl="icons/newItem.png" value="Item" onclick="newItem();"/>
      <o:menuItem iconUrl="icons/newCategory.png" value="Category" onclick="newCategory();"/>
    </o:popupMenu>
  </o:menuItem>
  <o:menuItem>
    <o:graphicImage url="icons/edit.png">
    <o:popupMenu>
      <o:menuItem iconUrl="icons/cut.png" value="Cut" onclick="cut();"/>
      <o:menuItem iconUrl="icons/copy.png" value="Copy" onclick="copy();"/>
      <o:menuItem iconUrl="icons/paste.png" value="Paste" onclick="paste();"/>
    </o:popupMenu>
  </o:menuItem>
  <o:menuSeparator/>
  <o:menuItem>
    <o:graphicImage url="icons/editItem.png"> 
  </o:menuItem>
  <o:menuItem>
    <o:graphicImage url="icons/deleteItem.png"> 
  </o:menuItem>
</o:popupMenu>

There are also some attributes that define certain aspects of PopupMenu's behavior. The disabled attribute of <o:menuItem> tag allows disabling a menu item so that it cannot be activated by the user. The submenuShowDelay and submenuHideDelay attributes of <o:popupMenu> tag allow customizing the period between mouse movement over (or out) the parent menu item and automatic menu showing (or hiding). These values are specified in milliseconds and the default value for both is 500, which corresponds to a half of a second. You can turn off automatic sub-menu showing and/or hiding by specifying -1 in the appropriate attribute(s).

The Three Invocation Modes

As it was described in the previous section, the simplest way of invoking the PopupMenu is binding it for automatic invocation by placing it into a component for which it should be invoked. By default, the PopupMenu will be invoked when "contextmenu" event is triggered into the parent component, which basically means showing the PopupMenu on right mouse click (or via ctrl-click in Opera browser where right mouse click cannot be intercepted). The event to which the PopupMenu is attached can be customized with the event attribute of <o:popupMenu> tag. Be sure to specify the event name without the "on" prefix, for example you should use the "click" value instead of "onclick", like this:

<h:panelGroup ...>
  <o:popupMenu event="click">
    ...
  </o:popupMenu>
  ...
</panelGroup>

Albeit simple, the first approch of automatic PopupMenu binding by adding it inside of a component works only for JSF components and can't be used if you need to bind a PopupMenu to an HTML tag that is just part of page's markup and is not a JSF component.

The second way of how PopupMenu invocation can be configured is placing the <popupMenu> tag outisde of the component or HTML element to which it should be attached, and referring that component/element by declaring the for attribute of the <popupMenu> tag. The for attribute should be assigned with the id of a JSF component or id of any HTML element, whose event should be listened to. Here's a formal description of how this attribute should be defined:

  • The first way of specifying this attribute is for referencing JSF components and it is similar to the way of specifying the for attribute of the standard <h:outputLabel> and <h:message> tags. It can either be an "absolute" identifier that begins with a colon and includes ids of all naming container parents, such as ":form:button1", or it can be a relative identifier that refers to another child in the same naming container, for example "button2". The formal rules of finding the component by identifier are described in API reference for the UIComponent.findComponent() method.
  • The second way of specifying this attribute is for referring HTML elements rather than JSF components. Referring to HTML elements is similar to referring JSF components with an absolute identifier – you just need to prepend actual element id with a colon symbol. For example in order to refer a an HTML button tag declared as <input id="myHtmlButton" type="button" value="Test"/> you should use the ":myHtmlButton" value of the for attribute.

And finally, there's one more way of invoking the PopupMenu component called a "standalone" invocation mode, where a PopupLayer can be declared anywhere on the page and then shown programmatically using client-side API, which provides the full control over how and when the PopupLayer should be shown and/or hidden. This mode is turned on by declaring the standalone attribute with a value of "true". Doing so turns off automatic PopupMenu binding to a parent component (or a component referred to by the for attribute). The PopupMenu in the standalone mode can be shown using one of the following methods: show(), showAtXY(x, y), or showForEvent(event). You can choose the method that suits the desired PopupMenu positioning algorithm (see the Client-Side API section for the description of these methods). Regardless of the mode, the PopupMenu is hidden automatically when a menu item is chosen, Esc pressed, or mouse clicked outside of the PopupMenu, and it's also possible to hide the PopupMenu programmatically with the client-side hide() function. Study the Client-Side API section for the full list of methods that can be used to inspect and manipulate the state of the PopupMenu component.

Customizing Menu Appearance

By default, a PopupMenu displays an indent area on the left of the menu for menu item icons. Visibility for the indent area can be customized using the indentVisible attribute of the <o:popupMenu> tag, and its style is customized with the indentStyle/indentClass attributes.

You can learn the full set of customization options by reading the tag library documentation for <o:popupMenu>, <o:menuItem> and <o:menuSeparator>.

Client-Side API

All client-side API methods are listed in the following table:

   Method   
Description
show() Displays the PopupMenu at its current position as defined by the component's placement in the page's source code or the position specified explicitly with setLeft and setTop methods.
showAtXY(x, y) Displays the PopupMenu component at the specified absolute x and y coordinates
showForEvent(event) Displays the PopupMenu component at the current mouse coordinates according to the passed event object.
hide() Hides the PopupMenu component.
setLeft(x) Sets the integer x coordinate in pixels that will be used by the show() function.
setTop(y) Sets the integer y coordinate in pixels that will be used by the show() function.
isVisible() Returns true if the PopupMenu is visible.
getLeft() Returns the x coordinate of the top-left corner of the PopupMenu in pixels.
getTop() Returns the y coordinate of the top-left corner of the PopupMenu in pixels.
focus() Gives the keyboard focus to the PopupMenu component on which this method is invoked.
blur() Removes the keyboard focus from the PopupMenu component on which this method is invoked.

There are also the following methods for manipulating individual <o:menuItem> components (you can locate an of menu item component on client-side by its client id for invoking these methods):

Method Description
getDisabled() Returns a boolean value that specifies whether this menu item is disabled.
setDisabled(disabled) Specifies whether the menu item should be in a disabled state.