Mobile Common Components
Contents |
Introduction
Each component is a piece of UI that can be used together with other components to build a whole window. Components are defined using enyo that wraps the HTML DOM.
Following enyo's approach, a component can be composed by nested components. When designing new components, this should be kept in mind in order to create smaller components that could be reused.
Openbravo Mobile Core provides a palette of common components that can be reused to create your own ones. The aim of this document is to present some of them, explaining how they can be adapted to be used in different places.
Layout
The components explained in this section are used to compose the layout of the application.
Terminal
It is the holder where the rest of windows are rendered in.
Detailed information can be found in its main article.
Window
Windows are components that are rendered in the terminal, they can be navigated from the menu or opened programmatically.
Further information can be found in its main article.
Multi Column Layout
The standard layout for mobile windows consists in two columns designed to properly work in different mobile devices. But this is optional. You can create your own window component.
As shown in the image above, the standard layout is two column. But, if the device width is not wide enought (less than 800px), the layout auto-switches to single column (image below).
Each of these two columns are composed by a Toolbar at the top and a Panel. The Toolbar holds the buttons and the Panel holds the contents. In single column mode, a Column switcher button is automatically added to the toolbar, this button allows the user to navigate from one column to the other (it is also possible to swipe between columns).
If you want a window to support this layout, OB.UI.MultiColumn
must be its main component:
enyo.kind({ name: 'OB.MYMODMyWindow.UI.MyWindow', kind: 'OB.UI.WindowView', windowmodel: 'OB.MYMODMyWindow.Model.MyWindow', components: [{ kind: 'OB.UI.MultiColumn', name: 'multiColumn', leftToolbar: { kind: 'OB.MYMODMyWindow.LeftToolbar' }, leftPanel: { kind: 'OB.MYMODMyWindow.LeftPanel' }, rightToolbar: { kind: 'OB.MYMODMyWindow.RightToolbar' }, rightPanel: { kind: 'OB.MYMODMyWindow.RightPanel' } }], init: function(model) { ... } });
OB.UI.MultiColumn
kind expects the following attributes:
leftToolbar
andrightToolbar
: Define the kinds that will render the left and right column toolbars. They should inherit fromOB.UI.MultiColumn.Toolbar
kind, as detailed in the next sectionleftPanel
andrightPanel
: Define the kinds that will render the left and right columns panels. The kind these ones can inherit is open, so they can implement the UI required for the window
Toolbar
enyo.kind({ name: 'OB.MYMODMyWindow.LeftToolbar', kind: 'OB.UI.MultiColumn.Toolbar', showMenu: true, buttons: [{ kind: 'OB.MYMODMyWindow.ButtonNew', span: 3 }, { kind: 'OB.MYMODMyWindow.Button2', span: 3 }, { kind: 'OB.MYMODMyWindow.Button3', span: 6 }] });
OB.UI.MultiColumn.Toolbar
is the component that is used to represent the toolbar in a multicolumn layout.
It has 3 kind of buttons:
- Menu. The Menu button is always positioned in the left side of the toolbar. When it is tapped, the standard menu is dropped down. To show this button in the toolbar, the
showMenu
property must betrue
. - Column switcher. This button allows to switch from the left to the right column and vice versa. It is displayed in the right side of the left toolbar and in the left side of the right toolbar when the browser's width resolution is narrow (less than 800px). It is managed by the layout, so it is not necessary to write any code to deal with it.
- Custom buttons. These are the buttons that provide custom functionality to the toolbar. Check for details in the next section. The
span
property determines their width; the summed amount of all buttons in a toolbar must be exactly 12.
Toolbar Custom Buttons
E.g.: the new button
enyo.kind({ name: 'OB.MYMODMyWindow.ButtonNew', kind: 'OB.UI.ToolbarButton', icon: 'btn-icon btn-icon-new', events: { onNewDocument: '' }, tap: function () { this.setDisabled(true); this.doNewDocument(); } });
Toolbar custom buttons are placed inside a toolbar, they are OB.UI.ToolbarButton
kind (extend from).
- the
icon
property is a CSS class containing the icon to display in the button - the
tap
function is executed when the button is tapped or clicked. Note that the components are UI representations. So this logic, in general, should be restricted to trigger an event that will be caught by the window containing the toolbar. In the code above,doNewDocument
will trigger theonNewDocument
event. This way, this button can be reused by different toolbars in different windows, each of them handling theonNewDocument
event and implementing their own logic
Buttons can be disabled/enabled using their setDisabled
method.
Empty Toolbar
Some windows won't require any button. But, even in this cases, the toolbar is still needed to show the menu button as well as the column switcher. OB.UI.MultiColumn.EmptyToolbar
is a convenience kind to do it:
enyo.kind({ name: 'OB.MYMODMyWindow.MyEmptyToolbar', kind: 'OB.UI.MultiColumn.Toolbar', showMenu: true, buttons: [{ kind: 'OB.UI.MultiColumn.EmptyToolbar', i18nLabel: 'MYMODMyWindow_ToolbarTitle' }] });
This component displays a toolbar with a title. The toolbar title is defined in the i18nLabel
and points to the localizable Search Key labeled MYMODMyWindow_ToolbarTitle that must have been added within the backend.
Menu
Windows in mobile applications can display a standard menu.
Menu is configured at toolbar level. To make the menu button available, showMenu
option must be set to true
.
Menu is composed by different types of options:
- Session indicator: It is always the first menu option and cannot be hidden. It indicates whether the session is currently online or offline. When the user taps on it, a popup is opened. This popup allows the user to end the session.
- Custom menu entries: These block of entries are the custom ones created for the window. These entries can be programmatically added based on the window's needs. The next section explains how to add new custom entries.
- Standard menu entries: Menu can, optionally, display entries that allow to navigate to the rest of registered windows. To display this section, the
showWindowsMenu
toolbar property must be set totrue
. - Profile: The last entry is always the profile one. When user taps on it, a popup displaying the current profile's info is shown. From it, it's possible to open another one and change the profile settings. The options available in this second pop up can be configured at terminal level through the
profileOptions
property.
enyo.kind({ kind: 'OB.UI.MultiColumn.Toolbar', showMenu: true, // makes the menu available showWindowsMenu: true, // shows entries for standard windows // menuEntries defines custom entries menuEntries: [{ kind: 'OB.UI.MenuAction', i18nLabel: 'MYMOD_EntryName1', eventName: 'onMyAction1', permission: 'MYMOD_Action1Permission', }, {kind: 'OB.UI.MenuSeparator'}, { kind: 'OB.UI.MenuAction', i18nLabel: 'MYMOD_EntryName2', eventName: 'onMyAction2', }], ... });
Custom menu entries are defined by the menuEntries
toolbar property. It is an array of OB.UI.MenuAction
kinds. These are the properties:
-
kind
:OB.UI.MenuAction
the kind of the menu entries -
i18nLabel
: The search key of the message that will be used as label -
eventName
: It is the enyo event that will be bubbled when the user selects this option -
permission
: Preference that will be used to grant access to this entry, see Mobile_Security_Model. In case this property is not defined. Everyone will have access
![]() | It is possible to add a separator, rendered as a gray line, between two entries by adding a OB.UI.MenuSeparator kind in between them.
|
Keyboard
enyo.kind({ kind: 'OB.UI.Keyboard', sideBarEnabled: true, initComponents: function() { // initialize keyboard with needed customizations } });
Keyboard is the main component to allow user data input.
Keyboard components extend OB.UI.Keyboard
enyo kind. A keyboard is composed by 3 elements: toolbar, keypad and sidebar. These elements can be customized when defining a new keyboard.
Keyboard's Toolbar
The very left column of buttons, is the toolbar (see image above). Each of the buttons in the toolbar represents a different command. For the user, there are two ways of executing these commands:
- the first one, is tapping on the toolbar button before entering any data with the keyboard. Doing so, the button gets selected, and then, the user can enter the data and tap the enter key. If enter is tapped without having selected any button, keyboard
defaultcommand
function is executed (in case it was defined) - the second one is entering data without having any button selected and tapping on the button afterwards.
It is possible to add a new toolbar to a keyboard. Check this sample below (Note that the code goes inside the initComponents method of the keyboard):
initComponents: function() { ... this.addToolbar({ name: 'myToolbar', buttons: [{ command: 'myCommand', label: OB.I18N.getLabel('OBPOS_KbCode'), classButtonActive: 'btnactive-blue', definition: { action: function(keyboard, txt) { // implement logic here } } } // additional buttons can be added in this array ], shown: function() { var keyboard = this.owner.owner; keyboard.showKeypad('basic'); keyboard.showSidepad('sideenabled'); keyboard.defaultcommand = 'myCommand'; }); ... }
The addToolbar
method receives a plain javascript object, let's see the properties it has:
name
: Unique name that identifies this toolbar among all the toolbars defined in the keyboard. Executekeyboard.showToolbar('myToolbar')
to show a toolbarbuttons
: Array of buttons that are part of the toolbar. Each of these buttons are objects with the following properties:command
: Command executed by this buttonlabel
: Label displayed in the buttonclassButtonActive
: CSS class that will be applied when the button is active
shown
: Function that is executed when the toolbar is shown (keyboard.showToolbar
is invoked)definition
: Function implementing the logic for the command. Alternatively, this property can not be present and adding the command implementation as seen in Implementing commands section
Keypad
It is the central set of keys that enables the user to add information (see image above). By default, there's a numeric keypad, but it is possible to define custom ones. A keyboard can have multiple keypads being possible to switch between them regarding some action.
A new keypad can be created as an enyo component and added to the keyboard using the keyboard's addKeypad
method. New keypad components need to have a padName
property that is used to show it using showKeypad
method in the keyboard. By default, all keyboards have a numeric keypad named basic.
Sidebar
Currently the buttons displayed in the side bar are not customizable. There are two out of the box sidebars:
sidedisabled
: All buttons are disabled. It's the default sidebarsideenabled
: All buttons are enabled. When using this sidebar,OB.UI.Keyboard
needs to implement the commands (see next section). Here is the list of buttons and their commands:- + and - executing + and - commands
- Quantity executing line:qty command
- Price executing line:price' command
- Discount executing line:dto command
Implementing commands
Commands can be implemented in keyboard's initComponents
method. Note that this should be done before invoking the parent's constructor this.inherited(arguments)
.
initComponents: function() { ... this.addCommand('line:price', { permission: 'OBPOS_order.changePrice', action: function(keyboard, txt) { if (keyboard.line) { keyboard.receipt.setPrice(keyboard.line, OB.I18N.parseNumber(txt)); keyboard.receipt.trigger('scan'); } } }); ... this.inherited(arguments); }
Commands are added to the toolbar with the addCommand
method. It receives two arguments:
- Command name: A string that matches the command name
- Implementation: Consists on a plain javascript object with the following properties:
permission
: (optional) Allows to secure the command. If this preference has not been defined in the backend, the command won't execute. See Mobile_Security_Modelaction
: Function invoked when the command is executed. It receives as parameter a reference to the keyboard and the current text the user has entered
Confirmation popups
Confirmation popups are modal popups displaying a message and a set of buttons. They are shown by invoking the OB.UTIL.showConfirmation.display(title, msgText, buttons, options)
method.
OB.UTIL.showConfirmation.display( // title OB.I18N.getLabel('OBWH_DeleteDocumentTitle'), // msgText OB.I18N.getLabel('OBWH_DeleteDocumentText'), // buttons [{ label: OB.I18N.getLabel('OBWH_DeleteLbl'), action: function () { me.setDisabled(true); me.bubble('onDeleteDocument'); } }, { label: OB.I18N.getLabel('OBMOBC_LblCancel') }], // options { onShowFunction: function (popup) { //executed when the popup is opened }, onHideFunction: function (popup) { //something to do when the popup //is closed without use an action }, style: 'background-color: #EBA001' } );
Parameters in detail:
title
: Title of the popupmsgTex
: Text content of the popupbuttons
: Array of javascript plain objects defining each of the buttons (it can have many). If no button is defined, it will be renedered with a single OK button that will close the popup when it is taped. The properties for each button are:-
label
: Text inside the button -
action
: Function to be executed when the user taps the button. The default action, if none is defined, will be to close the popup
-
options
:-
style
: Indicates the CSS style of the popup container -
onShowFunction
: If defined, this function will be executed when the popup is shown. Here you can navigate (the popup is passed as a parameter) through the UI components. E.g.: the CSS class of a button could be changed -
onHideFunction
: This method is executed if noaction
is executed when the popup closes. E.g.: let's say we made a popup with two buttons, 'ok' and 'cancel'. The 'ok' button does some action like accepting a ticket and the 'cancel' button just closes the popup. In this scenario, the 'onHideFunction' will not be executed in the 'ok' button cause it has an action defined, but it will be executed in the 'cancel' button.
-
If defined, this function will be executed when the popup is hidden without executing actions. It means that this function will be executed using the background, the close (x) button or a button which doesn't defines an action.
Complex modal windows
When confirmation poupups are not enough, it is possible to define modal popups with any arbitrary content.
enyo.kind({ name: 'OBWH.Movement.ProductSearch', kind: 'OB.UI.Modal', i18nHeader: 'OBWH_Product', body: { kind: 'OBWH.Movement.ProductSearchList', } });
The kind implementing the modal window extends OB.UI.Modal
, the properties it defines are:
i18nHeader
: With the Search Key of the message that will be displayed as the popup's titlebody
: Popup implementation. Here, you can define any kinds you need to render your contents
This code should be to add a popup to a window:
enyo.kind({ name: 'OBWH.Movement.View', kind: 'OB.UI.WindowView', windowmodel: OBWH.Movement.Model, components: [{ kind: 'OB.UI.MultiColumn', ... }, { kind: 'OBWH.Movement.ProductSearch', name: 'modalProductSearch' }] });
It is important to name this popup because that name will be used to identify that popup in the open and close events.
Showing a popup
To show a popup, the event doShowPopup
must be thrown. This event will receive two parameters:
- the name of the popup that we want to show.
- args to be received by the
executeOnShow
function of the affected popup
this.doShowPopup({ popup: 'mymodalname' }); //Args can be added to the event. This args will be saved in the popup component. This args can be read from the popup component using "this.args". //The function executeOnHide of the popup will be executed. this.doShowPopup({ popup: 'mymodalname', args: myParameters });
Hiding a popup
From inside
To hide a popup from a button that is inside the popup, the event doHideThisPopUp
must be thrown, and the current popup will be hiden.
this.doHideThisPopup(); //Args can be added to the event. This args will be saved in the popup component. This args can be read from the popup component using "this.args". //The function executeOnHide of the popup will be executed. this.doHideThisPopup({args: myParameters});
From another component
To hide a popup from other component, the event doHidePopup
must be thrown. This event will receive two parameters:
1. the name of the popup that we want to hide
2. args to be received by the executeOnHide
function of the affected popup
this.doHidePopup({ popup: 'mymodalname' }); //Args can be added to the event. These args will be saved in the popup component. These args can be read from the popup component using "this.args". //The function executeOnHide of the popup will be executed. this.doHidePopup({ popup: 'mymodalname', args: myParameters });
Adding a popup from other module
How to create a new modal from a module