Menus
Mojo supports four types of menu widgets. You should review the Menu User Interface Guidelines for how best to apply each menu type and for general information on designing menus in your application. Briefly:
- App Menu is a conventional desktop-style menu that drops down from the top-left corner of the screen when the user taps in that area.
- View Menu applies to menus across the top of the screen and can be used as a display header or action buttons.
- Command Menu is used to set a menu at the bottom of the screen.
- Submenu can be used in conjunction with the other menu types or be attached to any element in the page.
The App Menu, View Menu, and Command Menu all use a single model definition with a menu items array, are instantiated through setupWidget, and propagate events via the commander stack. The Submenu shares many of the model properties with the others, but is handled differently, so it is addressed in its own subsection below.
The System UI includes another menu, called the Device Menu, which is anchored to the top right of the screen. This menu cannot be controlled or changed in any way by an application.
Menu Widgets
Unlike all other widgets, Menu widgets are not declared in your scene view file; they are instantiated completely within the scene assistant. The Menu widget is instantiated with a call to setupWidget. Specify the menu type, attributes, and model. The model is primarily made up of the items array, which includes an object for each menu item. Use the visible property in the Menu model to show or hide the menu.
The major options are in the items array. You can have selectable items and groups at the top level of any menu, where groups allow you to specify a second level of selectable items. Items can have a label and an icon, found at iconPath, and through a class assigned icon. The width can be set, overriding the automated sizing, and the item can be selectively disabled. You can bypass most of the item properties and set the item's contents with a template instead.
Each item includes a command value that is propagated through the commander stack when this item is selected. This is a rather significant topic which we'll touch on briefly here, but you should review the Commander Chain to get a full description of this part of the framework.
Please note, it is crucial that you do not stop any event that your application does not fully handle. The Commander Chain is used to propagate a number of Framework events to the appropriate framework and system handlers. If you stop all events in your handleCommand function, or stop events you do not fully handle, some basic functionality of webOS will break.
StageAssistant.prototype.handleCommand = function(event) { this.controller=Mojo.Controller.stageController.activeScene(); if(event.type == Mojo.Event.command) { switch(event.command) { case 'do-myAbout': this.controller.showAlertDialog({ onChoose: function(value) {}, title: $L("My App ? v1.0"), message: $L("Copyright 2008-2009, My Company Inc."), choices:[ {label:$L("OK"), value:""} ] }); break; case 'do-appPrefs': this.controller.pushScene("myAppPrefs"); break; case 'do-appHelp': this.controller.pushScene("myAppHelp"); break; } } };
If you'd like to group several items together, you would include an items array and the toggleCmd which will be set by the framework to the command of the currently selected items in the nested items array.
Items which do not specify any visible attributes (label, icon), and are not groups, are treated as dividers. During layout of the menu buttons, all "extra space" is evenly divided among the dividers. If there are no dividers, then the buttons are evenly spaced.
You can set the checkEnable property to lazily update the enable state of items in the app-menu or submenus. A Mojo.Event.commandEnable event will be sent through the commander chain each time this menu item is displayed or invoked via keyboard shortcut. If a commander calls preventDefault() on the event, then the menu item's model will be modified to disable the menu item. Otherwise it will be enabled. This is useful when a menu item, particularly in the App Menu, is tied to a feature that may or may not be available at a given time. It's used by the framework with the Edit menu to disable the cut/copy/paste options whenever there isn't a text field in focus.
Application Menu
The Application Menu appears in the upper-left corner of the screen when the user taps the left-hand side of the status bar. It includes some system-defined and some application-defined actions, and is intended to have an application-wide scope.
The application list contains a few required actions: Edit, which is a item group including Cut, Copy and Paste; Preferences and Help, both of which are disabled by default. You are free to leave out these default items, or add any other items to the menu, and to enable Preferences and/or Help by hooking them to the appropriate actions for your application.
To create a basic application menu with one item, "About My App", and all default menu items (Preferences, Help, and Edit with Cut, Copy, and Paste):
this.appMenuModel = { items: [ {label: "About My App...", command: 'do-myAbout', shortcut: 'a'} ] }; this.controller.setupWidget(Mojo.Menu.appMenu, {}, this.appMenuModel);
This setup code corresponds to the command handler code sample above. Note the specification of a shortcut key to invoke the command.
Typically, you'd like to have the same Application Menu (or similar menus) presented throughout your application, but it would be painful to replicate the coding in every scene. Earlier we referred to the commander stack and applying that here is helpful. You can place the this.appMenuModel definition and the command handler in your Stage Assistant, and then instantiate the menu in each scene:
this.controller.setupWidget(Mojo.Menu.appMenu, {}, StageController.appMenuModel);
The Stage Assistant will handle all the appMenu functions, but has to be aware of which is the active scene. Note the call to Mojo.Controller.stageController.activeScene() to get that scene in the command handler.
View Menu
The View menu presents items as variable sized buttons, either singly or in groups across the top of the scene. Individual button widths can be adjusted from within the items property width; the framework adjusts the space between the buttons automatically. Using empty list items, you can force items to particular locations on the screen.
You can group buttons together or combine actionable buttons with header information as in this example from the News application:
To instantiate this menu you would use code that puts the back button, newsfeed header and forward button into a single group, adjusting the width of the header to present an integrated look:
this.feedMenuModel = { visible: true, items: [{ items: [ { icon: "", command: '', label: " "}, { label: this.feed.title, width: 210 }, { icon: "", command: '', label: " "} ] }] }; this.controller.setupWidget(Mojo.Menu.viewMenu, { spacerHeight: 0, menuClass:'no-fade' }, this.feedMenuModel);
Typically you would use the View menu for actionable buttons, buttons with an attached Submenu, or header displays as in our News example.
There are two attribute properties for View and Command Menus that differ from the App Menu. The spacerHeight sets the height of the menu items and affects spacing within the scene. By default, this is set to a zero value, causing the menu to float over the scene contents. By setting this height, the scene items are pushed down below the menu. The other property, menuClass, creates a class to use for styling this menu. By default the .view-menu class is used.
Command Menu
The Command Menu presents items at the bottom of the screen. Items will include variable-sized buttons that can be combined into groups. As with the View Menu, button widths can be adjusted from within the items' property width, with the framework automatically adjusting the space between the buttons. You can override positioning by including empty list items to force an item to the right or the middle of the screen, or include an items entry with the disable property set to true.
You can define toggle buttons or include buttons with other dynamic behavior:
You can group buttons together or combine actionable buttons into a selection group as in this example:
To instantiate this menu you would use code that puts the back button, newsfeed header and forward button into a single group, adjusting the width of the header to present an integrated look:
this.cmdMenuModel = { visible: true, items: [ {items:[{label: $L('Back'), icon:'back', command:'back'}, {label: $L('Forward'), icon:'forward', command:'fwd'}]}, {items:[{label: $L('Back'), command:'back'}, {label: $L('Fwd'), command:'fwd'}]} ] }; this.controller.setupWidget(Mojo.Menu.commandMenu, undefined, this.cmdMenuModel);
There are two attribute properties for View and Command Menus that differ from the App Menu. The spacerHeight sets the height of the menu items and effects spacing within the scene. By default this is set to a zero value, causing the menu to float over the scene contents. By setting this height, the scene items are pushed down below the menu. The other property, menuClass, creates a class to use for styling this menu. By default the .view-menu class is used.
Sub-menu
Pop-up sub-menus can be used to offer a transient textual list of choices to the user, typically off of another menu type, or even from a DOM element in the scene. It accepts standard menu models with the addition of some unique properties, but unlike the other menu types, Sub-menu does not use the commander for propagating selections. Instead, the onChoose callback is used.
You can create Sub-menus dynamically:
sceneController.popupSubmenu({ onChoose: this.popupChoose, placeNear: clickEvent.target, items: [ {label: 'Apply', command: 'apply-cmd'}, {label: 'Applique', command: 'applique-cmd'}, {label: 'Applaud', command: 'applaud-cmd'}, {label: 'Approximate', command: 'approx-cmd'} ] });
A modal list will appear with the label choices presented. When the user selects an item, the onChoose function will be called (in the scope of the scene assistant) with the command property of the chosen item. If the user taps outside the popup menu, it's still dismissed, and the onChoose function is called with 'undefined' instead.
Within the items array, you have additional properties as well.