Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Omnis Webdev

Download as pdf or txt
Download as pdf or txt
You are on page 1of 308

Creating Web &

Mobile Apps
Using the Omnis JavaScript Client

TigerLogic Corporation
Sept 2013
28-092013-01
The software this document describes is furnished under a license agreement. The software may be
used or copied only in accordance with the terms of the agreement. Names of persons, corporations, or
products used in the tutorials and examples of this manual are fictitious. No part of this publication may
be reproduced, transmitted, stored in a retrieval system or translated into any language in any form by
any means without the written permission of TigerLogic.
© TigerLogic Corporation, and its licensors 2013. All rights reserved.
Portions © Copyright Microsoft Corporation.
Regular expressions Copyright (c) 1986,1993,1995 University of Toronto.
© 1999-2013 The Apache Software Foundation. All rights reserved.
This product includes software developed by the Apache Software Foundation
(http://www.apache.org/).
OMNIS® and Omnis Studio® are registered trademarks of TigerLogic Corporation.
Microsoft, MS, MS-DOS, Visual Basic, Windows, Windows 95, Win32, Win32s are registered
trademarks, and Windows NT, Visual C++ are trademarks of Microsoft Corporation in the US and other
countries.
SAP, R/3, mySAP, mySAP.com, xApps, xApp, and other SAP products and services mentioned herein
as well as their respective logos are trademarks or registered trademarks of SAP AG in Germany and
in several other countries all over the world.
IBM, DB2, and INFORMIX are registered trademarks of International Business Machines Corporation.
ICU is Copyright © 1995-2003 International Business Machines Corporation and others.
UNIX is a registered trademark in the US and other countries exclusively licensed by X/Open Company
Ltd.
Sun, Sun Microsystems, the Sun Logo, Solaris, Java, and Catalyst are trademarks or registered
trademarks of Sun Microsystems Inc.
J2SE is Copyright (c) 2003 Sun Microsystems Inc under a licence agreement to be found at:
http://java.sun.com/j2se/1.4.2/docs/relnotes/license.html
MySQL is a registered trademark of MySQL AB in the United States, the European Union and other
countries (www.mysql.com).
ORACLE is a registered trademark and SQL*NET is a trademark of Oracle Corporation.
SYBASE, Net-Library, Open Client, DB-Library and CT-Library are registered trademarks of Sybase
Inc.
Acrobat is a trademark of Adobe Systems, Inc.
Apple, the Apple logo, AppleTalk, and Macintosh are registered trademarks and MacOS, Power
Macintosh and PowerPC are trademarks of Apple Computer, Inc.
HP-UX is a trademark of Hewlett Packard.
OSF/Motif is a trademark of the Open Software Foundation.
CodeWarrior is a trademark of Metrowerks, Inc.
This software is based in part on ChartDirector, copyright Advanced Software Engineering
(www.advsofteng.com).
This software is based in part on the work of the Independent JPEG Group.
This software is based in part of the work of the FreeType Team.
Other products mentioned are trademarks or registered trademarks of their corporations.
Table of Contents

Table of Contents
ABOUT THIS MANUAL.....................................................6

CHAPTER 1—TUTORIAL.................................................7
STARTING OMNIS.....................................................................8
CREATING A LIBRARY .............................................................9
CREATING A DATABASE SESSION ..........................................11
OPENING A DATABASE SESSION ............................................13
VIEWING YOUR TABLES .........................................................14
VIEWING YOUR DATA ............................................................15
MAKING A SCHEMA ...............................................................16
EDITING A SCHEMA ...............................................................17
CREATING A DESKTOP FORM .................................................18
EDITING A DESKTOP FORM ....................................................21
TESTING A DESKTOP FORM AND INSERTING DATA ................25
CREATING A WEB FORM........................................................28
ADDING FIELDS TO A WEB FORM ..........................................30
ADDING CODE AND FURTHER FIELDS TO A FORM ..................32
ADDING A PICTURE AND A BUTTON TO A FORM ....................37
ADDING A REMOTE TASK ......................................................41
TESTING YOUR WEB FORM....................................................42
TESTING YOUR FORM ON A MOBILE DEVICE .........................44
SUMMARY .............................................................................46
TUTORIAL LIBRARIES ............................................................46
WELCOME WINDOW ..............................................................47
CHAPTER 2—JAVASCRIPT REMOTE FORMS.........48
CREATING JAVASCRIPT REMOTE FORMS ...............................48
REMOTE TASKS .....................................................................55
REMOTE FORM PROPERTIES ..................................................63
REMOTE FORM INSTANCES AND METHODS ...........................67
CLIENT COMMANDS ..............................................................70
REMOTE FORM EVENTS.........................................................73
CLIENT METHODS..................................................................76
TESTING JAVASCRIPT REMOTE FORMS ..................................81
REMOTE MENUS ....................................................................85
SUBFORM SETS ......................................................................87
RESIZABLE FORMS AND COMPONENTS ..................................93
RUNNING JAVASCRIPT IN THE CLIENT ...................................95
STYLED TEXT ........................................................................97

3
Table of Contents

ANIMATIONS..........................................................................98
TIME ZONES AND DATES .......................................................99
PDF PRINTING .....................................................................100
CHAPTER 3—JAVASCRIPT COMPONENTS ...........108
JAVASCRIPT COMPONENT PROPERTIES................................110
JAVASCRIPT COMPONENT EVENTS ......................................115
JAVASCRIPT COMPONENT ICONS .........................................116
ACTIVITY CONTROL ............................................................120
BACKGROUND CONTROL .....................................................120
BAR AND PIE CHART CONTROL ...........................................122
BUTTON CONTROL ..............................................................124
CHECKBOX CONTROL ..........................................................125
COMBO BOX ........................................................................126
COMPLEX GRID ...................................................................128
DATA GRID CONTROL .........................................................130
DATE PICKER CONTROL ......................................................135
DEVICE CONTROL................................................................137
DROPLIST CONTROL ............................................................145
EDIT CONTROL ....................................................................146
FILE CONTROL .....................................................................148
HTML OBJECT....................................................................150
HYPERLINK CONTROL .........................................................153
LABEL OBJECT ....................................................................153
LIST CONTROL.....................................................................154
MAP CONTROL ....................................................................158
NAVIGATION BAR CONTROL................................................161
PAGE CONTROL ...................................................................163
PAGED PANE .......................................................................163
PICTURE CONTROL ..............................................................164
PIE CHART CONTROL...........................................................165
POPUP MENU CONTROL.......................................................165
PROGRESS BAR CONTROL ...................................................166
RADIOGROUP CONTROL ......................................................167
RICH TEXT EDITOR CONTROL .............................................169
SLIDER CONTROL ................................................................170
SUBFORM ............................................................................171
SWITCH CONTROL ...............................................................173
TAB CONTROL .....................................................................174
TIMER CONTROL .................................................................176
TRANS BUTTON CONTROL...................................................176
TREE CONTROL ...................................................................177
VIDEO CONTROL .................................................................182

4
Table of Contents

CHAPTER 4—CREATING APPS USING IOS CLIENT184


REQUIREMENTS ...................................................................185
CREATING REMOTE FORMS FOR IOS ....................................186
IOS FORM PROPERTIES AND METHODS ............................... 196
IOS FORM EVENTS .............................................................. 198
IOS COMPONENTS ............................................................... 200
CREATING AN OMNIS IOS APP .............................................235
TESTING YOUR OMNIS IOS APP............................................237
DEPLOYING YOUR OMNIS IOS APP .......................................240
CHAPTER 5—ULTRA-THIN OMNIS ..........................241
HTML FORMS AND REMOTE TASKS ...................................241
USING TASK METHODS TO PROCESS REQUESTS ..................244
RETURNING CONTENT TO THE CLIENT .................................247
PERSISTENT REMOTE TASKS ...............................................251
MULTIPART FORM DATA .....................................................252
DIRECT CLIENT CONNECTIONS ............................................253
CHAPTER 6—LOCALIZATION...................................255
LOCALIZATION FOR THE JAVASCRIPT CLIENT ......................255
CHAPTER 7—DEPLOYING YOUR WEB & MOBILE APPS 260
OMNIS WEB ARCHITECTURE ...............................................261
EDITING YOUR HTML PAGES .............................................261
SETTING UP THE OMNIS APP SERVER...................................265
SETTING UP YOUR WEB SERVER.........................................274
CREATING STANDALONE MOBILE APPS ...............................282
THE JAVASCRIPT SERVERLESS CLIENT ................................287
INDEX ...............................................................................299

5
About This Manual

About This Manual


This manual describes all the features in Omnis Studio that allow you to create web and
mobile apps for desktop and mobile platforms. It describes how you create Remote forms
using the JavaScript Client for displaying in the browser on web and mobile devices, as well
as setting up the Omnis App Server for deploying your applications.

If you are new to Omnis Studio


If you are new to Omnis, you should look at the Welcome screen in Omnis which is
displayed when you start Omnis and contains a tutorial as well as several sample web apps.
You can work through the same tutorial in this manual, while subsequent chapters will
provide you with all the information you need to create web and mobile apps using the
JavaScript Client.
You can read the Omnis Programming manual to learn about the general tasks and
techniques required for creating Omnis applications. In addition, there are the Omnis
Reference manuals containing information about all the Commands, Functions, and
Notation available in Omnis, together with a comprehensive Help system available from
within the Omnis development environment using the F1 key.

6
Starting Omnis

Chapter 1—Tutorial
The first section of this tutorial shows you how to create an Omnis application to browse a
picture database on your desktop computer. The database is a library of sample client
designs for a fictional design company including TV program idents, Album artworks, and
book jackets. You could, however, use the application to store any type of picture data, such
as a library of your digital photos. To use the application for your own data, you need to
work through the tutorial to create the application and then create and logon to your own
database, or you could use the library in the final folder, located inside the welcome/tutorial
folder.
Further sections of the tutorial show you how to view the same picture database in a web
browser and/or a mobile device such as a tablet or smartphone. (Note that some editions of
Omnis Studio may not allow you to develop web or mobile applications, but you will be
able to complete the first part of the tutorial.)
The first part of the tutorial will take about an hour to complete.

What will you learn?


The tutorial shows you how to create the Omnis class structure required to match the data
structure in an existing database (a SQLite database file) and how to create a simple data
entry window to browse and insert new pictures. Then it shows you how to create a web
form to browse the data in a web browser, either on a desktop computer or mobile device.

7
Chapter 1—Tutorial

Mouse and Keyboard Usage


In this tutorial, all mouse and key combinations are given in shorthand for all supported
platforms, therefore "press Ctrl/Cmnd-T" means you press Ctrl-T under Windows, and
Cmnd-T under OS X, and similarly "press F2/Cmnd-2" means you press the F2 key under
Windows, and Cmnd-2 under OS X.

Context Menus
Many of the tools in Omnis have context menus that provide options that speed up
development and navigation (to show a context menu click the Right mouse button on the
tool under Windows, or Ctrl-click on the tool under OS X).

Starting Omnis
To create an Omnis Studio application, you use the Development version. Once your
application exists, you normally use it in conjunction with the Runtime or Server version of
Omnis Studio. The Development version has all the browsers and debugging facilities that
you need to help you build an application, but also allows you to test your application in
runtime mode as you build it and without having to compile your app. During this tutorial,
you will be using the Development version.
When you start Omnis Studio, the Integrated Development Environment (IDE) will appear
and the Studio Browser is opened.

If you cannot see the Studio Browser then press the compass icon on the main Omnis Studio
toolbar, or press the F2/Cmnd-2. If any Omnis libraries are currently open, they will appear
under the Libraries node in the Folders tree list in the Browser. If you cannot see the tree
list in the Browser, press the Folders button on the Studio Browser window toolbar.

8
Creating a Library

Creating a Library
The starting point for your Omnis application is an Omnis library. A library stores all the
windows (forms), menus, reports, and other classes in your application. To create a library:
 Press F2/Cmnd-2 or click on the Studio Browser to bring it to the top, then click on
the Libraries branch in the Folders tree list and select the New Library option to the
right of the Folders tree list in the Browser.

Starting from the folder where Omnis Studio is installed (under Windows Vista this may be
in your Local folder):
 Navigate to the welcome/tutorial folder.

Under Windows XP the welcome\tutorial folder is in the main Omnis product tree in
Program Files, but under Windows Vista the welcome\tutorial folder is located in your
Local folder (note that you may need to enable hidden folders in the Windows File Manager
to access the AppData folder). The path under Windows Vista will be something like:
C:\Users\<your-name>\AppData\Local\TigerLogic\OS5x\welcome\tutorial

 In the New Library dialog, type the name pics.lbs, including the extension .LBS, and
click on OK/Save.

9
Chapter 1—Tutorial

When you create or open a library it appears in the Studio Browser. To view the contents of
a library you expand the Libraries branch of the Folders tree list and click on the library
name.
An alternative way to expand a branch in the Folders tree list is to double-click the library.
The classes that belong to the selected library are listed to the right of the Folders tree list in
the Browser list. Using the View menu on the Browser window toolbar you can change the
display to Large Icons, Small Icons or Details.

Note that the list displaying the contents of your library initially contains a Startup Task
that initializes the library when it starts up and a folder containing some System Classes
(inside the folder) that are required to configure a library.

10
Creating a Database Session

Creating a Database Session


Before you start to build your application you need to open a session to a SQL database. In
this case you are going to connect your session to an existing SQLite database that is
already populated with data, however you could use a database from another vendor (e.g.
Oracle, Sybase, DB2 or MySQL ) or some other data source connected via ODBC or
JDBC. The SQL Browser is the tool that you use during development to set up, modify and
examine your database.
 Click the SQL Browser option in the Folders tree list in the Studio Browser and then
select the Session Manager option on the left of the browser list to display all the
defined session templates.

 Click the New Session option to create a new session template.

The Modify Session window contains all the information needed to connect to your
database. (Not all the fields on the session template are needed for all databases.)
 Type PicSess in the Session Name box, select SQLite from the DBMS Vendor list,
select SQLITEDAM from the Data Access Module list; in this case, the DB Version is
not required.

Now you need to connect this session template to the SQLite database supplied in the
welcome\tutorial folder. On the Modify Session window the Host Name box needs to
contain the path to the SQLite database file that you wish to use.
 Click the Select Data File button (as shown below) to the far right of the Host Name
box.

11
Chapter 1—Tutorial

The SQLite database file is called 'pics.db' and is located in the welcome\tutorial folder on
your system.
 When you have located the pics.db database file on your system, click OK and the path
to this file appears in the Host Name box.

Note that there is also a New Data File button on the Modify Session window that you can
use to create a new empty SQLite database, but for this tutorial you will use the existing
database file, as above.
 Now press the OK button to save the session template.

You will see your new PICSESS session template appear in the list of available session
templates.

12
Opening a Database Session

 Click the SQL Browser option in the Folders tree list of the Studio Browser to exit the
Session Manager.

Opening a Database Session


To open the database session:
 Make sure the SQL Browser option is selected, then click on the Open Session
option

You should see your PICSESS session template displayed in the list of sessions.
 Select the PICSESS option to open the session.

The PICSESS session appears under the SQL Browser branch of the Folders tree list and
the Tables and Views icons on the right. (Different databases may contain different
database objects.)

13
Chapter 1—Tutorial

Note that if you quit and restart Omnis Studio then you will need to reopen your database
connection/session, as above, to continue this tutorial.

Viewing your Tables


To view the tables contained in the PICS database:
 Expand the PICSESS branch of the Folders tree list and click on Tables in the tree list.
An alternative way to view tables is to double-click Tables in the Browser list.

 To view the column structure and indexes in the MyPictures table, double-click the
MyPictures table in the Browser list.

 Close the Alter Table window.

14
Viewing your Data

Viewing your Data


To view the contents of the MyPictures table:
 Right-click on MyPictures and select Show Data from the context menu.

 Expand the Interactive SQL window, resize the Pic_Image column (drag the line in
the table header), and scroll down to view the data.

Note the Interactive SQL tool has entered the SQL needed to view the whole of the
MyPictures table (SELECT * FROM MyPictures), but you can use this tool to return
whatever data you like by entering your own SQL statements and clicking on the Run
button. For example, you could add an 'Order By Pic_Category' clause to sort the data on
Pic_Category; in this case the Books would appear at the top.
 When you have viewed the data, close the Interactive SQL window.

Now you have used the SQL Browser in the Development version of Omnis Studio to create
the PicSess session and to explore the tables and data in the database, you need to provide a
way for your library to access the data in the database, using that session information.
To allow your library to access the data in the MyPictures table you must first create a
schema class in your library that defines the column structure of the table.

15
Chapter 1—Tutorial

Making a Schema
Make sure that the Libraries branch of the Folders tree list is expanded so that you can see
your library PICS in the tree list.
Then make sure that the SQL Browser branch of the Folders tree list is expanded so that
you can see Tables under your session PicSess in the tree list.
 Click on the Tables branch of the Folders tree list to select it. (You will see the table
MyPictures listed in the Browser list.)

 Drag the MyPictures table from the list of tables and drop it on the PICS library in the
Folders tree list to create a schema class.

 Click on the PICS library in the Folders tree list.

You should see a new schema class called MyPictures appear in the Browser list.

16
Editing a Schema

This schema was created by Omnis to match the definition of the database table when you
dropped the MyPictures table on the PICS library.

Editing a Schema
To edit the schema class:
 Double-click the MyPictures schema in the Browser list to open the schema editor.
Alternatively, click the MyPictures schema class and then select the Modify option.

The 'Server table or view' box at the top of the schema editor contains the name of the
database table MyPictures that is related to this schema. Each of the entries in the schema
contains the name and Omnis data type of one of the columns in the table. Note the data
type is the equivalent Omnis data type to that of the column defined in the SQLite database
table.
To ensure that certain kinds of queries execute in the most efficient manner it is
recommended that one column in each table should be designated as the Primary Key. It is
important that the value of the primary key column in each row is unique because it is used
to identify a particular row when it is to be updated or deleted. In other words only one row
in each table should contain a particular value in the primary key column.
 Locate the Pic_ID row (it should be row 5) in the schema class and make sure the value
of the Primary Key property is set to kTrue. (As you use Omnis Studio, you will meet
many constants like kTrue, all of which by convention start with the letter "k".)

When you have finished modifying a class in Omnis you can simply close the editor
window to save it, or you can use the Save option from the File menu, or press
Ctrl/Cmnd-S.

17
Chapter 1—Tutorial

 Close the MyPictures schema class to save it.

Creating a Desktop Form


Having created the data structure for your database, you can create a window or form to
browse and insert data locally.
 Click the Pics library in the Folders tree list in the Studio Browser and select the Class
Wizard option on the left of the Browser list to display all the available wizard types.

 Now click the Window... option on the left of the Browser list to display the available
window class wizards.

 Click the SQL Form Wizard in the Browser list.

 At the bottom of the Browser window type the class name PicsWindow and press the
Create button.

The radio buttons on the Omnis Class Wizard are to select the style of form to create. Select
the first radio button that reads "One field per column based on schema or query class".

18
Creating a Desktop Form

Note that if different text is displayed next to the first radio button, you have selected the
wrong type of wizard so you should press the Cancel button on the wizard window and
choose the SQL Form Wizard.
 Press the Next button to move on to the stage where you will choose the data structure
to be used to create the form.

Note that if at this point you get the message "There are no file classes available for
selection. Please create a file class in your library and try again", you have selected the
wrong type of wizard so you should press the OK button and choose the SQL Form
Wizard.

 Click the check box to select the MyPictures schema and press the Next button to
move on to the stage where you will choose the database connection that will be used to
access the data.

Note that if at this point you get the message "There are no SQL sessions available for
selection. Please use the SQL Object Browser to open a session and try again", you need to
cancel the wizards and open a database connection, as described earlier.

19
Chapter 1—Tutorial

 Click the checkbox to select the PICSESS database session and press the Next button
to move on to the stage where you will choose a GUI theme for your form.

 Select the Plain Blue theme from the list on the left of the Omnis Class Wizard
window.

 Press Next to move on to the final stage where the form will actually be created.

 Press the Finish button to create the form.

Note that at any time prior to pressing the Finish button you can press the Previous button
to go back and review or change a selection.

20
Editing a Desktop Form

Editing a Desktop Form


After the wizard has finished creating the form the Window Editor will open with the new
class in design mode, ready for you to modify as you wish.
 Resize the window (and reposition any fields if necessary) so that you can see all of the
fields.

Note the Component Store (bottom left) and Property Manager (right) are opened
automatically. The Component Store contains objects that you can add to your forms and
other classes, while the Property Manager lets you view and modify the values of
properties of selected objects. At this stage you do not need to use these tools.

Adding some code


Before you can open the window and use it to insert data, you must make a small change to
the Insert button. Doing this will introduce you to the Omnis Method Editor which is an all-
purpose tool with built-in debugger for adding code to the objects and classes in your
library.

21
Chapter 1—Tutorial

 Assuming you have the PicsWindow open in design mode, double-click on the Insert
button.

The Omnis Method Editor will open and the $event method behind the Insert button will be
highlighted.

This method will be executed when you click on the button; in this case the method inserts
the current values in the iSqlRow variable into the database, and it's before this line you
need to make a small addition.
 Click on the second line of code 'Do iSqlRow.$insert() Returns lReturnFlag' and press
Ctrl-I/Cmnd-I to insert an empty line above.

 With the empty line selected, press "c" or "ca" to locate the Calculate command.

22
Editing a Desktop Form

 Click in the Field name box (or tab to it) and enter iSqlRow.Pic_ID

 Click in the Calculation box (or tab to it), enter #NULL and then press Return to
complete the line of code.

23
Chapter 1—Tutorial

The Pic_ID column in the SQLite database we are using is an INTEGER data type with a
Primary Key, known as an INTEGER PRIMARY KEY, which will store a unique integer
value automatically. The trick is to insert the value of Pic_ID as NULL and SQLite will
insert the next available numeric value; in effect the value of Pic_ID is incremented by 1
automatically and the new value is inserted. If you delete a data record the value of Pic_ID
in that record is never reused; SQLite will always use a new unique value.
#NULL is a so-called "hash variable", a built-in Omnis constant, and represents a NULL
value. The line of code you added to the Insert button ensures that whatever value is entered
into the field in the open window, just before the row of data is inserted, the value of Pic_ID
is set to NULL.
Your method should now look like the following.

 When you have finished editing the method, close the Method Editor.

24
Testing a Desktop Form and Inserting Data

Testing a Desktop Form and Inserting


Data
Now you can test the form you have created to ensure that in runtime mode it performs as
expected. To do this:
 Press Ctrl/Cmnd-T to open or "test" the new window class.

This will create a window instance on the screen. The window is opened on top of the
design window. Note that when you press Ctrl/Cmnd-T to test your form you must first
make sure that the design window for PicsWindow is the top window and not some other
Omnis window such as the Component Store or Property Manager.
 Press the Next button on the open window to see the first row of data in the MyPictures
table.

25
Chapter 1—Tutorial

If you are not sure if your form is open, read the text on the window title bar. If it says
"Window PICS.PicsWindow", your form is in design mode and you need to press
Ctrl/Cmnd-T to test it.
If you don't see any data in your form, check that the database session is open (note if you
have closed and reopened Omnis, then resumed the tutorial, you will need to open the
database session again, as described in an earlier section in this tutorial).
 Press the Next button again to see the second row in the MyPictures table. You may
like to try out the other buttons on the form.

When you are developing a form you can press Ctrl/Cmnd-T at any time in order to switch
between the design mode and open mode, and back to design mode again.
To insert data (a record), first enter some data into the fields or as follows:
Pic_Category Book
Pic_Name Science in Chaos
Pic_Image [insert '11bookchaos.png' from the tutorial folder using the Paste
from File option, available from the Edit menu (press Alt under
Vista to view the Edit menu). You will need to change the
filetype to PNG]
Pic_Desc Cover art for Bob Zurich’s latest science book
Pic_ID leave this field blank; a new unique value of Pic_ID will be
inserted for you automatically
Pic_URL images\tutorial\11bookchaos.png
(this is not required for the desktop window but you will need this
information when you create a remote form for viewing the data in
your browser).
 Click the Insert button to save the record.

26
Testing a Desktop Form and Inserting Data

Important note: Your form must be in open mode to test it and edit/enter data.
 Close the pics window and the design window.

27
Chapter 1—Tutorial

Creating a Web Form


In this section you will build a remote form “from scratch” starting with a blank remote
form and adding controls one by one, but equally you could use the Remote Form wizard
which automates the whole process. Using a Remote Form wizard is described in the next
chapter, under the section “Creating a Remote Form using a Wizard”, so to save yourself
time you may prefer to use the wizard, but you will not learn how to add components to
your form manually or set their properties as described below.
Next you are going to create a web form (remote form class) to browse your database in a
web browser. You can place the remote form on a website* to allow anyone to look at your
picture database in a browser on a desktop computer or mobile device (*also requires the
Omnis Server to run your app, described later in this manual).
To create a remote form:
 Click the PICS library in the Folders tree list on the Studio Browser window to show
the New class options.

 Click on the New Class option in the Studio Browser and then the RemoteForm
option.

 The new Remote Form will appear in the Studio Browser; name the new class
PicsWebform.

 Double-click on PicsWebform to open it in design mode.

28
Creating a Web Form

The remote form will open in design mode.

The Component Store will open at the bottom of the Omnis window containing 30 or so
ready-made JavaScript based components which you can drag and drop onto your form.
Note you can Right-click/Ctrl-click on the background on the Component Store and select
the Text option to show the text labels for the components, as shown, which may help you
identify the different component types.

29
Chapter 1—Tutorial

Adding Fields to a Web Form


You can add fields to your form by dragging icons from the Component Store and dropping
them onto the form.
 Press F3/Cmnd-3 to bring the Component Store to the top and locate the Edit Control.

 Drag the Edit Control from the Component Store and drop it onto your form
somewhere near the top.

An edit field is placed on your form and assigned a default name, but you can change it
using the Property Manager.
 Press F6/Cmnd-6 to bring the Property Manager to the top and locate the name
property in the list of properties.

 Click in the cell next to the property name and enter Pic_Name.

30
Adding Fields to a Web Form

 Drag the right end of the field

 Then drag the border of the form itself to resize it.

Your form should look something like the following.

Next you need to add a dataname to the field to associate the field with a column in your
database.

31
Chapter 1—Tutorial

Adding Code and Further Fields to a


Form
Before you can add a dataname to the field, you need to add a Row variable to the form
that will link your form to the MyPictures table in your database. We can reuse the code
from the PicsWindow you previously created in this tutorial.
 Press F2/Cmnd-2 to bring the Studio Browser to the top and double-click the
PicsWindow class to open it in design mode.

 Double-click somewhere on the background of the form (not on a field) to open the
Omnis Method Editor for the form.

 Select all the lines of code in the $construct method and Copy them (press Ctrl/Cmnd-
C).

 Close the Method Editor and close the PicsWindow class.

 Double-click on PicsWebform to open it in design mode and double-click on the


background of the form to open the Method Editor for this class.

 Making sure the $construct method is selected, click in the right pane and paste the
code you copied; you should now see the following:

32
Adding Code and Further Fields to a Form

The code is added to the $construct method and note that the iSqlRow row variable has also
been added to your class (as well as the local variable lSessionName). The $construct
method will be executed when the remote form is opened (in this case in the client browser),
so you can use it to initialize the form and perform many other functions.
The three lines of code starting ‘Do iSqlRow…’ in the $construct method (highlighted
above) do the following:
1. The first line defines the row variable based on the Schema class in your library
(using the $definefromsqlclass method), which itself links to the table in your
SQLite database.
2. The next line of code creates a session object based on the session template called
PICSESS you created previously in this tutorial (using the $sessionobject
property).
3. The third line of code performs a SELECT on your database which creates a
results set of data (using the $select method).
The other code in the $construct method is for managing errors.
 Close the Method Editor

 Click on the Pic_Name field in your PicsWebform to select it, then press F6/Cmnd-6 to
open the Property Manager or bring it to the front.

 Locate the dataname property in the Property Manager and enter iSqlRow.Pic_Name;
this is a column in the iSqlRow variable that is linked to the Pic_Name column in the
MyPictures table in the database.

33
Chapter 1—Tutorial

You need to create some other fields in the form, but rather than creating them from scratch
you can copy the Pic_Name field and change the properties of each field.
 Click on the Pic_Name field and press Ctrl/Cmnd-C to copy the field.

 Press Ctrl/Cmnd-V to paste a copy onto your form.

 With the new field selected press F6/Cmnd-6 to open the Property Manager and change
the following properties:
dataname = iSqlRow.Pic_Category
name = Pic_Category

 Make the Pic_Category field narrower and move it so it's level with the Pic_Name
field.

34
Adding Code and Further Fields to a Form

 Select the Pic_Category field, copy and paste it onto the form, and change the
properties of the new field using the Property Manger (F6/Cmnd-6) as follows:
dataname = iSqlRow.Pic_Desc
name = Pic_Desc
issingleline = kFalse (so the field will allow multiple lines of text)

 Make the Pic_Desc field a little larger and place it under the Pic_Category field.

Now you need to create a further field.


 Copy and paste the Pic_Category field again and change the properties of the new field
as follows:
dataname = iSqlRow.Pic_ID
name = Pic_ID

 Move the Pic_ID field and place it under the Pic_Desc field.

35
Chapter 1—Tutorial

Your form should look something like the following:

36
Adding a Picture and a Button to a Form

Adding a Picture and a Button to a


Form
Next you need to add a picture field to your form.
 Press F3/Cmnd-3 to open the Component Store or bring it to the top.

 Locate the Picture Control and drag it onto your form.

 Make the new Picture field deeper by dragging its bottom border.

 Make sure the new field is selected, and press F6/Cmnd-6 to open the Property
Manager.

 Change the properties as follows:


dataname = iSqlRow.Pic_URL
name = Pic_Image

37
Chapter 1—Tutorial

The Pic_URL column contains the location of each picture referenced in the SQLite
database. (Note the actual image files are located in the html\images\tutorial folder in the
main Omnis folder.)
Next you need to create a button in your form to allow the end user to load each data record,
that is, each row in the database.
 Locate the Button Control in the Component Store and drag it onto your form.

 With the button selected, press F6/Cmnd-6 to open the Property Manager and change
its properties as follows:
name = Next
text = Next

38
Adding a Picture and a Button to a Form

You need to add some code to the button, but you can copy this from the Next button on the
PicsWindow you created previously in this tutorial.
 Press F2/Cmnd-2 to bring the Studio Browser to the top.

 Double-click the PicsWindow, then double-click on the Next button to open the
Method Editor.

Note that the code for the Next button is placed inside the $event method for the button
(highlighted in red below). The class contains two row variables, iSqlRow, which you've
seen already in the form code, and iOldRow; these variables are needed to load or "fetch"
each successive row of data from the database (result set). When you copy the code from
this method these variables will be copied as well automatically.

 Select all the lines of code and copy them using Ctrl/Cmnd-C.

 Close the Method Editor, and close the PicsWindow.

39
Chapter 1—Tutorial

 In the Studio Browser, double-click the PicsWebform to open it in design mode.

 Double-click on the Next button to open the Method Editor for the button.

Note the Method Editor has selected the $event method for the Next button on your form.
This method will contain the code that will be executed when the end user clicks on the
button.
 Select the first line of code (On evClick) and paste the code from the clipboard.

Your Method Editor should look the same as the following (note Omnis added the iOldRow
variable):

 You can delete the last line of code (Do $cwind.$redraw) since it will have no effect; to
do this, select the line and press Ctrl/Cmnd-X.

 Close the Method Editor for the PicsWebform.

40
Adding a Remote Task

Adding a Remote Task


Before you can test your remote form, you need to add a Remote task to your library; this
is required at runtime since it handles all the instances running in the client browser, and
without it you will not be able to test or run your remote form.
 Press F2/Cmnd-2 to bring the Studio Browser to the top.

 Click on New Class, then RemoteTask and name the new class PicsRemoteTask

 Double-click on the PicsWebform class to open it in design mode.

 Press F6/Cmnd-6 to open the Property Manager and add the name PicsRemoteTask to
the designtaskname property of the remote form

Now your library has a remote task you can test your remote form.

41
Chapter 1—Tutorial

Testing your Web Form


 If the PicsWebform form is not open, double-click on it in the Studio Browser to
open it.

 Right-click on the background of PicsWebform and select Test Form; alternatively,


when your remote form is the top window you can press Ctrl/Cmnd-T at any time to
test your remote form.

Your remote form should open in your default web browser. Omnis Studio creates an
HTML page for you automatically containing the JavaScript client; in this case the page is
called 'PicsWebform.htm' and is placed in the html folder inside the main Omnis Studio
development folder (which is inside your ‘C:\Users\<username>\AppData\Local’ folder
under Windows Vista or later). This page displays your remote form by connecting to your
development version of Omnis Studio and the Pics library you have created; you can view
the source for the test HTML page in your browser to see the embedded JavaScript client
object.

42
Testing your Web Form

 In your browser, click on the Next button and each data record should be displayed.

If the data is not displayed this may be because your database session is not open; this may
be because you have closed Omnis and returned to the tutorial at a later time. If you need to
open the database session, click on the SQL Browser, click on the Open Session option,
then click on PicSess. Return to your PicWebform in design mode, press Ctrl-T to open it in
your browser and try clicking the Next button again.

Next you can adjust your form to be displayed on a mobile device.

43
Chapter 1—Tutorial

Testing your Form on a Mobile Device


At present the fields on your PicsWebform are positioned to be displayed in a browser on a
desktop computer, but you can adjust the same form to be displayed on different devices.
 If your web browser is still open, close it.

 In the Studio Browser, double-click on the PicsWebform to open it in design mode.

 Click on the background of the form and press F6 to open the Property Manager.

 Locate the screensize property and set it to kSSZjs768x1024Landscape.

The remote form will adjust its size automatically and the window frame will change. The
same fields (and methods) are used for this screen layout (different size and orientation), but
you can resize and reposition the fields if necessary to fit the current screensize; in this case
you don't need to move the fields at all since our form has only a few fields.

44
Testing your Form on a Mobile Device

You can change the value of the height and width properties of the form, and move and
resize your fields as much as you like, and Omnis will store these values for each different
value of screensize. The dotted grey area shown beyond the remote form background
(defined by the height and width values) will not be displayed in the browser, it shows the
visible area available for your form and each screensize and orientation.
 Next set the screensize property to kSSZjs320x480Landscape.

The screen will adjust its size again and the window border will change to show a mobile
device; the device image around the remote form is for display purposes only. You may
want to resize and reposition the fields to fit the form area. To remove the scroll bars, you
can set the height of the form to 300 (allowing 20 pixels for the mobile menubar) and the
width to 480.

If you change the screensize property to kSSZjs320x480Portrait you may need to set the
width property to 500 or so to enable the horizontal scrollbar on the form to allow you to
scroll across to move the fields into the visible area of the form. When you have positioned
the fields for Portrait layout you can set the width to 320 and the height to 460 (allowing
20 pixels for the mobile menubar).
To test your remote form on a mobile device or any other computer, assuming those devices
are within the same local network (LAN/WLAN), you can enter the test URL into the web
browser on your device but replace the Localhost IP address (127.0.0.1) with the IP address
of your computer itself, that is, the computer running Omnis Studio and your library. (On a
PC, you can use the ‘ipconfig’ command in the Command prompt to find your IP address,
while on OS X you can use ‘ifconfig’ in a Terminal window.)

45
Chapter 1—Tutorial

First you'll need to open the form in your desktop browser to find out the test URL.
 Click on the background of your PicsWebform and press Ctrl/Cmnd-T to test the form
(remember, if the data does not display when you click Next, close the browser, go to
the SQL Browser and open the PicSess session, and reopen the form using
CtrlCmnd-T).

 Open the web browser on your mobile device or tablet computer and enter the same
URL displayed in your desktop browser, but replacing the local host IP with the IP
address of your development computer; it will be something like the following (the port
number and IP shown in red will be different, otherwise the URL should have the same
format):
http://194.131.70.184:52357/jschtml/PicsWebform.htm
When you submit the test URL on your mobile device the PicsWebform remote form will
open, but this time Omnis detects that the form is on a mobile device and displays the
correct screen size, layout and orientation. Note it is possible to adjust the fields on your
form for several different screen sizes and orientations (including Landscape and Portrait)
and the correct layout will be chosen automatically depending on the device. If a layout for
the current device is not found then the nearest screen size or layout specified in the form is
used.

Summary
This tutorial does not cover the process of deploying your application to the web, but
hopefully it has given you an insight into how quick and easy it is to create and test remote
forms in a web or mobile app. For more information about deploying your web application,
refer to the Deploying your Web & Mobile Apps chapter.

Tutorial Libraries
There is a library called ‘pics.lbs’ in the final folder, located inside the welcome/tutorial
folder, that contains all the classes created in this tutorial, plus there is some code in the
Startup_Task to open the database session automatically: you might like to open this library
and examine the classes and their methods.
In addition, there is a second library called ‘pics2.lbs’ in the tutorial folder that has some
extra classes including a Query class, Report class, and Menu class that enhance the
Desktop aspects of the application.

46
Welcome Window

Welcome Window
The Welcome window opens when you first start Omnis Studio and contains a set of sample
apps that use the JavaScript Client. The Welcome window can also be opened by clicking
on the New Users button on the main Omnis menu bar.
The sample web apps in the Welcome window cover a range of business and home uses and
include the following:
 Memo allows you to create quick post-it like notes using subform sets
 Contacts manager for recording information about colleagues or friends
 Todo app for handling tasks in the office or home,
 Holidays app for managing annual leave requests,
 Timesheets app for recording time-based tasks,
 Guestbook app for recording feedback from your website visitors,
 Webshop app which has a product catalog and shopping cart.
We urge you to examine these apps and in particular try out the JavaScript forms that they
all use and examine the code behind each form: you can try the apps in your desktop
browser or in the web browser on your mobile device.

47
Chapter 2—JavaScript Remote Forms

Chapter 2—JavaScript
Remote Forms
To create web or mobile app in Omnis you need to create a Remote Form class using the
ready-made JavaScript Components available in the Component Store in design mode. At
any stage during the design process you can test a JavaScript remote form using the “Test
Form” option (press Ctrl/Cmnd-T or Right-click on the form) and the Remote form will
open in the web browser on your development computer. The remote form and the
components you have added to the form are embedded into a simple HTML file in the
JavaScript Client object and are rendered in the browser using JavaScript and CSS.
In order to test or open a remote form, your Omnis library also needs to have a Remote Task
class which will handle the remote form instance and any current connections to web or
mobile clients. JavaScript remote forms and remote tasks are discussed in this chapter,
while the individual JavaScript components are described in the next chapter.

Creating JavaScript Remote Forms


You can create a new Remote form class in the Studio Browser using the New
Class>>Remote Form option, or the Class Wizard>>Remote Form option. The first
option creates a blank remote form ready for you to drop in JavaScript components, while
the second option launches the Remote Form Wizard described in the next section.
The JavaScript Client functionality is enabled by setting the $client property in a new
remote form. When you create a remote form, either a blank new one or using the Remote
Form Wizard, Omnis will set the $client property to kClientJavaScript by default so the
JavaScript Client is the default client for your web and mobile apps. The other options in
the $client property include kClientiOS or kClientPlugin which enable remote forms for the
iOS Client plug-in and the Web Client plug-in, respectively (the latter is only included for
backwards compatibility for developers wishing to use the Web Client plug-in).
Once you have set $client and added some components to the form, the $client property is
grayed out and you can no longer change the property in that form. You can only change
$client when the remote form is empty.

48
Creating JavaScript Remote Forms

Remote Form Name


Like any other class in Omnis, the name of a new Remote form can be anything you like but
would normally take account of its function within your application. The class name does
not have to conform to any convention other than any conventions you may like to use in
your application to identify different class types: so for example, your remote forms could
be prefixed with “rf”.
However you should note that the name of the Remote form class, plus the “.htm”
extension, is used as the name of the HTML file which is created when you test your remote
form in design mode. Therefore you should restrict any characters used in the name of your
Remote form to only those normally allowed in a web context, or to be sure of removing all
possible conflicts, you should only use alphanumeric characters and do not use spaces. For
example, a remote form name cannot include the hash symbol (#) or other special symbols
since this may cause unexpected results in the browser, or in the case of #, the remote form
may not open in test mode at all.

Creating a Remote Form using a Wizard


To use the Remote Form Class Wizard you need to open a database session and your
library must contain a Schema class: when you step through the wizard you will be asked to
select a database session name and schema class to link to your remote form. This section
assumes you have a database session and schema class in your library. If not, you might like
to follow the steps in the Tutorial in Chapter 1 to create a database session and a schema
class, including the sections: "Creating a database session", "Opening a database session",
"Making a schema", and "Editing a schema".
To create a new JavaScript Remote Form
 Assuming you have opened a database session and you have created a schema class in
your library, click on the Class Wizard option

49
Chapter 2—JavaScript Remote Forms

 Click on the Remote Form option to launch the remote form wizard

 The SQL JavaScript Form wizard will be selected by default; next you need to name
the new class, such as PicsWebform, and then click on Create

When you create a remote form in your library you also need to create a Remote Task: this
is required at runtime since it handles all the remote form instances running in the client
browser, and without it you will not be able to test or run your remote form.

50
Creating JavaScript Remote Forms

 Select ‘Create New Remote Task’, then select ‘Plain Remote Task’ from the list of
remote task templates, enter a name for your new task, such as PicsRemoteTask, and
finally click on Next

For the next stage of the wizard you can select the type of remote form created, based on a
schema class or (query class) in your library.

The Parent / Child option requires two schema classes linked in a parent/child relationship.
 Accept the default form type, that is ‘One field per column based on schema or query
class’ and click on Next

51
Chapter 2—JavaScript Remote Forms

For this stage of the wizard you can select the SQL class to be linked to your remote form:
this will either be a Schema class or Query class, the latter is a type of data class that lets
you combine one or more schema classes or individual columns from one or more schemas.
Note that you can expand the tree list to display all the columns in your schema class which
would allow you to select individual columns to be added to your remote form. If you check
the schema name in the list, all the columns in that schema will be selected.
 Check the box next to the MyPictures schema class and click on Next

The MyPictures schema class will be in the Pics library if you have followed the appropriate
sections in the tutorial: if a schema class is not displayed you will have to cancel the wizard
and create one.

The next stage of the wizard lets you select an open database session.
 Check the box next to the PICSESS session

The PICSESS session will be in the SQL Browser if you have followed the appropriate
sections in the tutorial, or if you are using the pics.lbs in the ‘final’ folder, the session

52
Creating JavaScript Remote Forms

should be opened for you automatically. If a session is not displayed in the wizard you will
have to cancel the wizard and open a session in the Studio Browser.
 To complete the wizard click on Finish

When the wizard is completed your remote form will be opened in Omnis in design mode.
The Property Manager will appear on the right side of the Omnis window, and the
Component Store will open at the bottom of your screen.

53
Chapter 2—JavaScript Remote Forms

JavaScript Components
When you edit a remote form (assuming the $client property is set to kClientJavaScript), the
Component Store contains a set of components for the JavaScript Client.

To display the Component Store as above you can Right-click on the background of the
window and select the Text option to show text labels, and then you may need to enlarge
the window to display all the components. You can Right-click on the Component Store and
select the Save Window Setup option to store the layout of the window.
See the JavaScript Components chapter for more information and example code for each
component.

Copying Components
In design mode, you can copy a component on one form and paste it onto either the same
form or a different form using the Copy/Paste menu options or Ctrl-C/Ctrl-V keyboard
options. Alternatively, you can hold down the Ctrl key, then click on and drag a component
to make a copy of the component in the new location. You can also drag a component from
one remote form and drop it onto another form to make a copy of a component, but only if
both the forms are set to the same screen size (i.e. the setting of $screensize is the same for
both forms).

54
Remote Tasks

Remote Tasks
In order to test or run your remote form in a browser, your library should contain a Remote
Task and the $designtaskname property of your remote form should be set to the name of a
remote task in the current library. When you create a new remote form from the Studio
Browser, and if your library contains a single remote task, the $designtaskname property
will be set to the name of that remote task automatically. If your library does not contain a
remote task, you will have to create one manually and set the $designtaskname property of
your remote form to the name of the new remote task. If your library has multiple remote
tasks, and you create a new remote form from the Studio Browser, the $designtaskname
property will not be set, so again you will have to assign this manually before you can set
the form.

Creating Remote Task Classes using Wizards


You can create an Omnis remote task from scratch or by using one of the templates or
wizards provided in the Studio Browser. Alternatively, when you use one of the Remote
Form wizards you have the option to create a new remote task.
To create a remote task using a template of class wizard
 Click on the New Class>>Remote Task option in the Studio Browser

 Name the new Remote task and press Return

Or to use a class wizard you can:


 Click on Class Wizard option in the Studio Browser and then the Remote Task option

 Select the wizard you want, name the new class and click on Create

The following wizards/templates are available:


 Plain Remote Task
creates an empty remote task containing an $event method with code for evBusy and
evIdle events; this is suitable for running JavaScript Remote forms.
 Monitor
creates a task and window to monitor remote connections from within your application
when deployed on the Omnis App Server.
 HTML Report
creates a task to generate HTML reports on the fly
 Submit
creates a task and standard HTML file containing a submit form which interacts
directly with Omnis; note the HTML file does not use the JavaScript Client.

55
Chapter 2—JavaScript Remote Forms

$enablesenddata Property
The remote task property $enablesenddata should be set to kFalse for all tasks controlling
JavaScript remote forms since the $senddata() method is not implemented for JavaScript
remote forms.

Plain Remote Task Wizard


The Plain Task wizard creates a basic template remote task that is suitable for linking to
most simple remote forms. The Plain remote task also has an $event() method containing a
template event handling method that detects evBusy and evIdle events in the task. You can
add your own code to handle these events.
The Plain Remote Task has a $construct() method containing a parameter variable called
pParams of type Row Variable. This row variable receives all the parameters of the
JavaScript Client, such as the remote form name, the client width and height, and the user
agent string: see below.
When you create a task using the Plain Task wizard you can specify the Inherit from
Monitor task option. This option adds a set of “monitor” classes to your library which
allows you to record client connections associated with the new plain task you are adding to
your library. If you check the Monitor option, the wizard prompts you for details about the
new monitor task. If your library does not contain a monitor task, you need to specify the
Create New Monitor Task option. If, however, your library contains a monitor task, you
can specify the Use Existing Monitor Task option to add the new plain task you are
currently adding to your library to the existing monitor.

Monitor Remote Task Wizard


The Monitor wizard (or checking the ‘Inherit from Monitor task’ option in the Plain Task
wizard) creates a number of “monitor” classes, including a new task and monitor window,
that allow you to record remote connections between web or mobile clients and the
Omnis App Server.
The wizard prompts you to enter the name of the new Monitor remote task and window, but
in most cases you can accept the default names. The Amend Startup Task option lets you
add code to the Startup_Task in the current library to open the Monitor window at startup;
this is checked by default.
The Monitor window, called wMonitor by default, has three panes. The Connections pane
shows the connections grouped by remote form name. The History and Server Usage
panes let you monitor the traffic flow on your Omnis Server and provide some general
information about server usage. You can print the server usage using the Print Report
button.

Remote Task Instances


When the JavaScript Client first connects to the Omnis App Server, Omnis creates an
instance of the Remote Task Class associated with the Remote form class to which the client

56
Remote Tasks

is connecting (and specified in the $designtaskname property of the remote form). Once the
remote task class has been instantiated, next the Remote form instance is created. The
$construct method of first the Remote task and then the Remote form are run, so these
methods can include any code you want to run prior to opening the form (in the task
construct method) or when the form is opened.

Construct Row Variable


When a form is opened and the Remote task and Remote form instances are created, Omnis
passes a parameter variable of type Row to the $construct() method of the Remote task and
then the Remote form (in that order). This parameter variable contains a column for each
parameter of the JavaScript Client object instantiated on the client: therefore, it will include
columns for OmnisLibrary and OmnisClass (as defined in your HTML file), as well as extra
columns containing additional information about the client object.
The construct row variable will contain the following columns and typical values:

Column Description
OmnisLibrary <OmnisLibrayName>
OmnisClass <RemoteFormName>
param1, 2, .. 9 Up to 9 pre-defined custom parameters called param1, param2, etc,
which you can add to the JavaScript Client object in your HTML
page; you can add custom parameters prefixed with “data-“ to send
further values to the task or form construct method
OmnisPlatform JSU, the JavaScript Client
JSscreenWidth The screen width of the client, e.g. 1280 for desktop PC
JSscreenHeight The screen height of the client, e.g. 1024 for desktop PC
JSscreenSize The initial setting of $screensize for the client, e.g. kSSZDesktop
userAgent The navigator.userAgent of the client, which usually contains the
browser type and version
appName The navigator.appName of the client, i.e. the browser application
name, such as “Microsoft Internet Explorer” or “Netscape”
Flags Currently indicates if the client supports animation: 1 means the
browser does support animation, zero means that it does not
JStimezoneOffset offset from UTC in seconds, e.g. “120” for clients on UTC+2
ClientLocale the Locale language setting of the client, e.g. “en_GB” for clients
in the UK, or “en_US” for America

The appName and userAgent columns return properties of the client browser and therefore
allow you to determine which browser and version the client is using, such as whether it is a
desktop or mobile browser.

57
Chapter 2—JavaScript Remote Forms

Using the Construct Row Variable in your Code


If you want to use the values in this parameter variable, you can create a parameter variable
of type Row in the $construct() method of your remote task or remote form which will
receive the parameter variable when the task/form is constructed. To examine the values in
the variable, you can set a breakpoint in the $construct() method of your remote task or
remote form, open the form (using Ctrl-T), and Omnis will switch to the debugger allowing
you to right-click on the variable to examine its value.
For example, many of the sample apps available in the Welcome window use the construct
parameter variable to get the screen size of the client device in order to set the size and
position of various controls in the initial remote form for the app. The following is the code
for the $construct() method of the jsShop remote form in the Webshop app, which receives
the screen size of the client device, and calls another method to setup the columns for a data
grid control on the main jsShop remote form:
; $construct method containing a Parameter var called pRow of type
Row; the form also contains an instance var iScreensize (Char)
Calculate iScreensize as pRow.JSScreensize
Do method setupSizes
Etc.
; code for setupSizes method
Switch iScreensize
Case kSSZjs320x480Portrait
Do $cinst.$objs.pagePane.$objs.orderGrid.$::columnwidths.$assign(
"150,50,50,70")
Case kSSZjs320x480Landscape
Do $cinst.$objs.pagePane.$objs.orderGrid.$::columnwidths.$assign(
"70,40,40,70")
Case kSSZjs768x1024Portrait
Do $cinst.$objs.pagePane.$objs.orderGrid.$::columnwidths.$assign(
"300,75,75,175")
Case kSSZjs768x1024Landscape
Do $cinst.$objs.pagePane.$objs.orderGrid.$::columnwidths.$assign(
"250,75,75,175")
Default
Do $cinst.$objs.pagePane.$objs.orderGrid.$::columnwidths.$assign(
"100,50,60,75")
End Switch

58
Remote Tasks

Changing Forms
The remote task instance has a method, $changeform(), which enables you to replace the
form currently in use on the client, with another form in the same library. $changeform() has
a single argument, which is the new remote form name. When it executes, the current form
instance destructs, and the client constructs an instance of the new form to display in the
user’s browser. You can use task variables in the remote task instance to pass information
between the destructed remote form instance, and the new remote form instance.
There are some restrictions to note:
 $changeform() cannot be used in the $construct() or $destruct() method of a remote
form instance or remote task instance. If used, Omnis generates a runtime error.
 Multiple calls to $openform() (described later) or $changeform() during the processing
of a single event will result in only the last call to $openform() or $changeform()
having any affect.
One scenario for using $changeform() is where the end user is required to log onto your
web application, whereby the initial “logon” form prompts the user for a name and
password, and the application changes to another form when the user has successfully
submitted a valid name and password.

Multiple Forms
You can open more than one form within a single client connection, that is, within a single
remote task instance. At any one time, only one of these multiple instances is visible, and
the forms must be from the same library.
There are two methods of a remote task instance which you can use to manage multiple
forms: $openform() and $closeform(). Like $changeform(), both these methods take a single
argument, the remote form name.
If the form passed to $openform() already has a remote form instance open in the context of
the remote task instance, it becomes the visible form for the remote task. Otherwise, Omnis
constructs a new instance of the remote form in the remote task, and makes the new remote
form instance the visible form.
The $closeform() method closes (destructs) the remote form instance for the named form,
without closing the task instance or any other forms that may be open within the task. It is
possible to close the last remaining remote form instance, but this is not recommended,
since the end user will be presented with a blank screen. If the referenced form is not
visible, the client observes no affect; otherwise, the most recently visible open remote form
instance becomes visible.

59
Chapter 2—JavaScript Remote Forms

There are some further restrictions to note:


 $closeform() and $openform() cannot be used in the $construct() or $destruct() method
of a remote form instance or remote task instance. If used, Omnis generates a runtime
error.
 Multiple calls to $openform() or $changeform() during the processing of a single event
will result in only the last call to $openform() or $changeform() having any affect.
 Calling $showurl() or $showmessage() in the $destruct() method of a remote form has
no affect.
 All forms must be in the same library.
You can use task variables to handle communication between multiple remote form
instances in a remote task instance.
To facilitate communication between different remote form instances, remote forms can
also receive the event evFormToTop. In design mode, you can enable this event for a form,
using the $events property of the form. The event generates a call to the $event() method of
the remote form. evFormToTop occurs when an existing remote form is about to become
visible on the client as a result of a call or calls to $openform() or $closeform().

Client Access Properties


Remote tasks have a number of properties for managing the connections between the Omnis
App Server and the web or mobile clients connected to your application. These properties
will be populated only when there are live remote task and remote form instances created by
a client connection.
 $connectbytessent
specifies the number of bytes which have been sent to the client during the connection.
This property is set after $construct() has been executed.
 $requests
specifies the number of events executed on the server. Excludes connect and disconnect
messages. Updated prior to evBusy message.
 $reqtotbytesreceived
the total number of bytes received from the client for all requests. To calculate an
average per request, you can divide this value by $requests. Updated prior to evBusy
message.
 $reqtotbytessent
the total number of bytes sent to the client for all requests. To calculate an average per
request, you can divide this value by $requests. Updated prior to evIdle message.
 $reqmaxbytesreceived
The largest block in bytes received from the client for all requests. Updated prior to
evBusy message.

60
Remote Tasks

 $reqmaxbytessent
The largest block in bytes sent to the client for all requests. Updates prior to evIdle
message.
 $reqcurbytesreceived
The number of bytes received from the client for the current request. Updated prior to
evBusy message for the current request.
 $reqcurbytessent
The number of bytes sent to the client for the current request. Updated prior to evIdle
message.

Timeouts
You can control how long someone is connected to the Omnis App Server and how long a
single client connection can remain idle, using the following properties.
 $maxtime
the maximum time in minutes that a client is allowed to stay connected; the default
value is 0 which means the client can stay connected indefinitely.
 $timeout
the maximum time in minutes that a client is allowed to stay idle; the default value is 0
which means the client is allowed to stay idle indefinitely.

Client Connections
Remote tasks have some properties that tell you about the current client connection.
 $clientaddress
the TCP/IP address of the current client. Note that this may not be the exact TCP/IP
address of the client machine, due to the possible presence of proxy servers and
firewalls between the client machine and the web server.
 $connectionid
the id of the current client connection; ids are allocated dynamically by the Omnis
Server and numbers are not reused unless the server is restarted.
 $connectiontime
the time and date the client connected to the Omnis Server, i.e. the time the current task
instance was instantiated.
 $lastresponse
the time and date the client last accessed the remote task instance on the Omnis Server.

Secure Sockets
You can use secure sockets (HTTPS) if you have installed an SSL certificate on your web
server. The JavaScript Client will use a secure connection to connect the client to the web
server if you prefix the URL or IP_address in the data-webserverurl parameter with

61
Chapter 2—JavaScript Remote Forms

“https://”. In addition, remote tasks have the $issecure property that lets you turn secure
mode on and off dynamically, by assigning to the property for the current task at runtime.

Remote Task Events


For remote tasks, the evBusy and evIdle events are sent to the $event() method during the
lifetime of a connection: evBusy is sent when Omnis receives a request from a client, evIdle
is sent when Omnis is about to return the result of a request, i.e. the task instance is about to
become idle. The following example, shows the code for the $event() method in the
Monitor task created using the Monitor task wizard:
On evBusy
If iMonitorOpen
Do iMonitorRef.$setstatus($cinst,kTrue) Returns lServerBusyFlag
If lServerBusyFlag
Quit event handler (Discard event)
; server cannot handle request
End If
End If
On evIdle
If iMonitorOpen
Do iMonitorRef.$setstatus($cinst,kFalse)
End If
On evRejected
Do $cinst.$showmessage(pErrorText)
In addition, tasks report the evRejected event which is generated when Omnis rejects a
connection by a client. Usually this occurs if there are too many users trying to connect to
Omnis, or $maxusers of the remote task has been exceeded. The parameter pErrorText is
"Too many users connecting to server" for the first case, and "Too many users connecting to
task [taskname]" for the second.

62
Remote Form Properties

Remote Form Properties


Like other types of Omnis class, remote form classes have a number of properties that
control their appearance and behavior. You can set most properties of a remote form class
in the Property Manager (press F6/Cmnd-6), but the properties for remote form instances
must be assigned in the code in your app. Remote form instances also have methods: see the
Remote Form Methods section.
Many of the properties, including many of the standard form properties, are reasonably self-
explanatory, but some properties that are specific to remote forms require further
explanation and are described in the following sections. The $serverlessclient property
enables the Standalone Mobile Apps capability which is described later in this manual,
while the $stringtabledata and $stringtabledesignform properties concern Localization
which is also discussed later in this manual.

Screen Size and Orientation


You can design different layouts for the different screen sizes and orientations within the
same remote form design class. When the end user runs your application, the JavaScript
Client will chose the most appropriate screen size for the end user’s device automatically,
and will switch orientation if the device is rotated. The JavaScript remote form property
$screensize specifies the screen size and orientation in the remote form and can be set to
Desktop, and various Portrait or Landscape options for different tablets and mobile devices.

There are a number of default screen sizes available in the $screensize property, which
include the following (note other sizes can be added: see below):
 kSSZDesktop
for remote forms running in a web browser on a laptop or desktop based PC or Mac
computer; in effect the screen size is unspecified and the $height and $width of the
form in design mode is used to size the form in the browser
 kSSZjs320x480Portrait or kSSZjs320x480Landscape
For mobile devices with screens 320 x 480 px (at 96dpi) in Portrait/ Landscape
orientation

63
Chapter 2—JavaScript Remote Forms

 kSSZjs768x1024Portrait or kSSZjs768x1024Landscape
For mobile devices with screens 768 x 1024 px (at 96dpi) in Portrait/ Landscape
orientation
Designing forms for different devices
When you create the remote form, you can place the objects on the form, for example, on
the desktop layout. Then when you are ready to design the layout for other devices you can
change the setting of $screensize, and reposition the same objects for each screen size and
orientation. In other words, each screen size/layout uses the same set of objects (and
methods) and the single remote form class stores the position of the fields for each screen
size/orientation setting.
Typically you would design the layout of a single remote form for a number of different
devices or screen sizes, and then use the floating edge, scaling and centering properties to
position and size the form on devices which have sizes relatively close to those that are
stored in the form.
When opening (constructing) a remote form, the JavaScript Client uses the most appropriate
screen size and orientation stored with the form, for the screen size and orientation of the
current device. If the user swaps from portrait to landscape, or back again, the JavaScript
Client repositions the controls automatically, using the coordinates the new orientation
stored in the remote form (assuming you have added a layout for each orientation). If for
example, the user switches to landscape orientation, and you haven’t added a layout for this
orientation to the form, the portrait layout is used by default.

Remote form width and height


When $screensize is set to one of the mobile sizes, changing $width and $height for the
remote form changes the width and height of the client area of the design window (the area
where you can place controls), rather than the size of the design window itself. The design
window adds scrollbars to the client area when necessary, therefore you don’t need to
enable the $horzscroll or $vertscroll for the tablet or mobile screen sizes. In addition, you
can control whether the design window shows the mobile title bar, by setting the
$designshowmobiletitle property for the form, although you may want to show this for most
types of mobile applications.
In most cases, when specifying the width and height for the mobile screen sizes, you can set
the $width and $height properties to match the exact coordinates in the current setting of
$screensize, allowing for the mobile title bar which is 20 pixels high. If you have set
$designshowmobiletitle to kFalse you may want to add 20 pixels to the height of the form.

Enabling alternative screen sizes


Support for different screen sizes can be added to $screensize to cater for a number of new
mobile devices with different screen sizes or form factors, including the BlackBerry® Q10
and the Samsung® Galaxy S4. The screens on such devices have a specific physical size,
but due to their high resolution they may have different CSS pixel dimensions which are
used when designing the layout of remote forms. For example, the Samsung Galaxy S4 has

64
Remote Form Properties

a 5" HD display which is 1080 x 1920 physical pixels at 441 ppi resolution, equating to
CSS pixel dimensions of 360x640.
Thers is a new library preference, $designedscreensizes, which is a comma-separated list of
screen size constants for JavaScript Client based remote forms in the library (note this is a
library wide preference, not a remote form property). To enab le the new screen sizes, you
need to check the kSSZjs345x345 and kSSZjs360x640Portrait options under the Prefs tab
in the Property Manager for the current library: note that by enabling the ‘Portrait’ option
you enable the equivalent landscape layout for the given size. The screen sizes enabled in
the new library preference will be used to populate the $screensize property in the Property
Manager and will be available for all remote forms in the library.
If you change $designedscreensizes, the size and position information for sizes or layouts
no longer in the list of designed sizes will not be lost: the designed layouts will remain
stored with the remote form in the library.
Implementing new screen sizes
The omnisobject containing the JavaScript client in the HTML page has a new attribute,
‘data-dss’, which contains the designed screen sizes for the library. If you use forms from
more than one library in a single client instance, each library must have the same set of
$designedscreensizes. If not, a runtime error will occur when trying to use a form from
another library.
If you change the screen sizes supported in the $designedscreensizes library preference, all
the HTML files for all remote forms in your library need to be rebuilt to reflect the new set
of screen sizes: this is done automatically when you test a remote form since the HTML file
is rebuilt every time you test a remote form.
Note there is a new jsctempl.htm template file to accommodate the new screen sizes and
ongoing support for any new sizes.
Requesting new screen sizes
Developers can now request a new screen size or form factor for inclusion in Omnis Studio,
although we will reserve the right to decide whether or not any suggested screen size is
appropriate for Omnis. Between major releases, we will make new sizes available by
supplying new screen size configuration files on request. An updated ‘ssz.cfg’ file will be
provided and can be placed in the ‘studio’ folder in the Omnis tree, and a new ‘ssz.js’ file
which should be placed in the ‘scripts’ folder. Then for the next major release the new or
updated screen sizes will become available for all developers with an updated set of files.

Initial Field and Tabbing Order


The $startfield property specifies which field in a remote form will get the focus when the
form is opened; it takes the field number as specified in the $order property of the field. For
positive values, it is the order number of the initial enterable field or control of the remote

65
Chapter 2—JavaScript Remote Forms

form. If you specify a negative value, and a subform is created from the remote form class,
the field specified in $startfield becomes the current enterable field on the form.
The relative values of the $order property for each field or control in your remote form
determines the tabbing order of the controls in the form. For inherited forms, the
$inheritedorder property determines the tabbing order for the first inherited field: zero
means maintain the designed order from the base class through to this class.

Responding to OK and Cancel Keys


You can specify which object in the remote form receive OK and Cancel events from the
keyboard, e.g. when the end user presses the OK or Cancel button. For the JavaScript
remote forms, $okkeyobject specifies the object in the form that receives evClick when the
user presses Return or Enter. Similarly, $cancelkeyobject specifies the object that receives
evClick when the user presses Escape. Both of these properties only apply if the field
currently with the focus does not use the key that is pressed, in which case these properties
will have no effect.

Form and Component Transparency


Remote forms have the $alpha property which sets the transparency of the form (an integer
from 0 to 255, with 0 being completely transparent and 255 opaque). In addition,
$backalpha lets you control whether or not subforms in the main form use the background
color of the subform field or the form itself. The majority of the JavaScript components
have the $alpha and $backalpha properties which control the transparency of the foreground
and background colors of the component.
In combination with the animation methods, you can use the $alpha of a form or control to
make elements in your form appear and disappear. The About windows in the sample apps
(available in the Welcome screen when you start Omnis) are displayed by setting the $alpha
property of the About subform and using the animation “ease in” effects. See the
Animations section.

Gradients
To create a gradient for the background of a JavaScript remote form, you can select a
gradient fill pattern for $backpattern and control the start and end colors for the gradient by
setting $forecolor and $backcolor.

66
Remote Form Instances and Methods

Remote Form Instances and Methods


When you “open” or test a remote form in Omnis it is opened in a web browser. In
development mode this will be the default web browser on your development computer, but
when your app is deployed the remote form will open in the end user’s web browser, or the
browser on a mobile device, or within a wrapper application for standalone mobile apps.
When a remote form is opened a remote form instance is created which will have a number
of methods that you can use in your code to perform various actions.

Remote Form Instance Properties


Remote form instances have a number of properties:
 $remotemenu
which is the current remote menu instance. This is only set when evOpenContextMenu
is being processed: see the Remote Menus section
 $sqlobject
is the JavaScript Client SQL object which is only available in client-executed methods
running in a wrapper application: see the Standalone Apps section

Remote Form Methods


Remote form instances have the following methods, to enable such things as animations,
client messages, client commands, and the ability to open another web page from within the
client:
 $beginanimations() and $commitanimations()
$beginanimations(iDuration [, iCurve=kJSAnimationCurveEaseInOut]) After calling
this, assignments to some properties are animated for iDuration milliseconds by
$commitanimations(); the $commitanimations() method animates the relevant property
changes that have occurred after the matching call to $beginanimations(); see the
Animations section
 $clientcommand()
$clientcommand(cCommand, wRow) Executes the command cCommand on the client
machine using the parameters in the row variable wRow; see the Client Commands
section for possible client commands.
 $maximize() and $minimize()
For subforms in a subform set only: maximizes or minimizes the remote form instance
if it is a member of a subform set
 $setcurfield()
$setcurfield(vNameOrIdentOrItemref [,bSelect=kFalse]) sets the current field on the
client and places the focus in the field; for mobile devices the soft keypad may be

67
Chapter 2—JavaScript Remote Forms

initiated (depends on the OS); if bSelect=kTrue, and if supported by the control, all of
its content will be selected; executing $setcurfield(‘’) will remove the focus from the
current field; you can specify the field by name, ident, or item reference
 $showmessage()
$showmessage(cMessage[,cTitle]) displays an OK message on the client machine using
the specified cMessage and cTitle
 $showurl()
$showurl(cURL[,cFrame,cWindowProperties]) opens the URL in a new window or
frame on the client machine; cURL specifies the URL of the HTML page; cFrame
specifies the HTML frame name; if cFrame is empty, the page is displayed in a new
window, otherwise it is displayed in the specified frame of the current window.
The final optional parameter for the $showurl() method, cWindowProperties, is ignored if
cFrame is not empty. Otherwise, it has the same format as the JavaScript argument to
‘window.open’, for example, "toolbar=0,menubar=1" specifies that the browser window
will have a menubar, but not a toolbar. The keywords are all boolean (0 or 1) except for the
width, height, top and left, which are numbers in pixel units. Possible keywords are:

Keyword Description
toolbar specifies if the browser window has a toolbar
status specifies if the browser window has a status bar
menubar specifies if the browser window has a menu bar
scrollbars specifies if the browser window has scrollbars
resizable specifies if the browser window is resizable
location specifies whether the browser window has a location bar
directories specifies whether the browser window displays Web directories
width width of browser window
height height of browser window
top top coordinate of browser window
left left coordinate of browser window

$redraw and $senddata Methods


Redraws are handled automatically for JavaScript forms and controls, so although
JavaScript based remote forms and controls contain the $redraw() method, it is not required
and if it is called it does nothing. In addition, the $senddata() method let you control when
data was returned to the client, but this is irrelevant for JavaScript Client which handles the
transfer of data between the client and server automatically.

68
Remote Form Instances and Methods

Client Messages
The $showmessage() method allows you to display a message on the client machine. This
method only applies to remote tasks that are associated with remote forms, that is, the
method does not work for remote tasks that handle HTML forms or “ultra-thin” clients.
Only one message can be shown in response to a single event. Executing $showmessage()
more than once in response to the same event will result in a single Ok message with the
text and title of the last call to $showmessage being shown. Alternatively, you can use the
OK message command provided it is executed on the client; in this case the command uses
a standard browser alert() or confirm() dialog.

Adding Objects to JavaScript Forms


You can add a new object to a remote form instance or a Paged Pane in the form using the
$add() method. Note that you cannot create an entirely new object using this method, rather
the $add() method in this context lets you copy an existing object in the form and add it to
the form or pane. The following method can be used, where $cinst is the remote form
instance:
$cinst.$objs.$add(
cName,rSrcItem[,rParentPagedPane,iPageNumber,bAllPanes=kFalse])
adds new object cName to the JavaScript remote form instance by copying rSrcItem
(existing object in same instance). The default action is that the new object is added to the
form (when rParentPagedPane etc are omitted), otherwise you can specify the Paged Pane
parameters to add the new object to a Paged Pane in the remote form.
This method can only be used in server methods, not a client-side method, that is, the
information about methods etc is not present on the client. There is a logical limit of 16384
controls on a remote form, although performance will be impaired well before that limit.
The rSrcItem and rParentPagedPane parameters must both be item references to objects in
the same remote form instance: their original properties and methods defined in the class
when the form was instantiated will be the initial properties and methods of the new object.
If the object to be copied (rSrcItem) is a paged pane, then its children are not copied.
This method of copying objects cannot be used to copy complex grids. Furthermore,
complex grids cannot be anywhere in the parent hierarchy.
Note that you cannot use the $remove() method to remove objects you have added using the
$add() method: to remove or hide such an object, you can set $visible for the object to
kFalse. In addition, you should note that $order is not assignable at runtime so you cannot
add a new object and then change its field order.

69
Chapter 2—JavaScript Remote Forms

Remote Form Instance Group


The item group $root.$iremoteforms is a global group of all remote forms instantiated in
Omnis at any one time. For this release you can inspect the $iremoteforms group within the
context of the current remote task (the current global group remains unchanged).
Therefore you can use $ctask.$iremoteforms in a remote task to return an item group
containing both top-level remote form instances and subform instances. In addition, the $obj
notation has been implemented for subform objects, so that if the current item is an item
reference to a remote form instance contained by a subform object, item.$obj is the item
reference to the remote form subform object. For example, if RF1 is a remote form
containing a subform object named sfobj, with a classname of RFSUB, then after both
forms have constructed:
$ctask.$iremoteforms will contain instances RF1 and RFSUB
$ctask.$iremoteforms.RFSUB.$obj will be
$iremoteforms.RF1.$objs.sfobj

Client Commands
The $clientcommand() remote form method allows you to execute various commands on the
client device, including ones that open various type of message boxes; the suitability of
certain commands will depend on the current client device (e.g. some of the commands may
not be available for certain mobile devices), so these commands should be thoroughly
tested, as appropriate, for all devices you wish to support. The $clientcommand() method
may be very useful since the JavaScript does not support client-side scripting,
i.e. component methods cannot be executed on the client (as in the Omnis Web Client plug-
in).
The $clientcommand() method must be executed on the Omnis Server in a remote form
instance, and requires various parameters dependent on the command sent to the client. It
has the following general syntax:
Do $cinst.$clientcommand(cCommand,wRow)
where $cinst is the current remote form instance, cCommand is the name of the command to
be executed on the client, and the wRow is a row variable containing any number of
parameters to be passed to the client.
The client commands that open a message box allow you to enter the message text in the
first parameter. You can create a line break in the message text using //.

70
Client Commands

Yes/No Messages
The “yesnomessage” command opens a Yes/No message box in which Yes is the default
button.
Do $cinst.$clientcommand("yesnomessage",row-variable)
Where row-variable is row(message text, title text, name of public form server method
called on yes, name of public form server method called on no, name of public form server
method called on cancel (leave empty for no cancel button)).
For example, in the Webshop sample app a Yes/No message is generated using the
$clientcommand method when a user clicks on a product size/type that is not available:
Do $cinst.$clientcommand('yesnomessage',row(con('Would you like
to order >',iProductList.product_size_1,'< instead?'),'Not
available','$orderYes'))

No/Yes Messages
The “noyesmessage” command opens a No/Yes message box in which No is the default
button.
Do $cinst.$clientcommand("noyesmessage",row-variable)
Where row-variable is row(message text, title text, name of public form server method
called on yes, name of public form server method called on no, name of public form server
method called on cancel (leave empty for no cancel button)).

Ok/Cancel Messages
The “okcancelmessage” command opens an OK/Cancel message box in which OK is the
default button.
Do $cinst.$clientcommand("okcancelmessage",row-variable)
Where row-variable is row(message text, title text, name of public form server method
called on ok, name of public form server method called on cancel (leave empty for no
cancel button)).

JavaScript Message Boxes


The “javamessage” command shows a JavaScript message box on the client. The message
box can be various styles (error, warning, success, prompt, message, query) and can have up
to three buttons and accompanying text.
Do $cinst.$clientcommand("javamessage",row-variable)
Where row-variable is row(style(error, warning, success, prompt, message, query), text,
title text, openatmouse(bool), butt1text:servermethodname, butt2text:servermethodname,
butt3text:servermethodname).

71
Chapter 2—JavaScript Remote Forms

Playing Sounds
The system bell
The “soundbell” command plays the default system sound on the client.
Do $cinst.$clientcommand("soundbell",row-variable)
In this case, row() is empty.
Play a sound file
The “playsound” command plays a sound on the client.
Do $cinst.$clientcommand("playsound",row-variable)
Where row-variable is row(name of sound file from html sounds folder).

Date Format
The “setcustomformat” command allows you to set the date format used on the client when
$customformat is empty (defaults to D m y).
Do $cinst.$clientcommand("setcustomformat",row-variable)
Where row-variable is row(date format). See the Date and Time Formatting section for
more details about setting the data format on the client.

Client Preferences
The following commands allow you to save and load end-user data on the client, such as
user preferences. You could use these commands to store and load usernames and/or
passwords to allow the end user to log onto your application.

Saving preferences
The “savepreference” command saves a value (as a character string) as a named preference
on the client.
Do $cinst.$clientcommand("savepreference",row-variable)
Where row-variable is row(preference name, preference value).

Loading preferences
The “loadpreference” command loads a named preference value from the client preferences
into an instance variable.
Do $cinst.$clientcommand("loadpreference",row-variable)
Where row-variable is row(preference name, instance variable name (e.g. a quoted string
containing the name of the variable)). The preference name is initially empty.

72
Remote Form Events

Locking the User Interface


The “lockui” command lets you lock the user interface manually, for example, when a series
of events are taking place, and unlock the UI when the events have completed. This
command is useful with the progress control and $sendcarryon – in this case, you can lock
the UI when you start the progress bar, and unlock it when you have finished using the
following code:
; to lock:
Do $cinst.$clientcommand("lockui",row(kTrue))
; to unlock, either:
Do $cinst.$clientcommand("lockui",row(kFalse))
; or
Do $cinst.$clientcommand("lockui",row())

Subform Sets
There are a number of client commands that allow you to create and manage subform sets:
see the Subform Sets section for more information.

PDF Printing
The “showpdf” and “assignpdf” client commands allow you to print and display PDF files
in the client browser: see the PDF Printing section for more information.

Remote Form Events


JavaScript fields and controls trigger events which you can respond to in the $event()
method for individual controls. JavaScript remote forms also trigger events, including when
the screen size or orientation of the client device changes, or when a form or subform is
brought to the top when multiple forms are open. Remote forms trigger the following
events:
 evAnimationsComplete
The animation has completed, with the parameter pEventCode
 evFormToTop
The remote form is about to become visible on the client, with parameters pEventCode
and pScreenSize which is a kSSZ... constant for the current screen size on the client
 evScreenOrientationChanged
The orientation of the screen displaying the form has switched between portrait and
landscape, with parameters pEventCode and pScreenSize which is a kSSZ... constant
for the current screen size on the client

73
Chapter 2—JavaScript Remote Forms

 evSubFormToTop
An existing remote form, contained in a subform that has $multipleclasses set to kTrue,
is about to become visible on the client, with the parameter pEventCode
 evOpenContextMenu and evExecuteContextMenu
JavaScript remote forms report the context menu events: see the Context Menus section
The evFormToTop and evSubFormToTop events are discussed in the Multiple Forms
section, while evAnimationsComplete is discussed in the Animations section.

Event Parameters
When an event is triggered, a number of event parameters are sent from the client to the
event handling method. The first of these parameters is always the name of the event that
occurred, and all subsequent parameters are specific to the event and describe the event in
more detail. For example, a click on a list passes the click event in the first parameter
(pEventCode=evClick) and the list line clicked in the second parameter (pLineNumber).

Enabling Form Events


If you want to use any remote form events in your code, you have to enable the events in the
$events property of the remote form. You have to do this in design mode by clicking on the
background of the form and selecting the $events property in the Property Manager. You
can enable an event by selecting it in the dropdown list for the $events property.

Form Orientation
When the orientation of a remote form changes (e.g. when the end user rotates their mobile
device), Omnis sends an evScreenOrientationChanged event to the top remote form. This
allows the remote form to adjust the coordinates of any dynamically added objects. In
addition, evFormToTop also receives the pScreenSize event parameter, allowing other
forms to make adjustments if necessary when they come to the top.

74
Remote Form Events

Event Methods
You can trap and respond to events generated in a remote form in the $event() method in
the form. You have to add a method called $event to the Class methods for the form to
create an event handler. Like other event methods you can use the On event command to
trap specific remote form events. The following $event method responds to the
evScreenOrientationChanged event and sets the iScreensize variable to the correct screen
size.
On evScreenOrientationChanged
Switch pScreenSize
Case 3
Calculate iScreensize as kSSZjs320x480Portrait
Case 4
Calculate iScreensize as kSSZjs320x480Landscape
Case 9
Calculate iScreensize as kSSZjs768x1024Portrait
Case 10
Calculate iScreensize as kSSZjs768x1024Landscape
Default
Calculate iScreensize as kSSZDesktop
End Switch
Do method setupSizes

Running Event Methods on the Client


Event handling methods can be set to run on the client and for most simple methods and
calculations this is advisable. To set a method to run on the client you need to Right-click
on the method in the method editor and select the ‘Execute on Client’ option. By default, an
event is sent back to the Omnis App Server, the client is momentarily suspended while the
event handling method is processed on the server, and when the method is finished control
is passed back to the client. In some cases, this may not be a problem, but in general it
makes sense to execute your methods on the client and avoid any network delay if possible.
Whether or not you execute a method on the client will depend what the method has to do
and what information it requires: in general, any method that changes the user interface on
the client can be executed on the client, while a method that needs to fetch data or write data
to your server database needs to execute on the Omnis App Server.

75
Chapter 2—JavaScript Remote Forms

Client Methods
You can run certain methods on the client, such as event handling methods, instead of
running them on the Omnis App Server. When such Client Methods are called in your
application, runtime execution does not pass back to the Omnis App Server, rather the
method is executed entirely in the end-user’s browser within the JavaScript Client. Enabling
certain methods to execute on the client can speed up your application by cutting down on
network traffic, while from a design point of view, this capability may allow you to add
more interactivity into the user interface of your web or mobile app.
Any methods in your JavaScript remote forms that are enabled to execute on the client are
converted to JavaScript files. These JavaScript files are run in the browser when the method
is called on the client. When a client browser opens a JavaScript remote form, the Omnis
App Server generates a JavaScript file containing the client methods for the remote form
(the generation of this file only occurs once unless the remote form class is modified, in
which case it will regenerate the file). This file is added to the html/formscripts folder in the
Omnis tree inside a subfolder named after the library. Each remote form containing client
methods has a separate JavaScript script file.
When you deploy and run your web or mobile app on the Omnis App Server, these
JavaScript script files are generated at the same location as in the development version, the
first time the client calls the client-side method. For the deployed app, the JavaScript files
are in minified form, and therefore are smaller and will run faster since all the comments are
stripped out.

$init method
You can create a client-side method with the name $init in your remote form which the
client calls after the form and the client scripts file have been loaded. This allows you to do
any final initialisation of the remote form, especially when the remote form is running in
serverless client mode.

Enabling Client methods


To enable a method to execute on the client, you can Right-click on the method name in the
Method Editor and select the ‘Execute on Client’ option. Whether or not an existing method
can be enabled to execute on the client will depend on the Omnis commands, functions, and
in some cases the type and scope of the variables used in the method. When you try to
enable the method to execute on the client, Omnis checks whether all the commands and
functions within the method can be executed on the client, and if not, it will not allow the
method to be marked as ‘Execute on Client’. If the method can be executed on the client,
the method name will be shown in pink and the restrictions on client methods will then
apply to this method.
If you create a new empty method in the method editor, it can be enabled to execute on the
client without error (since it does not contain any commands, functions or variables at this

76
Client Methods

stage), but the number of commands and functions available to use will be limited to those
shown in the Method Editor. The type of Local and Parameter variables you can create will
also be restricted: see Data Types below.
The Omnis Help (F1) indicates whether or not a command or function can be executed on
the JavaScript client: please note that some commands or functions could be executed in the
Web Client plug-in but may not now be executable in the JavaScript client which only allow
a smaller subset of commands and functions to be run on the client.

Binary functions
The Binary functions cannot be used in JavaScript client methods since JavaScript does not
support binary data particularly well.

Text blocks
You can use the text block commands (Begin text block, Text:, End text block, Get text
block) in JavaScript client methods to build up a block of text, e.g. to generate styled text
(see the Styled Text section).
The Omnis flag
You can use the flag() function in your code to return the status of #F, the Omnis flag,
which can be true or false, depending on the result of executing a method or Omnis
command.
Object properties in client methods
While some properties can only be assigned in Server methods, you can read the current
value of many more remote form properties and component properties in Client executed
methods. So for example, you cannot change the size and position of an object in a client
method (by setting $top, $left, $width, and $height), but you can return the current values
for an object in a client method, e.g. $cobj.$width returns the width of the object.

Debugging Client methods


Client methods cannot be debugged in the Omnis method editor since method execution
occurs in the client browser. Instead, you must use the Script Debugger within the browser
you are using to test the client executed parts of your application. Note that for this reason
you cannot use any Omnis commands that interact with the debugger or trace log (Trace on,
Open trace log, etc) in client methods, or any that would interrupt command execution
(Breakpoint, Yes/No message). However, while developing your app, you can use the Send
to trace log command in client executed methods to write a line to the JavaScript console.

Calling Custom Methods


You can use the Do method command to call a custom method (your own method) in the
current remote form instance. If you use this command in a client method you must include
parenthesis after the method name for the method to be called. For example, to call a

77
Chapter 2—JavaScript Remote Forms

custom method called $mymethod from within in a client method in the current remote form
instance, you must use Do method $cinst.$mymethod(), or you can use Do
$cinst.$mymethod().

Data Types for Client methods


JavaScript itself only supports a small number of built-in data types, and these do not
correspond directly with Omnis data types. Since instance variables are used by both the
JavaScript Client and the Omnis App Server, these can still be given any Omnis data type.
However, Local variables and Parameter variables in client methods can only be Date
Time, List, Row or Var type. The Var type is a generic variable used for data of any type.
The client does not enforce the type of data stored in a variable, unless you assign a value to
an instance variable or list column, in which case the client will convert the assigned value
to the correct Omnis type for the instance variable or list column, or failing that, if the data
cannot be converted, the client throws an exception, reported by an OK message.

Further restrictions
 Field reference parameters are not supported, since JavaScript methods use call by
value.
 Date Time local variables and parameters do not have a subtype in client methods.
 Date Time, List and Row variables are represented by a JavaScript object on the client,
whereas the other data types are the native JavaScript types (number, string and
Boolean).
When you change a method from client to server execution, or back again, the data type of
Local variables and Parameters changes to the most logical supported value for client or
server execution (restoring the original type when changing from client to server execution
if the type on the client is Var).

Execution and Method Calls


Method execution in the JavaScript client means that that no user-visible updates to the user
interface occur until control returns from the executing JavaScript to the browser (or other
container). This means that client methods should be as short as possible. This also means
that if a client-side method calls a server method, this call cannot occur in a synchronous
manner, since the user interface would appear frozen while the server code was executing
(since no user-visible updates to the user interface occur while a synchronous AJAX call is
running). This means that the mechanism for calling a server method from a client method is
implemented differently for the JavaScript client.
When code in a client-side method calls a server method (either using $cinst.$methodname
notation, or by using the Do method command), the call to the server is executed
asynchronously. After making the server method call, the client-side method continues to
completion (note that the server method call returns true or false to indicate if it has started).

78
Client Methods

The client-side method can only call one server method like this – if it makes a second call,
the client throws an exception.
If the client code needs to handle the return value from the server method, then you must
implement a client-side method in the remote form with the name <method name>_return,
for example, to receive the return value from a server method called $test, implement a
client-side method $test_return. The _return method must have a single parameter, which is
the return value from the server method. A typical action of the _return method might be to
update a progress control, and then issue another call to the server. This allows a time-
consuming operation to execute while showing its progress.

Client Method Examples


There is an example app demonstrating client methods available in the Apps Gallery on the
Omnis website (www.tigerlogic.com/omnis). The app includes a simple entry form with
client-side field validation, and some animated help tips – you should download the library
and examine the client methods and code. A sample of the code is described here.

Field Validation
A web or mobile form may include several mandatory fields. You can use a client-side
method behind the Submit button (called Add in the example app) to check that the fields
contain some data – this is the code for the email field:
; $event method behind Submit button – it is enabled to execute on
the client
On evClick
If pos('@',iEmail)=0
Do $cinst.$objs.EmailLabel.$textcolor.$assign(kRed)
Calculate lCurField as 'Email'
Else
Do $cinst.$objs.EmailLabel.$textcolor.$assign(kBlack)
End If
; check other fields…
The code checks whether or not the Email field contains an ‘@’ and if not the field label is
colored red and the cursor is placed in the Email field – if the Email field contains data the
method moves onto the next field. All the other fields on the form are checked for any
content and handled in a similar way: the password field is checked for a minimum number
of characters, as follows:
If len(iPassword)<6
Do $cinst.$objs.PasswordLabel.$textcolor.$assign(kRed)
Calculate lCurField as 'Password'
Else
Do $cinst.$objs.PasswordLabel.$textcolor.$assign(kBlack)
End If

79
Chapter 2—JavaScript Remote Forms

Animated Help tips


In the client-method example app, the form has some help buttons that you can click on to
receive tips about how to fill out the form. These help tips are implemented using a hidden
text box and the animation methods – when you click on a button, the text box is made
visible and is moved into position next to the appropriate field, and when the button is
clicked again the text box is hidden. The code to achieve this is in a client-side method
behind the Help tip button marked with a ‘?’ icon: the button is in fact a Picture control with
its $iconid set to 1794, and the code is placed behind the $event() method. The Tip box is a
paged pane containing a Rounded rectangle and a Text field – when the form is opened its
$alpha is set to 0 and it is positioned off the screen. The help tip next to the Password field
has the following event method:
On evClick
If iLastTip='password'
Do $cinst.$beginanimations(500,kJSAnimationCurveLinear)
Do $cinst.$objs.Tip.$alpha.$assign(0)
Do $cinst.$commitanimations()
Calculate iLastTip as ''
Else
Calculate iTip as
"A password must to at least 6 characters long."
Do $cinst.$beginanimations(500,kJSAnimationCurveLinear)
Do $cinst.$objs.Tip.$top.$assign(270)
Do $cinst.$objs.Tip.$alpha.$assign(255)
Do $cinst.$commitanimations()
; the Tip box is made visible and moved into position
Calculate iLastTip as 'password'
End If
There is a similar Help tip button and method for the Email field. If the Password Tip box is
already visible in the form and you click the Email Help button, the Tip text is changed and
the Tip box itself is moved next to the Email field.

Client Objects and Inheritance


The JavaScript client uses JavaScript objects to represent each remote form and each
control on the remote form. The client methods of a remote form and its controls are
defined as methods of the remote form and control objects.
Once a remote form and its client methods script file have been loaded, the JavaScript
remote form object has a member called ivars which is a JavaScript object that maps
instance variable names to instance variable field numbers. If you override an instance
variable, then the ivars object will have more than one entry for the variable – overridden
superclass variables will have a numeric suffix to distinguish them.

80
Testing JavaScript Remote forms

The Do inherited command is evaluated at the point at which the script file is generated by
the server. This means you can only use Do inherited from within the actual method you
have overridden. This differs from the other clients, in that they allow you do call Do
inherited from a private method called from an inherited public method, and then the call to
Do inherited calls the overridden public method.

New Page Browser Prompt


In most desktop browsers (excluding Opera) a web page can prompt the user before
navigating to another page. Using the $init client-side method for a remote form you can
specify the message to be added to the user prompt.
If the $init method returns a character string, the browser will prompt before navigating to
another page, but only if the browser supports this feature. The returned character string
may not be in the browser prompt, depending on the browser, for example, Firefox does not
currently display it.
If $init does not end with a Quit method command, or returns another type, then
functionality is unchanged from the current behavior.
Once one $init method has returned a string, any return values from any other $init calls for
other remote form instances are ignored, so there is no way to turn off the prompt once it
has been enabled.

Testing JavaScript Remote forms


You can test a JavaScript remote form using the Test Form option, available in a remote
form either by right-clicking on the background of the form and selecting Test Form, or by
pressing Ctrl-T. The Test Form option will open the remote form in a web browser specified
as the default browser on your development computer; the remote form will open in a new
browser window or create a new separate tab if your browser supports tabs.
You can switch back to Omnis and continue to change your remote form or its methods, and
use Ctrl-T at any time to test your form. Each time you press Ctrl-T Omnis will try to open a
new browser window or tab: if your browser is already displaying your remote form, and
you have modified the form, you can switch to your browser and Refresh the browser to see
the latest changes to your form.
When you test your remote form using Test Form (Ctrl-T) an HTML page is created for you
automatically containing the JavaScript Client and all the required parameters to allow you
to open your Omnis app in a web browser. The test HTML file is located in the HTML
folder under the main Omnis folder, and can be used or incorporated into the other web
pages on your website when you are ready to deploy your application. The name of the test
HTML file will be the same as your remote form class name plus the .htm extension. The
test HTML is based on a template file which is also located in the HTML folder: see below
for more information about the template.

81
Chapter 2—JavaScript Remote Forms

The URL for the test HTML page will be something like the following:
http://127.0.0.1:51452/jschtml/<remoteformname>.htm
The test URL contains the IP address of your Localhost (127.0.0.1), the port number of
your copy of Omnis Studio, a reference to the test JavaScript Client HTML folder, and the
name of the HTML file. The port number during testing will be the port number specified in
the $serverport Omnis preference, or if this is empty (the default) a port number is selected
randomly from the available ports on your computer.
If you try to open or navigate to the test URL from your browser history it may not work: in
this case such a URL may not have the correct port setting since the port number is assigned
dynamically during testing if the $serverport property is empty and therefore may be
different from one session to another. In addition, you cannot open or test your remote form
by opening the test HTML in the template folder: again your browser will not have the
correct URL to load the test HTML file.
Omnis Studio and your library must be open and running to test your remote form. So if
you open the test HTML file from your file system, and Omnis and your library are not
open, then your remote form will not be displayed and your web or mobile app will not run.

Template HTML File


The test HTML created when you use the Test Form or Ctrl-T option is based on a template
file called ‘jsctempl.htm’ which is located in the HTML folder under the main Omnis
folder. When you press Ctrl-T a copy of the template file is made and the individual
parameters for your remote form are written to the test HTML file: this occurs every time
you test your form to ensure the test HTML file is up to date and has the correct parameters.
Therefore, if you make any changes to the HTML file in HTML folder your changes will be
overwritten the next time you test your remote form: if you want to keep a version of this
file, either rename it or copy the file to another location.
Note: Existing users will note that this is a change in behavior: in previous versions of the
Omnis Web Client plug-in the test HTML file was created the first time you tested a remote
form and was not rebuilt each time you tested the same form.

Default Web Browser


When you test your remote form using the Test Form option (Ctrl-T) it is opened in the
default web browser on your development computer. If you want to test the form in another
browser on your computer you can copy the test URL and paste it into another browser
(note the port number may change from session to session).
If you want to override the default action for the Test Form option, you can specify the
name and path of an alternative browser in the $webbrowser Omnis preference (edit the
Omnis preferences via Tools>>Options). If this preference is empty, then the default
browser on your development computer will be used for testing remote forms.

82
Testing JavaScript Remote forms

Debugging Remote Forms


When you open a remote form in your development browser you will need to debug the
methods and code in the form. You can do this by setting breakpoints in your code and you
can send messages to the Omnis trace log or the JavaScript console (provided it is
available) to allow you to debug your code.
Breakpoints
You can set breakpoints in your code, so when you test your remote form using the Test
Form option or Ctrl-T and a breakpoint is encountered, control will pass from your web
browser back to Omnis. In this case, when a breakpoint is encountered, the Omnis entry
(button) in the Windows Task bar will flash (the default color is orange) and you will have
to click on the button to return to the Omnis application window to continue debugging.

Trace Log
The tracelog() function allows you send debugging and other messages to the Omnis trace
log from within client methods executed in the JavaScript Client: this will allow you to
debug client methods. The tracelog(string) function writes the string to the Omnis trace log,
or does nothing if debugging is disabled using the library property $nodebug. It returns true
if the string was successfully written to the trace log.
Alternatively, in JavaScript client-executed methods you can use the Send to trace log
command which sends the text to the JavaScript console.

Error reporting
When an error is encountered in your code in the JavaScript client Omnis populates the
#ERRCODE and #ERRTEXT global variables with the appropriate error code and message
text. You can read the value of these variables in client executed methods using the
following functions:
 errcode()
returns #ERRCODE, a numeric variable containing the error number generated by a
method
 errtext()
returns #ERRTEXT, a string variable containing the error text generated by a method

Testing your Remote Form on a Mobile Device


To test your remote form on a mobile device or any other client apart from your
development computer, assuming those devices are within the same local network
(LAN/WLAN) as your development computer, you can enter the test URL into the web
browser on your device but replace the Localhost IP address (127.0.0.1) with the IP address
of your development computer. For example, reusing the test URL above and replacing the
IP address, the following URL could be used on a mobile device such as a phone or tablet
computer:

83
Chapter 2—JavaScript Remote Forms

http://194.131.70.184:51452/jschtml/jsMain.htm
You can use the ipconfig command to find the IP address of your development computer,
via the Command prompt on a PC or the Terminal on a Mac.
You can test a mobile remote form in a wrapper application using the Test Form Mobile
(Ctrl-M) option, assuming a wrapper application is setup and enabled: if a wrapper is not
setup you can test your mobile forms in a web browser during development, as above. See
the Deployment section for details about setting up a wrapper application.

Testing Mobile Layouts


If you are using Firefox during development, you can test different layouts for mobile and
tablet screen sizes in a single browser window using the ‘Responsive Design View’ mode:
note this is a feature of Firefox and is not available in other browsers. This may save you a
lot of time during the initial stages of designing your mobile application, since this avoids
having to test your app on multiple devices to test different sizes and layouts. However, we
recommend that you should test your final app on any real device that you wish to support
when you are ready to deploy your app.
To enable this functionality, you need to set the ‘gResponsiveDesign’ flag to true in the
‘ssz.js’ script file located in the html/scripts folder in your Omnis development tree. For this
to take effect, you must restart Omnis after setting the responsive design flag. To enable this
mode in Firefox, go to the Tools>Web Developer menu option and select ‘Responsive
Design View’: you will need to show the Menu bar in Firefox to see this option. Then when
you test your remote form in Firefox, you can select different screen sizes and orientations
in the dropdown menu in the Firefox browser window, and your remote form will redraw
using the appropriate screen size specified in $screensize for the remote form. When you
have finished testing using this mode, you should set gResponsiveDesign in the ‘ssz.js’
script file back to false.

Troubleshooting Remote Forms and Tasks


Remote Tasks
When I try to test my remote form using Ctrl-T, it does not open and the error “To
use a remote form class, you must set the design task of the remote form class to a
remote task” is displayed.
You need to create a remote task in your library and set the $designtaskname property of the
remote form class to the name of the remote task you created. A remote form instance needs
a remote task instance to run (for testing or deployment), so will not open without a remote
task and the $designtaskname property being set.

Remote Forms
When I open my blank remote form in design mode I don’t see any JavaScript
components in the Component Store.
You need to set the $client property of the remote form to kClientJavaScript to use the new

84
Remote Menus

JavaScript components. When you use the New Class>>Remote Form option in the Studio
Browser, the client property should be set to kClientJavaScript for you automatically. (Note
you cannot switch an existing Web Client based remote form to the JavaScript Client, but
there is a migration tool available in the Studio Browser to help you move to the new
client.)
Events
I have placed an event method behind my button (or any other event-driven object)
but nothing happens when I click it while testing the form in a browser.
You must specify which events are to be triggered by the object or remote form in the
$events property of the object or form. So for a button, the evClick event must be checked
in the $events property of the button. Events for some objects are checked by default but
you may like to examine the state of each event in the $events property and make sure the
events you need are enabled.

Remote Menus
The Remote Menu class allows you to add various types of menu to remote forms and
individual controls. A remote menu can be opened as a Popup Menu control, added to a Tab
Control, or as a Context menu for the form itself or individual control (popup menus and tab
menus are described in the Components chapter).

Creating Remote Menu Classes


When you design a remote menu you need to create a title, specified in $title, and add
individual menu lines: the text for a menu line is added to the $text property for the menu
line. A remote menu does not contain methods, rather each line has a separate ID which is
specified in the $commandid for the menu line. When a menu line is selected at runtime,
you can use the line ID to detect which line was selected and branch your code accordingly.
For example, when a remote menu is used as a popup menu and the menu is clicked, the
evClick event is triggered with the selected line reported in pLinenumber.

85
Chapter 2—JavaScript Remote Forms

Context Menus
A context menu is a menu that can be opened by the end user by right-clicking on the
background of a form, or within the border of a form control. You can implement context
menus for remote forms or individual form controls by setting the $contextmenu property of
the form or control to the name of a Remote menu class. Each line in a remote menu has the
$commandid property, so when the user selects a line in the menu this ID can be used to
trigger a specific action in your code. When a line in a remote menu is selected, an
evExecuteContextMenu event is reported to the form or field with event parameters
containing the Command ID of the selected line, and for fields, a reference to the field
which was clicked on.
Remote forms and controls have the $disabledefaultcontextmenu property to disable default
menus from opening when the end user right-clicks the form or object: the default menu for
the edit control could be the clipboard menu. If true, the default context menu for the object
will not be generated in response to a context click ($clib.$disabledefaultcontextmenu and
$cobj.$disabledefaultcontextmenu must both be false for the default menu to be generated).

Context Menu Events


Remote forms or controls report the following events in response to a context click.
 evOpenContextMenu
Sent to a field or a remote form when a context menu is about to open; the event
contains the parameters pEventCode, pContextMenu which is a reference to the remote
menu instance that is about to pop up as a context menu, and pClickedField which is a
reference to the field which was clicked
 evExecuteContextMenu
Sent to a field or remote form when a context menu item is selected; the event contains
the parameters pEventCode, pCommandID which is the command ID of the selected
remote menu item, and pClickedField which is a reference to the field which was
clicked
The remote menu instance itself only exists during the evOpenContextMenu event,
therefore it is possible to modify the menu before it is displayed on the client, or you can
discard the event to prevent the menu from being displayed.
Remote form instances have the property $remotemenu which is the name of the remote
menu instance (set only when evOpenContextMenu for the field or form is being
processed): for hierarchical menus, this is the item reference to the remote menu instance of
the attached remote menu.
After evOpenContextMenu completes, and the user selects a remote menu item, the client
sends an evExecuteContextMenu event to the form or form control that received the
evOpenContextMenu, passing the event parameter pCommandID containing the value of
$commandid of the selected menu line.

86
Subform Sets

Subform Sets
You can open a special kind of subform or group of subforms that behave rather like
separate windows in the JavaScript Client. The subforms in a subform set are different to
standard subforms (which are embedded in a Subform control, and described in the
Components chapter) in that they have a title bar and resizable borders, and the end user can
move or resize them within the “main” remote form running on the client. Such dynamic
subforms within a subform set will allow you to create highly flexible user interfaces in your
apps, by allowing a high degree of interactivity for the end user.
The new subforms or group of subforms are opened as part of a new client object called a
Subform Set (SFS), which is created at runtime in the JavaScript Client and allows you to
manage the group of subforms. The new subforms are opened in the client at runtime within
the main JavaScript remote form, or they can be opened within the context of a single page
in a paged pane. Each separate subform in the Subform Set is a standard Remote form class
that you have previously created in your library, which is referenced and added to the
Subform Set.

Stacking Order List


The subforms in a Subform Set have a “stacking order” (or Z-order) relative to one another,
so the top-most form in the set will appear in front of any forms lower in the stacking order
if they intersect. Clicking on a form lower in the stacking order brings it to the front. The
tab order of the remote form excludes controls on the subforms in a Subform Set behind the
top form in the set. There is a maximum of 256 remote form instances (including subform
instances) in a remote task instance. When you have more than one Subform Set open (this
is allowed but not recommended) there is no relative stacking order between the sets.

Creating Dynamic Subforms


There is a set of new client commands to open and manage the subforms in a Subform Set
which you can execute using the $clientcommand() method. These client commands must
be executed on the Omnis App Server in the context of the current remote form instance
($cinst); the $clientcommand() method will not work in a client-side method. The
$clientcommand() method requires two parameters: the cCommand to be executed and a
wRow variable containing the parameters for the command, with the syntax:
Do $cinst.$clientcommand(cCommand,wRow)
where $cinst is the current remote form instance.

87
Chapter 2—JavaScript Remote Forms

Subform Client Commands


The following client commands are available for creating and managing Subform Sets.
subformset_add
The subformset_add command creates a Subform Set within the current remote form
instance.
Do $cinst.$clientcommand("subformset_add",row-variable)

Where row-variable is row(setname, parent, flags, ordervar, formlist)


Note the parent parameter is available if you want to create the subform set inside a paged
pane, rather than the remote form instance. The columns for the row variable parameter are
as follows:
setname: a string which is the name of the set, which must be unique within the current
remote task.
parent: the container for the set, either:
 pagedpanename:page (e.g. pp:5), so that the subforms belong to the specified page of
the paged pane)
 or empty, meaning that the subforms in the set belong to the remote form instance
invoking $clientcommand.
flags: the sum of 0-4 of the following constants, which affect the behavior of the forms in
the set:
 kSFSflagCloseButton: The subforms in the set have a close button
 kSFSflagMinButton: The subforms in the set have a minimize button
 kSFSflagMaxButton: The subforms in the set have a maximize button; note the
subform can only be maximized (resized) if kSFSflagResize is enabled
 kSFSflagResize: The subforms in the set have a resize border so that they can be
resized using the mouse or when the Maximize button is pressed
ordervar: the name of an instance list variable in the remote form invoking the
$clientcommand. The client keeps this list variable up to date with the stacking order and
position information for the subforms in the set: see below.
formlist: a list which defines the subforms to be added initially to the subform set (this list
can be empty), i.e. a list of remote form classes that you have previously created in your
library. The order of the forms in this list represents the stacking order from top to bottom,
so that once the set has been added, the top-most subform will be for line 1, and the bottom-
most subform will be for the last line. The columns in the list are as follows:
 Column 1: uniqueID: An integer which must uniquely identify this subform in the set.

88
Subform Sets

 Column 2: classname: The name of the Omnis remote form class for the subform.
 Column 3: params: Literal parameters to be passed to the $construct of the subform e.g.
‘Test’,200.
 Column 4: title: The title of the subform - text displayed in the title bar of the subform.
 Column 5: left: The left coordinate of the subform (for Desktop browsers, or portrait if
a mobile device). The constant kSFScenter centers the form horizontally in its parent.
 Column 6: top: The top coordinate of the subform (for Desktop browsers, or portrait if
a mobile device). The constant kSFScenter centers the form vertically in its parent.
 Column 7: width: The width of the subform. If the forms in the set are resizable, then
the form cannot be made narrower than the minimum of this width and the width
designed for the remote form class.
 Column 8: height: The height of the subform. If the forms in the set are resizable, then
the form cannot be made taller than the minimum of this height and the height designed
for the remote form class.
 If the subforms are to be displayed on a mobile device, Columns 9-12 are landscape
left, top, width and height respectively. If these are omitted, the landscape values
default to the portrait values.
subformset_remove
The subformset_remove command removes a set of subforms. All subforms in the set will
be destructed and removed from their parent.
Do $cinst.$clientcommand("subformset_remove",row-variable)

Where row-variable is row(setname) where setname is set to be removed.

subformset_formadd
The subformset_formadd command add a form to an existing subform set.
Do $cinst.$clientcommand("subformset_formadd",row-variable)

Where row-variable is row(setname, uniqueID, classname, params, title, left, top, width,
height, modal)
The row variable parameter are as follows:
setname: a string which is the name of the set to which the subform is to be added.
uniqueID: an integer which must uniquely identify this subform in the set.
classname: the name of the Omnis remote form class for the subform.
params: literal parameters to be passed to the $construct of the subform e.g. ‘Test’,200.
title: the title of the subform - text displayed in the title bar of the subform.

89
Chapter 2—JavaScript Remote Forms

left: the left coordinate of the subform (for Desktop browsers, or portrait if a mobile
device). The constant kSFScenter centers the form horizontally in its parent.
top: the top coordinate of the subform (for Desktop browsers, or portrait if a mobile
device). The constant kSFScenter centers the form vertically in its parent.
width: the width of the subform. If the forms in the set are resizable, then the form cannot
be made narrower than the minimum of this width and the width designed for the remote
form class.
height: the height of the subform. If the forms in the set are resizable, then the form cannot
be made taller than the minimum of this height and the height designed for the remote form
class.
modal: zero if the subform is non-modal, or 1 if the subform is fully modal, and prevents
the use of any other form or subform in the remote task’s user interface.
If the subforms are to be displayed on a mobile device, the next four columns are landscape
left, top, width and height respectively. If these are omitted, the landscape values default to
the portrait values.
The parameters above, starting with uniqueID, are identical to those in the formlist (for the
subformset_add command), except the modal indicator is present between the two sets of
coordinates.

subformset_formremove
The subformset_formremove command removes a subform from an existing set and
destructs it (removing it from its parent).
Do $cinst.$clientcommand("subformset_formremove",row-variable)

Where row-variable is row(setname, uniqueID, focus)


The row variable parameter are as follows:
setname: a string which is the name of the set from which the subform is to be removed.
uniqueID: an integer which identifies the subform in the set to be removed.
focus: optional (default value is kFalse). If the focus parameter is kTrue, sets focus to the
new top form in the set unless it is minimized.

subformset_formtofront
The subformset_formtofront command brings a subform in a set to the top of the stacking
order, and gives it the focus. You must use this command to display a subform that has
previously been minimized.
Do $cinst.$clientcommand("subformset_formtofront",row-variable)

Where row-variable is row(setname, uniqueID)


setname: a string which is the name of the set containing the subform.

90
Subform Sets

uniqueID: an integer which identifies the subform in the set to be brought to the front.

Using the Stacking Order Variable (ordervar)


When you use the subformset_add client command a list called ordervar is created
containing a list of the subforms in the subform set. The ordervar variable allows you to
manage the subforms in the set. It has the same definition as the formlist, and like the
formlist it contains the subforms in the order of the top to the bottom of the stacking order.
Note that if coordinates have been centered using kSFScenter, the ordervar contains their
actual values rather than the value kSFScenter.
Whenever the stacking order changes, or a form is moved or resized, the client updates the
values in ordervar. This results in:
 Automatic updates to controls which are data-bound to the ordervar.
 A call to a client method in the container form for the SFS. If you add a client-executed
method called $sfsorder, with a single parameter, which is the set name, you can add
processing that occurs each time the set is updated. For example, you could use a tab
control to display a tab for each member in the set, where the current tab represents the
top-most subform.
You can use the ordervar list in conjunction with the subformset_formtofront
$clientcommand to manage the subforms in the set, e.g. bring a form to the front by
selecting a line in a popup menu (this is the only way to restore a minimized subform). For
example:
; the ordervar list is assigned to iOpenForms, C1 contains the
subform ID
Do $cinst.$clientcommand("subformset_formtofront",
row('SubformSet',iOpenForms.[pLineNumber].C1))
If a subform has been minimized, you would you have to use such a method to display the
subform again since minimized subforms are not visible in the parent remote form.

91
Chapter 2—JavaScript Remote Forms

Example
The following code creates a subform set containing two subforms.
; setupSubformSet method which could be called from £construct
; Create vars: iFormList (List), iID, iClassName, iParams, iTitle,
iLeft, iTop, iWidth, iHeight
; jsSub1 and jsSub2 are remote forms in the library
Do iFormList.$define(
iID,iClassName,iParams,iTitle,iLeft,iTop,iWidth,iHeight)
Do iFormList.$add(1,"jsSub1",,"subform1",10,10,200,200)
Do iFormList.$add(2,"jsSub2",,"subform2",220,10,400,200)
Do lRow.$define(lSetName,lParent,lFlags,lOrderVar,iFormList)
Do lRow.$assigncols(
"SubformSet",,kSFSflagCloseButton+kSFSflagMaxButton+
kSFSflagMinButton+kSFSflagResize,,iFormList)
Do $cinst.$clientcommand("subformset_add",lRow)
The code creates the subforms in the main remote form within the browser:

The Memo sample app available in the Welcome screen uses subform sets.

Subform Styles
The Omnis style sheet Omnis.css contains CSS classes that specify the appearance of the
subform frame of the members of subform sets, as well as the images for the maximize and
minimize buttons. You can modify these classes to give the subform frames your own style.
Open Omnis.css and search for “subform” to locate the styles.

Subform Titles
You can use $cinst.$title to change the title text for a member of a subform set.

92
Resizable Forms and Components

Subform References
You can obtain a reference to any subform instance within a subform set using the
$sfsmember root notation. For example:
$root.$sfsmember(cSetname,iUniqueID)
returns an item reference to the remote form instance for the subform set member with the
specified unique ID in the named subform set in the current remote task. This notation can
be used in server and client methods.

Resizable Forms and Components


The $dragborder and $edgefloat properties allow JavaScript components and remote forms
to be dynamically resizable at runtime in the end user’s browser. In addition, remote forms
have the $resizemode property which allows a form displayed in a desktop web browser to
be resized.

Web Form Resizing


JavaScript remote form classes have a property called $resizemode which determines
whether or not a form resizes when the end user resizes the browser window. In previous
versions, the size of a remote form was fixed regardless of the size of the browser window
displaying the form or whether or not the browser window was resized, but using the
$resizemode property you can make the form resize if required.
The $resizemode property only applies when the remote form is being displayed in a
standard browser window on a desktop computer or laptop, that is, the property does not
apply when the form is displayed in a browser on a mobile device or when the form is being
used as a subform since in this context the form size is fixed.
The value of $resizemode is one of the kJSformResizeMode... constants that specify how
the form behaves when it initially opens and when the browser window is resized. The
kJSformResizeMode... constants are as follows:
 kJSformResizeModeNone
The form does not change size when the browser window is resized and the form is
positioned at the left of the browser window. This corresponds to the behaviour in
Omnis Studio 5.2.x
 kJSformResizeModeCenter
The form does not change size when the browser window is resized but the form is
centred horizontally in the browser window, only if its width is less than the browser
window width
 kJSformResizeModeAspect
The form resizes itself as the browser window is resized maintaining its aspect ratio to

93
Chapter 2—JavaScript Remote Forms

fit the browser window; it will not resize to a size smaller than the designed size in the
remote form class
 kJSformResizeModeFull
The form resizes itself to fit the browser window, regardless of aspect ratio; it will not
resize to a size smaller than the designed size in the remote form class
You can assign $width and $height of the remote form at runtime, however this may conflict
with $resizemode, so you should only assign these properties when $resizemode is
kJSformResizeModeNone.

Component Resizing
The “floating edge” ($edgefloat) capabilities for JavaScript components allow you to resize
them at runtime, so when a remote form is resized in the end user’s browser its components
will resize automatically, if their $edgefloat property has been set as appropriate. Note that
like the form resizing, this behavior only applies when the remote form is being displayed in
a standard browser window on a desktop computer or laptop, not a browser on a mobile
device.
In previous versions, the $edgefloat property only applied to resizing components in design
mode, but the setting of $edgefloat for each component is applied at runtime when the form
is resized on the client. The $edgefloat property can be set to one of the kEF… constants
which determines which edges of the component, if any, will “float” or resize when the form
is resized. See the Omnis Help (F1) for a list of all possible settings of $edgefloat.
You can store a different setting of the $edgefloat property for each component, for each
different screen size ($screensize), which means you can set different $edgefloat properties
for web and mobile browsers. When setting $edgefloat in the Property Manager in design
mode, you can set the value of $edgefloat for all $screensize values by holding the Control
key when selecting the $edgefloat value.
The setting of $edgefloat for a component is used to resize the component (or not if set to
kEFnone) when the form or container field is resized at runtime, and when one or more of
the following occurs:
 When the component is in a subform and the subform is resized (that is, its size at
runtime is different to the size of the subform class)
 When applying a different mobile device size while running in a mobile device custom
wrapper
 When the $resizemode property of the form causes the form to resize
 When the component is in a resizable subform in a subform set and the subform is
resized

94
Running JavaScript in the Client

Draggable Component Borders


End users can resize some JavaScript components dynamically at runtime in their web
browser by dragging the border of the component. When the end user’s mouse is over the
edge of a component that can be resized, the cursor changes to indicate that the border can
be dragged and resized.
To allow this functionality, JavaScript components have a new $dragborder property, which
only applies when a component has its $edgefloat property set to one of the kEFposn…
constants (other than kEFposnClient or kEFposnJoinHeaders). If $dragborder is set to true,
and you have set $edgefloat as above, the end user will be able to resize the component at
runtime by dragging the border of the component with the mouse.
You can store a different setting of the $dragborder property for each component, for each
different screen size ($screensize), therefore components on the same form could be
resizable for web desktop browsers and not for mobile devices. When setting $dragborder
in the Property Manager in design mode, you can set the value of $dragborder for all
$screensize values by holding the Control key when selecting the $dragborder value.
The appearance of the drag border area can be modified by editing the styles div.omnis-db-
vert and div.omnis-db-horz in omnis.css.

Running JavaScript in the Client


The JavaScript: command (including the colon) allows you to execute any native JavaScript
in the client browser directly from your Omnis code; this can include calls to other
JavaScript embedded into or linked to the HTML page containing your JavaScript remote
form. Omnis does not perform any validation of the code you insert into the JavaScript:
command in the method editor (you can check for errors in the JavaScript console of the
browser). You cannot include any square bracket notation in the code parameter of the
JavaScript: command, since the code needs to be evaluated by the server when generating
the script file. A simple example would be to open an alert in the browser with the standard
alert() function, as follows:
JavaScript: alert("Hello World");
Since this command executes native JavaScript code on the client it must be executed in a
client-side method. The JavaScript: command will only appear in the Command list in a
method that is enabled to execute on the client. Omnis will not allow the JavaScript:
command to be present in a server method (an error occurs). If you try to execute
JavaScript: on the server, by calling a client-side method from a server method, a debugger
error will occur.
You can include JavaScript in the HTML page containing your remote form (inline or
linked), and call code in these scripts from your remote form code using the JavaScript:

95
Chapter 2—JavaScript Remote Forms

command. To extend the alert() example above, you could embed a JavaScript function in
your HTML page, like this:
<html>
<head>
<script type="text/javascript">
function show_alert()
{
alert("Hello World");
}
</script>
</head>
<body>
<!-- body including the omnisobject containing your form -->
</body>
</html>
And call this function from your Omnis code using the JavaScript: command as follows:
JavaScript: show_alert();

Another example could include using the JavaScript: command to “push” events to Google
Analytics to track certain actions or events in your application. To do this you would need
to add the standard Web Analytics code provided by Google into your HTML page
(containing your remote form) and call the gaq.push() function with the correct parameters
from within your Omnis code.

Example Using the JavaScript: Command


A possible use for the JavaScript: command is for an event handler. You could use the $init
method to install an event handler, such as:
JavaScript:
document.getElementById("jsTEMP1_1076_client").onselect=function(
event) { __form.callMethodEx("selected",0,event); };
JavaScript: window.addEventListener("keydown",function(event) {
__form.callMethodEx("keydown",0,event) }, true);
Note that in both of these examples you can use __form.callMethodEx to call an instance
method of the remote form. The second parameter (zero in these examples) are flags which
control how callMethodEx behaves – these must always be passed as zero.
You could use the $init method to assign additional style information to controls on the
form. For example:
Do $cinst.$objs.$sendall($cinst.$addboxshadow($ref))
$addboxshadow is a form method with parameter pObj. The following JavaScript:
command adds a box shadow if the browser supports it.
JavaScript: pObj.elem.style.boxShadow="0px 0px 5px 5px #888888";

96
Styled Text

Styled Text
You can insert various text styles in some of the JavaScript components wherever text is
displayed. For example, you can insert colors, font styles, and images into the text within
the list control, the droplist control, the data grid control, and the hyperlink control.
Text styles can be inserted using the style() function, in both server and client methods. The
style() function inserts a style-character represented by an Omnis constant into a calculation
or a text block. The styles that can be used include some of the existing constants (listed
under ‘Text Escapes’ in the Omnis Catalog) and a few new ones, prefixed kEscJs...,
introduced for the JavaScript Client. The following style constants can be used:

Style Description
kEscColor In a client-side method, the color parameter must be a numeric literal or
constant.
kEscStyle In a client-side method, the style parameter must be a numeric literal or
constant.
kEscBmp In a client-side method, the icon id parameter must be either a numeric
literal, or the sum of a numeric literal and an icon size constant e.g.
1710+k48x48
kEscJsNewline No additional parameters are required. Inserts a <br> line break tag. See *
kEscJsClose No additional parameters are required. Closes the current open style
information (inserted by kEscColor or kEscStyle) in the styled text and
reverts to the original color and text style. Note - kEscColor and
kEscStyle insert a <span> tag to style the text. kEscJsClose closes the
<span> tag.
kEscJsHtml Inserts raw HTML (the second parameter to style()).

97
Chapter 2—JavaScript Remote Forms

* There is also a new function br() which can be used as short-hand to insert a new line.
The br() function and kEscJsNewline can only be used with styled text for the JavaScript
client.
The following example code produces a list line which looks like this from the styled text
data in iChar:

Calculate iFloatRight as style(kEscJsHtml,"<span


style='float:right;'>")
Calculate iFloatLeft as style(kEscJsHtml,"<span
style='float:left'>")
Calculate iSmallFont as style(kEscJsHtml,"<span style='font-
size:8pt'>")
Calculate iCloseSpan as style(kEscJsHtml,"</span>")
Calculate iIcon as style(kEscBmp,1710+k32x32)
Calculate iOpenP as style(kEscJsHtml,"<p
style='height:36px;margin:0px'>")
Calculate iCloseP as style(kEscJsHtml,"</p>")
Begin text block
Text: [iOpenP][iFloatLeft]Left text[iCloseSpan]
[iFloatRight]Right[iIcon][iCloseSpan][br()]
[iSmallFont][style(kEscStyle,kItalic)]
[style(kEscColor,kRed)]Line 2[iCloseSpan][iCloseP]
End text block
Get text block iChar

Animations
JavaScript remote forms have the methods $beginanimations() and $commitanimations()
which allow you to control animations for some controls.
 $beginanimations(iDuration[,iCurve=kJSAnimationCurveEaseInOut])
after calling this, assignments to some control properties are animated for iDuration
(milliseconds) by executing $commitanimations()
 iCurve values are:
kJSAnimationCurveEaseInOut (the default), kJSAnimationCurveEaseIn,
kJSAnimationCurveEaseOut, kJSAnimationCurveEase and kJSAnimationCurveLinear
The animated properties are: left, top, width, height, alpha, backcolor, backalpha, textcolor,
fontsize, bordercolor, linestyle, buttoncolor (the latter is for pushbutton only).
If you set the same property for an object more than once, the first property change is
animated, and then the last property change is animated when the first completes. Property

98
Time Zones and Dates

changes between the first and last are ignored. The evAnimationsComplete event (for
remote forms) is generated after the last property change(s) have completed. This allows
you to reverse the effect of an animation (which is the equivalent to the autoreverse/repeat
options available on iOS).
The sample apps in the Welcome window contain an About form which is loaded into a
subform on the main sample app form. Animations are used to display the About subform,
which initially has the $alpha value of zero (fully transparent) and is increased to 255 during
the animation, as follows:
; method behind About button
On evClick
Switch iScreensize
; set aboutSubForm size for different devices
Etc.
End Switch
Do $cinst.$objs.aboutSubForm.$classname.$assign("jsAbout")
Do $cinst.$objs.aboutSubForm.$visible.$assign(kTrue)
Do $cinst.$beginanimations(500,kJSAnimationCurveEaseIn)
Do $cinst.$objs.aboutSubForm.$alpha.$assign(255)
Do $cinst.$commitanimations()

Time Zones and Dates


The JavaScript Client exchanges dates and times between the server and client using UTC
time, regardless of where your server is located (note that UTC is essentially the same as
GMT but UTC is used globally as the standard time for web servers). You should therefore
store all dates and times in UTC and use the time zone offset of the client to either
determine or set the local time of the client. The $construct row variable parameter for the
remote task/form has a column JStimezoneOffset, which is the timezone offset in minutes
for the client relative to UTC time. For example, if the client’s local time zone is UTC+2
(or GMT+2), JStimezoneOffset will be 120. See the ‘Construct row variable’ section for
more information about the $construct row variable for tasks/forms.

Time Zone Functions


There are a number of Omnis functions that allow you to convert local dates and times to
UTC since the client and server need to both use UTC time: they are listed in the ‘Date and
Time’ group in the Omnis Catalog (F9/Cmnd-9).
 loctoutc() and utctoloc()
Converts the specified datetime (or time) from the local timezone to UTC (Coordinated
Universal Time), or vice versa, and returns the result

99
Chapter 2—JavaScript Remote Forms

 tzcurrent(), tzstandard(), tzstandard()


Returns the character string identifying the time zone, daylight saving time zone, or the
standard time zone of the current date and time of Omnis
You should note that on 32-bit Windows the TZ codes returned by the timezone (tz)
functions are the long time zone names and not the short abbreviated time zone names. If
you want to use the short time zone names, you can add a mapping to studio.stb, from the
full name to the abbreviation you wish to use.

Local Time
The $jslocaltime task property allows you to switch to Local time rather than UTC. If true,
the JavaScript Client and the Omnis App Server exchange date-time values in local time
rather than UTC time. $jslocaltime must be set in design mode: it cannot be assigned at
runtime.

Date Calculations
The dadd() function can be used in client executed methods to adds a number of “date
parts” to the given date. The sybtax of the function is:
dadd(datepart,number,date)
The datepart parameter determines what is added to the specified date and is one of a
number of constants: kYear, kMonth, kWeek, kQuarter, kDay, kHour, kMinute, kSecond,
kCentiSecond. The number is interpreted as the number of date or time parts or units
specified by a datepart constant. The number argument must be an integer when specifying
datepart as kYear, kMonth, kWeek, kQuarter, or kCentiSecond (the fractional part of a
number is ignored). You can use fractions for the other date parts.

PDF Printing
There is a printing device (external component) to allow you to print a report from Omnis
Studio to a PDF file and display it in the JavaScript Client in the end-user’s web or mobile
browser. There are two client commands (used with $clientcommand) to allow you handle
PDF reports in the JavaScript Client (if the end user’s device supports PDF). See the Omnis
Programming manual for more information about creating report classes to format your
PDF reports.
The PDF Device is available for Windows and OS X. Various supporting files are located
in the ‘python’ folder within the main Omnis Studio folder, and the PDF component itself is
in the ‘xcomp’ folder: these files need to be present in the Omnis App Server when you
deploy your web or mobile app.

100
PDF Printing

Note for existing users


The new PDF device replaces the “Custom Report Device” available in previous versions
(for Linux only). The constant kDevOmnisPDF is now used for the new PDF device,
therefore if you have used the “Custom Report Device” on Linux in previous versions, you
must now use kDevOmnisPrintPDF on Linux to refer to the old print device. In addition, the
device parameters for the Linux PDF device have been renamed to
kDevOmnisPrintPDFAutoOut and kDevOmnisPrintPDFAutoCommand.

Fonts
The PDF device will only work with Reports that use TrueType fonts, and using other fonts
may cause an error during PDF generation. Specifically only fonts contained in “.ttf”, “.ttc”
or “.dfont” files can be used. Therefore you must choose TrueType fonts for your report if
you intend to print using the new PDF device.
Ensure that all fonts used in your PDF reports are in the specified locations within the
rl_config.py file stated under the 'T1SearchPath' section within the rl_config.py file which
can be found in the following folder:
omnis\python\App\Lib\site-packages\reportlab
Any installed font that is used in your report and not in one of these locations will result in
an error message when attempting to print to the PDF Device.

Icons in PDF report text


You can include icons in text in a report printed to PDF using the style() function and the
kEscBmp escape constant. For example, you can use con(style(kEscBmp,1400),’some text’)
in a report entry field calculation to display an icon on a report.

PDF Print Destination


The new component is called OmnisPDF and appears as a new print option in the Print
Destination dialog, available to end users from the main File menu. If the end user selects
PDF as the report destination, then when they print a report, it will either be sent to a report
file specified in $prefs.$reportfile, or if this preference is empty Omnis will prompt the user
to select the path of the output PDF file. Note that this mechanism can be overridden
programmatically by using the $settemp method (see below).

101
Chapter 2—JavaScript Remote Forms

Printing PDF Using Code


To send a report to PDF programmatically, you can use the following code:
Calculate $cdevice as kDevOmnisPDF
Set report name MyReportClass
Print report
; or
Calculate $cdevice as kDevOmnisPDF
Set reference lReportInst to $clib.$reports.New Report.$open('*')
Do lReportInst.$printrecord()
Do lReportInst.$endprint()
In both of these cases the report will be sent to a report file specified in the
$prefs.$reportfile preference. Note that there is a separate value of $prefs.$reportfile for
each Omnis App Server stack (thread) and the main Omnis thread. If $prefs.$reportfile is
empty, and the code is running in the main Omnis thread, Omnis will prompt the user for
the destination PDF file; otherwise, if $prefs.$reportfile is empty and the code is running in
another thread, Omnis will generate a runtime error.

PDF Device Functions


The PDF device has a number of functions to allow you to set up reports sent to temporary
PDF files, to set up document properties, and to add security features such as passwords and
encryption.
$settemp()
The $settemp function allows you to specify that the next report will print to a temporary
PDF file in the omnispdf/temp folder. The function returns the name of the file that will be
created in omnispdf/temp (or an empty string if bTemp is kFalse). You can specify a
timeout in minutes whereupon the temporary PDF file will be deleted.
Do Omnis PDF Device.$settemp(bTemp,iTimeout) Returns cID

bTemp A Boolean: kFalse means a temporary file will not be used. kTrue means
the next report sent to PDF by the current task instance will be written to a
temporary file in the folder “omnispdf/temp” in the data part of the Omnis
Studio tree. Note that after the next report has been sent to PDF, the stored
value of bTemp will revert to kFalse.
iTimeout An integer: Only used when bTemp is kTrue. If omitted defaults to 10. The
time in minutes for which the next PDF file generated by the current task
will remain on disk. When the time expires, the Omnis PDF device
automatically deletes the file. Note that Omnis automatically deletes any
files left behind in omnispdf/temp when it starts up.

102
PDF Printing

Each task instance (including remote tasks) stores its own information set up using
$settemp. This allows $settemp to be used in one thread on the Omnis Server without
affecting other threads/clients.
$setdocinfo()
The $setdocinfo function lets you specify the author, title and subject properties for the PDF
documents generated by the current task. The author, title and subject parameters are all
strings, and the function returns kTrue for success.
Do Omnis PDF Device.$setdocinfo(cAuthor,cTitle,cSubject) Returns bOK

$encrypt()
The $encrypt function sets encryption (security) properties for the PDF documents
generated by the current task, and the function returns kTrue for success. The full syntax is:
Do Omnis PDF Device.$encrypt(
cUserPassword
[,cOwnerPassword='',
bCanPrint=kTrue,
bCanModify=kFalse,
bCanCopy=kTrue,
bCanAnnotate=kFalse]) Returns bOK
The parameters are as follows:

cUserPassword A character string: The user password for the document. If this is set
to empty then none of the other arguments apply and the document
will not be encrypted; otherwise the document will be encrypted and
the user password and other properties specified by this function will
be applied to it.
cOwnerPassword A character string: The owner password for the document. The default
is no password is assigned.
bCanPrint A Boolean: Specifies if the user can print the PDF document. The
default is kTrue.
bCanModify A Boolean: Specifies if the user can modify the PDF document. The
default is kFalse.
bCanCopy A Boolean: Specifies if the user can copy from the PDF document.
The default is kTrue.
bCanAnnotate A Boolean: Specifies if the user can annotate the PDF document. The
default is kFalse.

Security in Third-party PDF readers


The optional security parameters will be applied to the PDF file if you include them in the
$encrypt() function, but you should note that the third-party PDF viewer the end user is
using may not support these settings or may just choose to ignore them. The password
specified in cUserPassword should be interpreted by all PDF readers.

103
Chapter 2—JavaScript Remote Forms

PDF Printing in the JavaScript Client


PDFs generated by the new device can be used with the JavaScript Client. There are two
new client commands (used with $clientcommand) called “showpdf” and “assignpdf” to
display PDF files on the client. You should avoid generating large PDF documents to use
with the JavaScript Client since the generated PDFs are streamed from the Omnis App
Server (i.e. via a Web Server if one is being used). An alternative would be to output the
PDF document into the Web Server’s file system, and use a URL to the PDF on the Web
Server to send it to the client.

showpdf
The showpdf client command opens the specified PDF in a new window or tab. There is no
control over whether the PDF is opened in a new window or tab: typically this depends on
the end-user browser settings, including their setting for popups.
Do $cinst.$clientcommand("showpdf",row-variable)

Where row-variable is row(pdf-id, timeout, pdf-filename)


 pdf-id
A character string. Either a full pathname of a PDF file on the Omnis server, or an id
returned by $settemp
 timeout
An integer being the time in seconds that the client is prepared to wait for PDF
generation to finish. Defaults to 60. If PDF generation does not complete in time, or an
error occurs, Omnis returns a PDF document containing a suitable error message.
 pdf-filename
the file name of the PDF file
The following method generates a PDF and displays it on the client:
Calculate $cdevice as kDevOmnisPDF
Do Omnis PDF Device.$settemp(kTrue,1) Returns lID
Set report name New Report
Do Omnis PDF Device.$encrypt('bob','owner',1,0,0,0)
Do Omnis PDF Device.$setdocinfo('Bob','Title','Subject')
Print report
Do $cinst.$clientcommand("showpdf",row(lID,20))

assignpdf
The assignpdf client command opens the specified PDF in a PDF viewer control in the
current remote form instance. The PDF must be assigned to an HTML control in the remote
form which tries to open the PDF file using the PDF viewer installed in the end user’s
browser.

104
PDF Printing

Do $cinst.$clientcommand("assignpdf",row-variable)

Where row-variable is row(html-object-name, pdf-parameters, pdf-id, timeout, pdf-


filename)
 html-object-name
The name of an HTML Object control in the current remote form instance. The HTML
content of this object will be replaced with that necessary to display the PDF document
in a PDF viewer control.
 pdf-parameters
PDF viewer parameters. These apply when the PDF is viewed in a browser that uses the
standard Adobe PDF viewer control. They control the look and behavior of the PDF
viewer. See the Adobe website for details about the PDF Open Parameters.
 pdf-id
A character string. Either a full pathname of a PDF file on the Omnis server, or an id
returned by $settemp
 timeout
An integer being the time in seconds that the client is prepared to wait for PDF
generation to finish. Defaults to 60. If PDF generation does not complete in time, or an
error occurs, Omnis returns a PDF document containing a suitable error message.
 pdf-filename
the file name of the PDF file
The following method creates a report and assigns it to an HTML control in the remote
form.
Calculate $cdevice as kDevOmnisPDF
Do Omnis PDF Device.$settemp(kTrue,1) Returns lID
Set report name New Report
Do Omnis PDF Device.$encrypt('bob','owner',1,0,0,0)
Do Omnis PDF Device.$setdocinfo('Bob Smith','Title','Subject')
Print report
Do $cinst.$clientcommand(
"assignpdf",row(“htm”,”toolbar=1&zoom=20”,lID,10))
If you set the $html property of the HTML Object control to “<div %e></div>” the PDF
viewer will have the same border, position and dimensions as the designed control on the
remote form. Note that this command will not work on Android with the default web
browser, since it does not support the application/pdf plug-in. If the application/pdf plug-in
is not available on Android, it executes showpdf instead.

105
Chapter 2—JavaScript Remote Forms

Print PDF Example


The following methods will allow the end user to print a report to a PDF file: these methods
use the built-in PDF Device methods and the client commands.
; button to open PDF report
; create var lID (Char)
On evClick
Do $cinst.$createReport() Returns lID
Do $cinst.$clientcommand(
"showpdf",row(lID,60))
; or button to display PDF report in current remote form
; create var lID (Char), oHTML is an HTML obj on the form
On evClick
Do $cinst.$createReport() Returns lID
Do $cinst.$clientcommand(
"assignpdf",row("oHTML","toolbar=1&zoom=20",lID,20))
Here is the code for the $createReport() remote form method:
Calculate $cdevice as kDevOmnisPDF
If iSaveCopy ;; linked to check box on the form
Do Omnis PDF Device.$settemp(kFalse) Returns lID
Calculate lSaveLocation as left(sys(10),rpos(sys(9),sys(10)))
Calculate lSaveLocation as
con(lSaveLocation,"savedReports",sys(9),iFileName)
Calculate $prefs.$reportfile as lSaveLocation
Else
Do Omnis PDF Device.$settemp(kTrue,1) Returns lID
End If

Set report name repNice


If iEncrypt
Do Omnis PDF Device.$encrypt(
iUserPass,iOwnerPass,iCanPrint,iCanModify,
iCanCopy,iCanAnnotate) Returns #F
End If
Do Omnis PDF Device.$setdocinfo(iAuthor,iTitle,iSubject) Returns #F
Print report

If iSaveCopy
Quit method lSaveLocation
Else
Quit method lID
End If

106
PDF Printing

107
Chapter 3—JavaScript Components

Chapter 3—JavaScript
Components
The Component Store contains over 30 ready-made components for the JavaScript Client
which you can drag and drop onto a JavaScript remote form. The components are displayed
under the “JavaScript Components” tab in the Component Store (assuming the $client
property is set to kClientJavaScript, which is the default for all new remote forms).

The following components are available for JavaScript remote forms:

Component Description
Activity Control Animated image to display during Omnis Server activity
Background Control Object you can set to Rectangle, Line, Triangle, or Image
Bar Chart Control Displays a bar chart based on a list of values
Button Control Standard pushbutton which reacts to clicks
Checkbox Control Check box for on/off values
ComboBox Field combining entry box and droplist
Complex Grid Grid which can display all types of data and formatting
Data grid Control Simple grid for text and numerical data display
Date Picker Control Data picker with touch selection
Device Control Allows access to hardware and services on mobile device
Droplist List that drops down when clicked
Edit Control Standard edit field for data entry or display
File Control Allows end users to upload or download files

108
PDF Printing

Component Description
HTML Object Object to display HTML content
Hyperlink Control List containing hyperlink style options
Label Object Basic label object
List Control Standard list field for displaying list variable data
Map Control Displays a Google map for specified location(s)
Navigation Bar Control Navigation with touch selection
Page Control Allows selection of page pane using touch
Paged Pane Can contain fields on multiple panes
Picture Control Standard field for displaying images
Pie Chart Control Displays a pie chart based on a list of values
Popup Menu Control A menu that pops up when clicked
Progress Bar Control Shows progress of server process or calculation
RadioGroup Control Displays a group of radio buttons for exclusive selection
Rich Text Editor Control Text field that allows end user to edit text
Slider Control Slider component for setting values
Subform Allows you to insert another remote form as a subform
Switch Control Allows on/off selection; you specify an icon for on/off state
Tab Control Multiple tabs to control selection of page pane
Timer Control Timer object triggers an event at a specified interval
Tree Control List for displaying hierarchical data or list of options
TransButton Control Button with hover over effects
Video Control Plays a YouTube or Flowplayer video

Example Apps and Code


The JavaScript Apps Gallery on the Omnis website (www.tigerlogic.com/omnis) showcases
many of the JavaScript Components and provides a sample app which you can download
and run in the latest version of Omnis Studio. Many of the sample apps in the gallery are
featured in the sample code in this chapter.
In addition, the Welcome screen in Omnis (available via the New Users button in the main
Omnis toolbar) has several sample web apps that use many of the JavaScript Components,
including a Contacts manager for recording information about colleagues or friends, a
Holidays app for managing annual leave requests, and a Webshop app which has a product
catalog and shopping cart.

109
Chapter 3—JavaScript Components

JavaScript Component Properties


All JavaScript components have their own set of properties which you can view and set in
the Property Manager (F6).

Setting Properties using the Field List


When designing a remote form, you often need to click on the background of the form to set
its properties in the Property Manager. This may be difficult if your form is completely
filled with components and no form background is available to click on, as is often the case
for mobile forms. To select the form in this case, you can use the Field List (right-click
anywhere on the form, open the Field List and check the form name to open the Property
Manager for the form), or if you click on any individual component, then shift-click it to
deselect it, the focus will be returned to the form and its properties will be shown in the
Property Manager.

$dataname for JavaScript Controls


The variable specified in the $dataname property of a JavaScript component must be an
instance variable, or in some cases a column in a row instance variable.

Naming JavaScript Controls


When you create a component in your remote form, a name is generated automatically and
assigned to the $name property of the component. This is usually in the format
<remoteformname>_<component-type>_<number>, such as ‘rftest_edit_1001’ for an edit
control on a remote form called rftest. However, you can enter your own name for a
component which may better describe the object within the context of your form; for
example, an edit field to allow the end user to enter their first name could be named
Firstname. You can change $name of a component in the Property Manager.
The name you assign to an object does not have to conform to any convention other than
any conventions you may like to use in your forms or the application to identify different
objects. The name of a component (specifically the value in $name) can be used in the
Omnis notation and throughout your library to refer to the object. You should therefore not
use spaces and try to use alphanumeric characters only for object names to avoid any
possible conflicts in your code. For example, an object name should not include the dollar
sign ($) since this would cause a conflict when you reference the object using the Omnis
notation which prefixes property and method names with the dollar sign.

Control Size and Float Properties


All the JavaScript components have the $screensizefloat property which controls their
automatic resizing and floating properties when contained inside the wrapper which is

110
JavaScript Component Properties

provided to allow you to create standalone custom apps for iOS and Android. See the
Standalone Mobile Apps section for more details.

Date and Time Formatting


You can set the formatting for Date and Time type data for some of the JavaScript
components including Edit controls, Combo boxes, Data grids, Droplists, Hyperlink lists
and standard Lists. These components have the properties:
 $dateformatcustom
a date-time format string using the characters described below. If $dateformat is
kFormatCustom, and the data is of type 'Date Time', this property is used to format the
data. If empty, it defaults to the format set using the 'setcustomformat' client command
(set using $clientcommand); see ‘Multiple data formats’ below
 $dateformat
the format used to display 'Date Time' data, a kJSFormat... constant as follows:

kJSFormatNone No format
kJSFormatTime Default time format for client locale
kJSFormatShortDate Default short date format for client locale
kJSFormatShortDateTime Default short date and time format for client locale
kJSFormatMediumDate Default medium date format for client locale
kJSFormatMediumDateTime Default medium date and time format for client locale
kJSFormatLongDate Default long date format for client locale
kJSFormatLongDateTime Default long date and time format for client locale
kJSFormatFullDate Default full date format for client locale
kJSFormatFullDateTime Default full date and time format for client locale
kJSFormatCustom Use the custom format in $dateformatcustom

Date formatting characters


The date formatting characters for $dateformatcustom are D, V, w, E, n, M, m, y, Y, A, H,
h. Some additional characters are supported for Date/Time formatting for the JavaScript
Client components only, as follows:
j day with no leading zero (6)
P month with no leading zero (6)
K hour with no leading zero (0..23)
k hour with leading zero (1..12)
a am/pm
O timezone offset (+01:00)

111
Chapter 3—JavaScript Components

There is a new entry on the Constants tab in the Catalog (F9) called "Date codes (JavaScript
Client only)" that lists the formatting characters.

Multiple date formats


You can specify multiple date formats in the $dateformatcustom property for entry fields in
a remote form, which allows end users to input a date using one of a number of possible
formats, rather than being limited to a single date format. The multiple date formats can be
entered into $dateformatcustom separated using “|” (the pipe character), for example:
D/M/y|D m y|d-m-y|D/M/Y|D/m/y|D-M-y|D M y
When parsing data entered by the user, the client uses each format in order, until one
successfully matches the user input. The client uses the first format in the list to format the
data for display.
Date formatting and Locale
When the client connects, the server sends it the date formats, day names and month names
for the client locale (the server reads these from ICU). If you assign
$ctask.$stringtablelocale in $construct of your remote task, the server sends the client the
formats and so on for the assigned $stringtablelocale locale.

Date functions
Omnis has a set of built-in global variables called hash variables (since their names begin
with #) including a set of date and time variables. There are a number of functions to
provide you with access to the values stored in the hash variables from within client
executed methods in the JavaScript Client. Note that the default value of these variables
may depend on the language version of Omnis Studio you are using.
The date and time related functions use the special date format characters listed under the
‘Date codes’ item on the Constants tab in the Catalog (press F9/Cmnd-9).
 fmtshortdate()
fmtshortdate([newformat]) either sets #FD to newformat and returns the previous value
of #FD, a string used to format Short dates; or if no parameter is supplied returns the
current value of #FD (default value is 'D m y')
 fmtshorttime()
fmtshorttime([newformat]) either sets #FT to newformat and returns the previous value
of #FT, a string used to format Short times; or if no parameter is supplied returns the
current value of #FT (default value is 'H:N')
 fmtdatetime()
fmtdatetime([newformat]) either sets #FDT to newformat and returns the previous
value of #FDT, a string used to format Long date and time values; or if no parameter is
supplied returns the current value of #FDT (default value is 'D m y H:N:S')
 fmtdp() (not available in client executed methods)
fmtdp([newdps]) either sets #FDP to newdps and returns the previous value of #FDP, a

112
JavaScript Component Properties

numeric variable which specifies the format used for display or string conversion of a
floating point number; or if no parameter is supplied returns the current value of #FDP
(defaults to 12)
 getdatetime()
returns the current system date and time, formatted using #FDT
 getticks()
returns the number of ticks elapsed since system boot; a tick is 1/60th of a second. The
value can overflow and restart at zero (for a JavaScript client executed method, the
number of ticks since midnight on 1 Nov 2011).
The JavaScript client uses #FD and #FT for short date and short time instance variables in
client methods; previously it used #FDT when converting short dates and times to character
data.

Number Formatting
All JavaScript controls that can display number data have the property $numberformat,
which specifies how Number and Integer data is formatted or displayed in the control. The
JavaScript controls affected include the Edit Control, Combo box, Data grid, Droplist,
Hyperlink list and standard List control. The formatting is used when the control displaying
the data does not have the focus, so for example, the formatting is applied when the end user
tabs or clicks away from the number field.
The $numberformat property uses a single % format tag for the number followed by one or
more elements, for example, the number format %.2F displays a number with 2 decimal
places with a thousand separator. The following elements are available (in this order):
An optional "+" sign that forces to precede the result with a plus or minus sign on numeric
values. By default, only the "-" sign is used on negative numbers.
An optional padding specifier used for padding (if padding is required). Possible values are
0 or any other character preceded by a '. The default is to pad with spaces.
An optional "-" sign, that causes the string to left-align the result of this placeholder. The
default is to right-align the result.
An optional number that says how many characters the result should have. If the value to be
returned is shorter than this number, the result will be padded.
An optional precision modifier consisting of a "." (dot) followed by a number, specifies how
many digits should be displayed for floating point numbers. When used on a string, it causes
the result to be truncated.

113
Chapter 3—JavaScript Components

A type specifier that can be any of:


% print a literal "%" character
b print an integer as a binary number
c print an integer as the character with that ASCII value
d print an integer as a signed decimal number
e print a float as scientific notation
u print an integer as an unsigned decimal number
f print a float as is
o print an integer as an octal number
s print a string as is
x print an integer as a hexadecimal number (lower-case)
X print an integer as a hexadecimal number (upper-case)

Autoscrolling
You can enable automatic scrolling for Edit controls, Lists, Tree lists, Hyperlink controls,
Pictures and Html controls by enabling the $autoscroll property. If this property is kTrue for
the control, and the client is not a mobile device, the client automatically displays
scrollbar(s) when not all of the content in a field is visible.
Setting $autoscroll to kTrue changes $horzscroll and $vertscroll to kFalse, and in doing so
means you cannot set $horzscroll and $vertscroll. By default, $autoscroll is enabled for Edit
controls, Lists and Tree lists, while for Hyperlink controls, Pictures and HTML controls
$autoscroll is set to kFalse.
Note that in addition to controlling scroll bars, Data Grids and Lists have the $vscroll and
$hscroll properties which allow you to scroll a grid or list vertically or horizontally at
runtime in the client browser: the numeric value of these properties is either column or row
offset for grids, or the pixel offset for lists.

Rounded Borders
All the JavaScript components can have rounded borders by specifying the corner radius in
pixels in the $borderradius property. To set all the corners of the object to the same radius
you can enter a single value, or to specify the radius for different corners you can use the
syntax "n-n-n-n" which follows the same rules as CSS 3 rounded border syntax. The order
for the radius parameters is top-left, top-right, bottom-right, bottom-left. If bottom-left is
omitted the top-right value is used, if bottom-right is omitted the top-left value is used, if
top-right is omitted the top-left value is used.

114
JavaScript Component Events

Custom CSS Styles


You can create your own CSS classes or styles and apply them to the objects in your web
and mobile apps, allowing you to have more control of the styling, coloring, and overall
design of your apps.

CSS classes for Controls


All the JavaScript components have a property called $cssclassname which allows you to
apply your own CSS class to the component. You can add the CSS classes to a file called
‘user.css’ which is located in the ‘html/css’ folder in the main Omnis Studio folder. A style
can be applied to a control by setting its $cssclassname property to the name of a style. The
properties you define for each style in user.css must be flagged as !important to override the
JavaScript Client inline styles.
When you deploy your application on the Omnis App Server, you must put your custom
‘user.css’ file in the ‘html/css’ folder on the server.

JavaScript Component Events


Most of the JavaScript components report events which you can handle in an event method
($event) inserted behind the component. For example, when the end user clicks a button, an
evClick is generated which you can trap in the $event method for the button; this method
could display a message, initiate another method or determine some other action depending
on the code in the event method.

Enabling Events
Many of the components have their events enabled by default, but for some you may need to
enable specific events in the $events property for the component.
To enable an event
 Select the component and open the Property Manager (press F6)

 Click on the $events property in the Property Manager to drop down the list of events
for that component (the property will show “No Events” when no events are selected)

 Check (enable) the events you wish to trigger for this component

If you double-click a component in design mode, the Method Editor will open displaying
the method for that individual component. For components with events, the $event method
will be shown. For example, if you double-click on a button, the Method Editor will open
displaying the $event method containing the code On evClick; you can add more code after
this line to be run when the end user clicks the button. See the example code for each
component for example $event methods.

115
Chapter 3—JavaScript Components

Standard Field Events


Most JavaScript fields or controls report the evBefore and evAfter events, which are
triggered when the focus is about to enter or leave the control, respectively. You can use the
On event command to detect events in your event handling methods. For example, in the
$event() method for Edit control you could use the following commands to detect the
evBefore or evAfter event.
On evBefore
; do something..
On evAfter
; do something else..

Buttons and Lists


Buttons and all the list type JavaScript controls report the evClick event, as well as
evBefore and evAfter; and some list types also report the evDoubleClick event. For
example, the data grid control reports evDoubleClick which you could detect and initiate a
search based on the content of the grid line clicked on.

JavaScript Component Icons


Some of the JavaScript Controls allow you to add an icon, such as a Button, to create a
more appealing user interface for your apps. Such controls that support icons have the
$iconid property which allows you to specify the image to be used for the control. You can
use images that are 1.5 and 2 times the resolution (pixel density) of images that are used for
standard monitors, which means such images will be rendered in high definition on the most
recent smartphones and tablets, such as the Apple iPhone 5 or Samsung Galaxy S4.

Note to Existing Users


The existing method of storing icons in #ICONS or an Icon file and assigning the numeric
Icon ID ($iconid) to controls will continue to work, but new JavaScript remote forms do not
have the $iconpages property. To support high definition images for controls you can now
create and store icon images outside of Omnis but assign them to controls by specifying an
icon ID as before. These icon images are stored in the ‘html/icons’ folder in your Omnis
development folder and in the Omnis App Server when you deploy your application.
When Omnis references an Icon ID it will search for the icon in the ‘html/icons’ folder, then
it will search the #ICONS in the current library and then any other Icon datafiles. The new
icons will only be available to JavaScript Client remote forms (and for window classes in
the fat client). The Web Client plug-in and the iOS Client will not be able to use the new
icons, since those clients only support the current icon page system.

116
JavaScript Component Icons

Creating Icon Images


You can create your icons in any third-party image editing software and place the images
directly in the Omnis tree without having to import them into Omnis using the Icon Editor.
The icon or image files must be saved using the PNG file type and placed in a sub-folder of
the ‘html/icons’ folder in the main Omnis product tree. Each sub-folder represents what is
called an icon set which is a named collection of icons. The name of the sub-folder in the
icons folder is the name of the icon set. Note that an icon set cannot be named ‘datafile’ or
‘lib’ since those names are already used in the icons folder. Any files and folders that do not
conform to the naming conventions are ignored.
Image File names
Each image file within an icon set must conform to the following naming convention:
<text>_<id>_<size><state>_<resolution>.png
 <text> is the name of image. This string is used in the icon picker dialog when you set
an object’s $iconid in the Property Manager.
 <id> is the positive integer id to be used as the icon id. It can be in the range 1 to
10000000.
 <size> is the CSS pixel size of the image, i.e. the resolution independent size of the
image, meaning that for all resolutions of the same image this has the same value.
The value of <size> has the form <width>x<height>, where the values 16x16, 32x32 and
48x48 are special values since they correspond to the standard icon sizes supported by
Omnis.
 <state> is the checked, highlighted, or normal state of the icon for multi-state icons and
can be one of the following:
an empty string for the normal state of the icon
“c” is the checked state of the icon
“h” is the highlighted state of the icon
“x” is the checked highlighted state of the icon
 <resolution> is the factor by which the pixel density is greater than a standard monitor
and is one of the following:
“_2x” for HD devices such as the Retina display
“_15x” for some devices e.g. certain Android phones that have a 1.5x pixel density.
an empty string is the default and is for standard resolution devices, equivalent to _1x

117
Chapter 3—JavaScript Components

Example file names are:


pencil_1657_16x16.png Normal state 16x16 icon with ID 1657 for
standard resolution devices
pencil_1657_16x16_2x.png Normal state 16x16 icon with ID 1657 for HD
resolution devices
check_1658_32x32c_2x.png Checked state 32x32 icon with ID 1658 for HD
resolution devices
Note that the image file names are case insensitive and they must be unique across all
platforms and file systems (that is the case of file names is ignored).
You do not have to create an icon image for all resolutions – Omnis will use an icon image
closest to the resolution being referenced, scaling as appropriate, but as with all image
scaling it is better to force Omnis to scale an image down than to scale it up. Therefore, you
may like to provide the highest possible resolution image for your icons and allow Omnis to
scale the images to display the lower resolutions.
When the JavaScript Client connects, it sends its resolution to the Omnis App Server. This
allows the server to use the appropriate icon when setting iconid properties in server
methods.

Non-standard Size Images


You can create images with a size other than the standard sizes (16x16, 32x32, 48x48) by
creating the image at a non-standard size and including the image size in the file name when
the file is saved. For example, you can create an image 100x200 pixels and name it
something like “mygraphic_1688_100x200.png”. Existing users should note that this is the
equivalent of an ‘Icon Page’ in the old icon support.
Setting the Icon set in your library
Libraries have a new preference, $iconset. This is the name of the icon set to be used when
resolving icon ids for the JavaScript client and the fat client in the current library. When
using this library, and when looking up an icon for the fat client or JavaScript client, Omnis
will search for icons within this icon set before following the current icon search path for
the library. In this case icons present in the icon set will take precedence over those in
#ICONS, omnispic.df1, etc.
Setting the Icon ID for objects
When you set the $iconid of an object using the Property Manager, the icon set for the
current library will be shown in the Icon picker dialog ($iconset must be set for the library
for the icon set to appear) allowing you to select one of the icons in the set. You can select
the icon required and the Icon ID will be assigned to $iconid for the object.

118
JavaScript Component Icons

Errors
Any errors created while setting the icon ID for objects are sent to a file called
iconsetlog.txt located in the html folder.
Assigning a URL for images
When you set the $iconid of a JavaScript client object you can also assign a URL. In server
methods, if the value being assigned is a character value that contains a “/” character then
Omnis treats it as a URL generated by the iconurl function (meaning that it can contain
alternative icon files for the different client resolutions, and also that the server will pick the
correct icon for the client resolution).
In client methods, if the value being assigned is not an Icon ID (a literal integer or integer +
icon size constant) then Omnis treats the value as a URL generated by the iconurl function
on the server, and the client picks the correct icon for its resolution.
You could generate the required URLs with iconurl() (see below) in the $construct()
method of your remote form, and store them in an instance variable list which could then be
used in client executed code to assign the correct image to each object.

Image handling for tree lists


For the JavaScript Tree control, the iconid column is now an iconurl column, and the
$iconurlprefix property is now redundant although existing libraries that use $iconurlprefix
will continue to work. Instead, the iconurl column should be defined to be of type character,
and it should be populated using a new server-only function, iconurl(iconid), which returns
a URL string containing the name of the image file or a semi-colon separated list of file
names if an icon exists in more than one resolution. This enables the client to pick the
correct icon for its resolution.

Deploying HD Icons
You need to copy your icon sets and images files to the Omnis App Server when you want
to deploy your web or mobile app. If the icons are not copied to the Server tree they will
appear to be missing from your app.

Standalone Client Apps


Note that for standalone apps the icons needed for your mobile app will be bundled in the
SCAF. If any icons change on the Omnis App Server they will be updated on the client
when the standalone application files are updated.

Exporting Icons from an Icon Datafile


You may want to use some existing icons located in an Icon Datafile as separate files and
either add to or replace some of them with higher resolution versions. To enable you to
export existing icons there is a new tool in the Tools>>Add Ons menu, called the ‘JS Icon
Export’ tool, which is available in the ‘Web Client Tools’ dialog (scroll to the bottom of the

119
Chapter 3—JavaScript Components

list of Web Client tools). The ‘JS Icon Export’ tool will export all the icons in a selected
Icon Datafile and place them in a folder in the ‘html/icons’ folder, applying the correct
image file names. The $iconid property of a control will now reference the external image
file and not the icon datafile image.

Activity Control
The Activity Control provides an animated image to show some activity on the client, for
example, during a long list calculation or search operation on the Omnis Server. It has the
following custom properties:

Property Description
$activitystyle The style of the indicator, one of the following constants:
kJSActivityBar: a moving bar
kJSActivityBlock: a moving block
kJSActivitySmallSpinner: a small rotating spinner
kJSActivityCustomLink: the image in $customlink is used
$customlink The path of an animated GIF which can be displayed when
$activitystyle is set to kJSActivityCustomLink

The following code assigns a custom link to the activity control:


Calculate iCustomLink as
'http://www.mywebsite.com/images/animated1.gif'
Do $cinst.$objs.Activity.$customlink.$assign(iCustomLink)

Background Control
The Background Control allows you to draw various shapes in your remote forms. It can be
assigned one of a number of shapes including: Ellipse/Circle, Rectangle/Square, Rounded
rectangle/Square, Triangle, Horizontal Line, Vertical Line, and Image. If the object is an
Image the image source is specified in $imagepath as a URL relative to the Omnis tree
during development or your web server for deployment. You assign the shape to the object
by setting the $::shape property to one of the kJSBack... constants.
You can assign a solid color or gradient fill to a background component by setting its
$backpattern, $forecolor and $backcolor. You can also assign the stroke (border) thickness
and color by setting $strokewidth and $bordercolor.

120
Background Control

Animations and Changing Attributes


The Background Control has the $animation and $attr properties which allow various
animations or effects to be assigned to the object, such as fading the object in or out, or for
$attr various attributes of the object to be changed. The $animation and $attr properties
must be assigned at runtime and accept a string containing various parameters depending on
the function or attribute.
Apart from the scale attribute, the browser must support the Raphael JavaScript library to
allow animations and attribute changes (more details about the parameters you can use are
available from http://raphaeljs.com).
The $animation property follows the general format:
function( newvalue, time(milliseconds), ease(optional),
complete_context(optional) )
The functions available in $animation are:
 scale
increases and decreases the size of the object
scale( newvalue, time(milliseconds), ease(optional),
complete_context(optional) )

 alpha
changes the transparency of the object
alpha( newvalue, time(milliseconds), ease(optional) ,
complete_context(optional) )

 rotate
rotates the object
rotate( newvalue, time(milliseconds), ease(optional) ,
complete_context(optional) )
For example:
Calculate $cinst.$objs.backgroundobject.$animation as
"alpha(0,500,<>,fade_complete)"
fades the object to alpha value 0 over 500 milliseconds using a ‘slow, faster, slow’ easing
method (see below) and when complete calls evAnimComplete with a parameter
"complete_context".
You can use the complete event to chain the next animation, therefore to pulse an object
you could use:
Calculate $cinst.$objs.backgroundobject.$animation as
"alpha(0,500,<>,fade_off)"

121
Chapter 3—JavaScript Components

You could use the event handling method:


On evAnimComplete
If ( pAnimContext="fade_off" )
Calculate $cwind.$objs.backgroundobject.$animation as
"alpha(0,500,<>,fade_on)"
Else if ( pAnimContext="fade_on" )
Calculate $cwind.$objs.backgroundobject.$animation as
"alpha(0,500,<>,fade_off)"
End if

Ease transition effects


The following ease transition effects or “eases” are supported for animations:
= linear and default if not specified
> fast then slowing
< slow then faster
<> slow, faster, slow
bounce object bounces
elastic object stretches
backIn object backs in
backOut object backs out

Changing Background Attributes


The $attr property allows you to change various attributes of the object, such as their
transparency. For example, you can assign an alpha gradient to an object using the
following method:
; note must be assigned at runtime
Do $cinst.$objs.backgroundobject.$attr.$assign('attr(gradient, 0-
#FFFFFF:10-#FFFFFF)')
Do $cinst.$objs.backgroundobject.$attr.$assign('attr(opacity,0.0)')

Bar and Pie Chart Control


Omnis Studio provides two chart controls: a Bar Chart and a Pie Chart. The data to be
represented in both these controls is contained in a list variable which is assigned to the
$dataname property of the control. There is a sample app for both Bar and Pie charts in the
Apps Gallery on the Omnis website (www.tigerlogic.com/omnis).
There are various properties (on the Appearance tab in the Property Manager) that allow
you to control the appearance of a Bar and Pie chart: for Bar charts you can set the chart
direction ($chartdirection), the style of the bar ends ($barends), and you can display data
values when the end user’s mouse hovers over the bar ($showvalue); for Pie charts you can

122
Bar and Pie Chart Control

change the position of the legend (by setting $legendpos the legend can be above, below,
left or right of the pie) and allow the pie segments to move or “fly out” when the end user’s
mouse hovers over the segment (enable $flyout).

List data structure


To draw a simple bar or pie chart, the list variable assigned to the $dataname property of the
chart component needs to contain at least two columns. The first column contains the value
for the data point, and the second column contains the label or name for the data point. For
example, to construct a simple bar chart showing a list of figures for sales agents, you could
use the following method:
; create vars bar_data (List), amount (Number), name (Char)
Do bar_data.$define(amount,name)
Do bar_data.$add(120,'Steve')
Do bar_data.$add(230,'Dave')
Do bar_data.$add(245,'Anita')
Do bar_data.$add(125,'Claire')
Do bar_data.$add(280,'Ben')
With the $showvalue property enabled, the method produces the following chart.

For Pie charts, each value is shown as a percentage of the total of all the values in your list,
that is, the size of each segment (angle) is calculated as the proportion of the individual
value when compared to the total of all values in the list.

Events
Bar charts report the evBarClicked event with the bar clicked in the pBar parameter.
Similarly, Pie charts report the evSegmentClicked event with the segment clicked reported
in pPieSegment.

123
Chapter 3—JavaScript Components

; event method for bar chart, message is a field on the form


On evBarClicked
Calculate message as con("Bar clicked: ",pBar)
; event method for pie chart
On evSegmentClicked
Calculate message as con("Segment clicked: ",pPieSegment)

Button Control
The Button Control is a basic pushbutton that the end user can click to confirm or initiate a
process, such as an OK or Cancel button. The button can display an icon, specified in the
$iconid property (a URL pointing to an image file in the ‘html/icons’ folder), and/or a single
line of text specified in $text. The Button has the following custom properties:

Property Description
$buttonbackiconid The icon id of background image for the button. To use the default
system button, set $buttonbackiconid to zero and $buttoncolor to
kColorDefault
$buttoncolor The color of the button. To use the default system button, set
$buttonbackiconid to zero and $buttoncolor to kColorDefault
$textbeforeicon If true, and the control has both text and an icon, and the text is
displayed to the left of the icon
$::vertical If true, the text and icon are arranged vertically

When a Button is clicked an evClick event is triggered which you can handle in the event
handling method behind the button.
On evClick
Do something…

Example
For example, all the sample apps in the Welcome window have an About window which is
loaded into a subform and displayed using an animation; see the Animations section for the
About button code. The Close button on the About windows simply closes the About form
by sending a message to the main remote form to run a method; it has the following code:
On evClick
Do $cwind.$closeAbout()
In this case, $cwind is a reference to the main parent form which contains a method called
$closeAbout which contains code to fade out the About form and reset various buttons on
the main form.
See also the Trans button control.

124
Checkbox Control

Checkbox Control
The Checkbox control can represent On / Off or Yes / No values and is typically used to
allow the end user to turn on or off an option. The variable you specify in the $dataname
property of a Checkbox should be a Number or Boolean variable. The $text property
specifies the text for the Checkbox.
When a Checkbox is clicked an evClick event is triggered with the current value reported in
the pNewVal parameter.
For example, you could use a series of check boxes and a radio button group to filter a list
of people based on their gender and age group. The group of controls on the remote form
could look like this:

The $dataname for each of the check boxes is iAgeRange1, iAgeRange2, and iAgeRange3
respectively. These are all Boolean variables defined in the remote form, and the $dataname
of the Radio button group is iFilter, which is defined as a Short integer. Each separate check
box and the Radio group has a simple event method, which is:
On evClick
Do method filter
which will call the ‘filter’ class method when any of these objects is clicked. The filter
method filters the contents of the list called iList based on the selection of the check boxes
and radio buttons, and has the following code:

125
Chapter 3—JavaScript Components

Do iList.$unfilter(0)
If not(iAgeRange1)
Do iList.$filter(not(iAge<=20))
End If
If not(iAgeRange2)
Do iList.$filter(not(iAge>=21&iAge<=40))
End If
If not(iAgeRange3)
Do iList.$filter(not(iAge>40))
End If
Switch iFilter
Case 1
Do iList.$filter(iGender='F')
Case 2
Do iList.$filter(iGender='M')
End Switch
Note the ‘Smart list’ capability has to be enabled on the iList variable to allow the built-in
filtering using the $filter method. You can enable this using the code:
Do iList.$smartlist.$assign(kTrue)

Combo Box
The ComboBox control is a combination of a data field and a dropdown list from which the
end user can make a selection or enter their own value into the field. The variable for the
data field part is specified in the $dataname property. You can specify a default list of
options in the $defaulttext property, which is a comma-separated list of options, or build the
list dynamically (with $::listname, see below). When $defaulttext is specified, $defaultline
specifies the list line which is selected when the form is opened (set to 1 by default). The
$::listheight specifies the height of the droplist. The Combo Box has the $negallowed
property which means it can display negative numbers.
Rather than using a default list specified in $defaulttext, you can assign the name of a list
variable to the $::listname property to assign the contents of the list to the droplist part of
the combo box; $listcolumn specifies which column of the list variable is used to populate
the droplist part of the combo box.
When the list in a ComboBox is clicked an evClick is generated with the selected list line
reported in the pLineNumber parameter.

Content Tips
The Combo box control has the $::contenttip property which is a text string which is
displayed in the edit field part of the combo box when it is empty to help the user

126
Combo Box

understand what content should be entered into the field. For example, for a Last name field
you could enter ‘Enter your last name’ into $::contenttip to prompt the end user for their last
name.

Example
The maintenance screen in the Webshop sample app allows the user to enter new products
or delete existing ones: specifically, the data in the Webshop app contains food and drink
items, but it could be any type of products. When the user enters a new product, they can
select the product type from a Combo control; this allows the user to select from a list of
given product types or enter a new one.

The $dataname of the combo control is set to iDataRow.product_group, and the $::listname
is iGroupList. The evAfter event is enabled in the $events property of the control. In the
$construct method of the form, the iDataRow row variable is defined from the T_Products
table class, as follows:
; $construct of jsMaintenance form
; sets up form sizes, etc, then…
Do iDataRow.$definefromsqlclass($tables.T_Products)
Do $cinst.$objs.$sendall($ref.$construct())
The last line of code triggers all the field specific $construct methods which in this case
includes the Combo box control; the code defines the iGroupList from the product_group
column in the T_Products table class, performs a select on the data, and fetches all the data
back into the iGroupList variable.
Do iGroupList.$definefromsqlclass(
$tables.T_Products,'product_group')
Do iGroupList.$selectdistinct()
Do iGroupList.$fetch(kFetchAll)
When the user selects an item in the list or enters a new item into the entry part of the
combo box, an evAfter event is triggered and the $event method behind the combo control
is called, as follows:

127
Chapter 3—JavaScript Components

On evAfter
Do method newItem
Do $cinst.$setcurfield('product_name') ;; puts the focus in the
product_name field
The newItem method is placed behind the Combo box control itself and contains the
following code:
Do iGroupList.$search(
$ref.product_group=iDataRow.product_group,kTrue,kFalse,
kFalse,kFalse) ;; test iGroupList for group/type entered
If iGroupList.$line=0 ;; if not found in the group list
Do iGroupList.$add().product_group.$assign(
iDataRow.product_group) ;; add a new group to the list
End If

Complex Grid
A Complex Grid can display multiple rows and columns of data taken from a list variable
specified in the $dataname property of the control. You can use a $construct method behind
the grid control itself to build the list data to populate the fields in the complex grid. To
create a complex grid you place other controls in the row and header sections of the grid
control, including standard entry fields, droplists, buttons, and checkboxes. The $dataname
of each component you place in the grid must correspond to a column in your list variable
supplying the data to the grid. In addition, a complex grid is a container field having its own
$objs group containing the objects inside the grid control. The edgefloat properties of the
fields inside a complex grid do not apply when the grid has a horizontal scroll bar.
You can place event methods behind the embedded controls (rather than the grid field) to
react to user input and clicks within individual fields/cells in the grid. For example, you can
have a button in each row of the grid which when clicked triggers a method that performs an
action based on the row clicked.

Example
The Webshop sample app, available in the Welcome window (open via the New Users
button), uses a complex grid in the main product remote form to display a list of products.
Individual fields for the picture, name, description, price/size of the product are added to the
first line of the complex grid; when the form is opened on the client and the data is loaded
into the grid, these fields and are repeated for each row in the data list (one row per
product).

128
Complex Grid

The $dataname of the complex grid is set to iProductList which is built from a table class
T_Products which is linked to a schema class sProducts. A $construct method is placed
behind the complex grid that builds the list needed for the complex grid data.
; $construct of complex grid control in jsShop form
Do iProductList.$definefromsqlclass($tables.T_Products)
Calculate whereClause as con('WHERE product_group =
',kSq,'Appetizers',kSq)
Do $cfield.$build(whereClause) ;; calls $build
; $build method also behind complex grid control in jsShop form
Do iProductList.$select(pWhereClause,' ORDER BY product_isfood
desc')
Do iProductList.$fetch(kFetchAll)
When the form is opened, the $construct method is run and the product list is built from
database, while the data itself is displayed in the various fields embedded in the complex
grid with each product shown on a separate line in the complex grid.

There are three order buttons placed in the row of the complex grid; they are repeated for
each product in the list and allow the end user to order different sizes of product, such as a

129
Chapter 3—JavaScript Components

small, medium, or large drink or pizza. Each of the buttons has a simple method behind it
that passes a number to the process_order class method; the first button sends value 1, the
second button value 2, and the third button value 3.
; ‘Order now’ button method
On evClick
Do method process_order (1)
See the Data Grid section for the process_order method which updates the iOrderList and
the Orders data grid accordingly.

Data Grid Control


Data grids can display character and numeric data in a grid like structure, much like a table
or spreadsheet format. The data contents for the data grid is supplied from the list variable
specified in the $dataname property. You specify the number of columns in the grid object
itself in $designcols. The number of columns in your grid would normally correspond to the
number of columns in your data list. For each column in the grid (under the Column Tab in
the Property Manager) you need to assign $columndatacol to map the grid column to a
column in your data list: you can use the column name or number in $columndatacol.
The $hasheader property specifies whether or not the grid has a main header, while
$headertext specifies the text for the header and $::boldheader lets you specify a bold
header. The $columnnames property lets you specify the heading text for each column in
the grid (a comma separated list of names) which do not have to be the same names as the
column names in your data list variable. The $::columnwidths property allows you to set up
the widths of the columns (a comma separated list of integer values).
The $currentcolumn property is the current grid column for which properties are being
displayed under the Column tab in the Property Manager. The $movecolumn property
allows you to move a column to the specified position in the grid during design mode.
The end user can enter data into the cells of the grid if $enterable is enabled, and the grid
can grow by adding more lines to accommodate more data if $extendable is enabled. The
height of the rows in a data grid adjusts to fit the data automatically, unless you specify a
height in pixels in $::rowheight.

Numeric Data Validation


Data entered in grid columns with the numeric data type will be validated as it is entered.
When the end user tries to enter invalid data into the grid column field, such as an
alphabetic character, the data is rejected, and the field is highlighted momentarily to
indicate an error (the default action is to show a red border).

130
Data Grid Control

When leaving the entry field, the value is normalized: so for integer data it is constrained to
the valid range or for other numbers it is rounded to the correct number of decimal places;
also, leading zeroes are removed, and so on.

Data Grid Pick List


You can add a dropdown list or “picklist” to one of the columns in your data grid to allow
the end user to select a value from a list of preset values. You must create another list
containing the list of preset values and specify its name in the $columnpicklist property for
the column in which you want to add the picklist. The datatype of the column in your main
data list variable corresponding to the picklist column must be an integer, and
$columnmode for the grid column itself must be set to kJSDataGridModeDropList. The
integer value stored in this column will correspond to the line number of the selected line in
the picklist.
For example, if you want to list a product in your main grid field that has only four possible
colors, you could create a sublist containing those color values and assign this sublist to a
column in your grid field corresponding to an integer column in your main data list: this
would allow the end user to choose a color from a preset list of colors.

Data Grid Cell Formatting


You can apply your own formatting to individual cells in a Data Grid. For user-defined Data
Grids (where $userdefined is set to true) and where a column has its columnmode set to
kJSDataGridModeCustomFormat, you can customize the HTML used to layout or format
an individual cell in the grid.
When the grid is rendered (this occurs on demand e.g. when scrolling to make new data
visible), it calls the object client method:
$formatcell(list line number, designed grid column number)
which you implement to return html for the formatted cell contents. This HTML can, within
reason, be anything you like: you can also just return a text string. To assist this, there are
two new calls you can make:
 styledtohtml(text)
the styledtohtml(text) function returns the HTML representing the text string containing
embedded styles inserted using style() function. This is a built-in function, under the
General tab of the Catalog, which must be run in a client-executed method in the
JavaScript Client only.
 $addcolorcss(cClassName,iRgbColor,iAlpha)
is a method of the data grid object (as such it can only be executed in client-executed
methods). Call this in $init to add your own background color class to use with the html
returned by kJSDataGridModeCustomFormat.This class takes browser specific issues
with transparency into account.

131
Chapter 3—JavaScript Components

For example, you can use the following method:


Do $cinst.$objs.datagrid.$addcolorcss("myclass",rgb(255,0,0),128)
in $init, and then do the following in $formatcell:
Calculate columnvalue as iList.[row].[col]
if (columnvalue == "bad")
Quit method con(
'<div class="myclass"
style="padding:0;margin:0;height:16px">
',columnvalue,'&nbsp;','</div>')
Quit method columnvalue
Using transparency in the CSS background allows the selection color to show through the
formatted cell.

Data Grid Header Formatting


You can create your own formatting for column headers by adding a client-side method
called $formatheader which takes two parameters:
 Parameter 1: the text for the column header
 Parameter 2: the design grid column number (1-n)
The return value is HTML to use for the header, for example, for a bold header:
<b>Param 1</b>
For red text:
<span style="color:red">Param 1</span>
For right justified text (using float so that sort indicators still appear):
<div style="float:right;">Param 1</div>
You can reassign the column name to force a call to recalculate the HTML for the column
header, even if the text has not changed.

Data Grid Column Data Type Formatting


When you set $columnmode to kJSDataGridModeFormatted, the mode acts like
kJSDataGridModeAuto, in that the data grid automatically handles the data based on its
type. However, the grid formats the data using the properties $columndateformat,
$columndateformatcustom, and $columnnumberformat, rather than the $js...format...
properties.
You can use an integer column data type to represent a checkbox. To do this set
$columnmode to kJSDataGridModeFormatted and set the $columnnumberformat to “bool”.
This will cause integer data to be treated as Boolean, where non-zero means true, and zero

132
Data Grid Control

means false. If the end user updates the grid using the check box, 1 will be stored in the list
for true, and zero for false.

Grid Scrolling
JavaScript Data Grids have $vscroll and $hscroll properties which allow you to scroll a grid
vertically or horizontally at runtime in the client browser; note these properties are write-
only meaning that you cannot return their values at runtime.
The vertical scroll value assigned using $vscroll is the position of the scroll bar according to
row number in the control. The horizontal scroll value assigned using $hscroll is the
designed grid column number for a data grid.

Example
The Webshop sample app, available in the Welcome window (open via the New Users
button on the main Omnis menubar), uses a data grid to display a list of products that have
been ordered in the main product form. The data grid control is called ‘orderGrid’ and is
seen here in design mode:

The $dataname of the data grid is set to iOrderList which is defined from a table class
T_qOrders which is linked to a query class qOrders. When the product form is opened, the
$construct method behind the data grid defines the list from the table class.
; $construct behind the data grid
Do iOrderList.$definefromsqlclass($tables.T_qOrders)
When the end user clicks the ‘Order Now’ button in the product window, the data for the
selected product and size/type is passed to the process_order method (as value 1, 2, or 3),
which inserts the data into the list (after a check to see if the user has already ordered the
same product) and the list is redrawn. The process_order method is as follows:

133
Chapter 3—JavaScript Components

; process_order class method in the jsShop form


; contains pButtonNumber parameter (Short Int) to receive the value
of the product button clicked
If iProductList.product_price_[pButtonNumber]>0 ;; price must be
greater zero
Do iOrderList.$search(
$ref.order_product_id=iProductList.product_id
&$ref.order_size=iProductList.product_size_[pButtonNumber],
kTrue,kFalse,kFalse,kFalse)
If iOrderList.$line ;; found one so increment existing order
Calculate iOrderList.order_amount as iOrderList.order_amount+1
Else ;; new one so add to iOrderList
Do iOrderList.$add(
#NULL,#D,iProductList.product_id,iProductList.product_name,
iProductList.product_size_[pButtonNumber],
1,0,iProductList.product_price_[pButtonNumber])
Do iOrderList.$line.$assign(iOrderList.$linecount())
End If
Calculate iOrderList.total_price as
iProductList.product_price_[pButtonNumber]
*iOrderList.order_amount
Do $cinst.$objs.checkOutBtn.$enabled.$assign(
iOrderList.$linecount()>0)
Do $cinst.$objs.orderGrid.$redraw()
Else
Do $cinst.$clientcommand('yesnomessage',row(con('Would you like
to order >',iProductList.product_size_1,'< instead?'),'Not
available','$orderYes'))
End If
The Apps Gallery on the Omnis website has a further example showing how you can use the
Data grid component.

134
Date Picker Control

Date Picker Control


The Date Picker control allows the end user to select a date and/or time by clicking on the
up or down arrows for each part of the date or time. You can assign a Date/Time instance
variable to the $dataname property to load the date/time selected by the user, or you can
assign a two column instance row variable to contain the date/time and time zone offset of
the client in the respective columns (see below of info on the time zone offset).
The $datestyle property specifies the style or date/time content of the date picker control,
which can be a combination of date & time, date only, time only, or a calendar view, as
specified by a constant:

kJSDatePickerStyleDate a date display only


kJSDatePickerStyleDateTime a date and time is displayed
kJSDatePickerStyleTime a time display only
kJSDatePickerStyleCalendar a calendar is displayed

The color of the Date Picker is specified with $datefacecolor while $datefacealpha sets the
transparency (value 0-255).
When the date is changed on the client an evDateChange event is generated, or when in
calendar view an evDateDClick is sent when a date cell is double-clicked.

Calendar Style Picker


The Date Picker control can be switched to display a calendar style date picker, by setting
$datestyle to kJSDatePickerStyleCalendar. There are a number of properties that apply to
the control when the date style is set to calendar: see the Reference section for a list of
properties for the Calendar style picker.

Picker style on mobile devices


When $datestyle is set to kJSDatePickerStyleCalendar desktop browsers will display the
calendar as expected. However on mobile devices, even when $datestyle is set to
kJSDatePickerStyleCalendar, a calendar will be replaced with a date picker (same as
kJSDatePickerStyleDate), since a picker style date selector is the preferred style on mobile
devices. This can be overridden by setting the property $datestyleusepickeronmobile to
kFalse.

Example
In the Holidays sample app uses the Date picker control set to kJSDatePickerStyleCalendar
to allow users to select the dates for the holiday applications. The jsUserForm in the
Holidays app has two buttons to allow the end user to select a “From” date or “To” date to

135
Chapter 3—JavaScript Components

specify the Begin and End dates for their holiday request. The “From” button has the
following code:
On evClick
Calculate iUsingCalendar as kTrue
Calculate iSelectFrom as kTrue ;; this is the From button
Do method openCalendar
The openCalendar class method moves the calendarPane into view on the main form and
has the following code:
Do method enableFields (kFalse) ;; enables the calendar pane &
disables the name pane
Do $cinst.$objs.calendarPane.$top.$assign(90)
Do $cinst.$objs.calendarPane.$left.$assign(150)
Do $cinst.$objs.calendarPane.$visible.$assign(kTrue)
If you examine the Holidays app to look at the Date
picker note that it is on a page pane field called
calendarPane located on the jsUserForm. The $left
property for the calendarPane is set to 990, to hide it
from view, therefore you’ll need to select it using the
Field List (right-click the remote form, select Field
List and check the calendarPane) and set its $left
property to 200 in the Property Manager in order to
see it.

The $dataname of the Date picker control itself is set to iCalendarDate, an instance variable
of type Date Time and subtype ‘D m y’; when the end user selects a date this variable is set
to the selected date automatically. The Date picker has a simple event method to detect
when the end user double-clicks on a date cell; it has the following code:
On evDateDClick
Do method closeCalendar
The closeCalendar class method passes the date from iCalendarDate into either the
iFromDate or iToDate variable defined in the form; it has the following code:
If iSelectFrom ;; if the From button
Calculate iFromDate as iCalendarDate
Else ;; it must be the To button
Calculate iToDate as iCalendarDate
End If
Do $cinst.$objs.calendarPane.$left.$assign(1250)
Do method enableFields (kTrue)

136
Device Control

The final two lines of the method move the calendarPane off to the right and enables the
fields on the Name pane.

Time Zone Offset


You can return the time zone offset of a date value when it is passed back from the client by
using a two column row variable in $dataname; the first column should be defined as a Date
Time variable and the second of type Number. If the server passes a new value to the client
then only the first column is significant and should specify the new date to be sent to the
client.
When evDateChange signals that there has been a change on the client then the updated date
is passed back to the server in the first column of the row variable as a UTC/GMT date
value and the time zone offset of that value in the client's current time zone is passed back
in the second column. The time zone offset is the number of minutes from UTC/GMT, e.g.
GMT+2 the time zone offset is 120. This can be used to calculate the date in the time zone
of the client.
If time zone offset information is not required, $dataname can be specified as a Date Time
instance variable only.

Device Control
The new Device Control allows access to mobile device features such as getting the location
of the end user’s device using GPS, retrieving the contacts information from the device, or
returning images from either the camera or photo library on the device. Depending on the
type of application you are creating, some or all of these features may be useful to enhance
the interactivity and functionality of your app for end users when they run your app on a
mobile device, such as a smartphone or tablet computer.
The Device control itself is invisible and to enable access to the device functionality you
need to add the Device Control to your remote form and assign an action to the $action
property of the control at runtime using methods.

Running the Device Control and Compatibility


Important Note the Device Control only works in an application that is running within
one of the wrapper applications on a mobile device; it will not work if the app is run in a
standard web browser on a mobile device, or on a desktop computer. Therefore you will
need to create your mobile app, compile it into a wrapper app, and test it in a simulator or
directly on a mobile device by running the native app.
The Device control supports a number of hardware functions, some of which may not be
available on particular devices. You should test your app thoroughly on the specific devices
you wish to support with each of the device functions that you want end users to access.

137
Chapter 3—JavaScript Components

For some of the hardware features, Omnis can detect if they are not present on the current
mobile device running the app. For example, if a device does not have a hardware camera
then the action kJSDeviceActionTakePhoto will report an evPhotoFailed message.

Properties
Note the Device control is invisible, therefore some of the visual properties normally
associated with JavaScript components may not be relevant, such as $alpha.

Property Description
The “action” for the Device control which specifies which
$action function on the client mobile device is accessed; this is
assigned as a kJSDevice… constant: see below
$barcodeimage If true, a barcode image will be returned.
Contains contact address details when the Make Call and Send
$communicationaddress
SMS device actions are used.
Contains the data to be sent when the Send SMS device action
$communicationdata
is used.
$dataname The name of an instance variable for the Device control
Contains an instance variable name used for holding the image
$deviceimage
returned from the device.
Name of the sound sample to be played when the Beep device
$soundname
action is called.

Contact properties
There are a number of properties that are only relevant when the device action is set to
kJSDeviceActionGetContacts which allows you to obtain information from the contacts
database on the device. By setting these properties you can control what information is
returned from the Contacts data on the device. For example, if $contactname is set to kTrue
the contact request will include name info, and so on.

Setting the Action Property


The following list summarizes the actions available and the constant needed for the $action
property:
 kJSDeviceActionBeep – Beep Device
forces the device to play the default beep
 kJSDeviceActionGetBarcode – Get a Barcode or QR code
returns the output from Barcode/QR-code scanning function on the device (if
available); the output is usually a string which can be a URL

138
Device Control

 kJSDeviceActionGetContacts – Get contact info


returns contact information from the device; note there are other properties to
determine the content or extent of the contact information returned
 kJSDeviceActionGetGps – Get the device location
returns the location data using the GPS function on the device
 kJSDeviceActionGetImage – Get an Image
returns an image from the device’s image gallery
 kJSDeviceActionMakeCall – Make a Phone Call
forces the device to make a phone call (if available)
 kJSDeviceActionSendEmail | kJSDeviceActionSendSms – Send an Email or SMS
forces the device to send an Email or SMS / text message (if available)
 kJSDeviceActionTakePhoto – Take a Photo
forces the device to take a photo (if a camera is available)
 kJSDeviceActionVibrate – Vibrate the Device
forces the device to vibrate (if available)
The basic method to assign an action to the Device control is as follows:
Do $cinst.$objs.oDevice.$action.$assign(kJSDeviceAction…)
; where oDevice is the name of the Device control

139
Chapter 3—JavaScript Components

Events
Event Description
Sent when no Barcode could be obtained from the device.
evBarcodeFailed Parameters
pEventCode The event code
Sent to the device control when a Barcode is ready for processing.
Parameters
evBarcodeReturned pDeviceBarcode The Barcode data
pEventCode The event code
Sent when no contacts could be obtained from the device.
evContactsFailed Parameters
pEventCode The event code
Sent to the device control when contacts info is ready for processing.
evContactsReturned Parameters
pEventCode The event code
Sent to the device control when Location Data is ready for processing.
Parameters
evGpsReturned pDeviceGps The GPS location
pEventCode The event code
Sent when the device failed to return an image.
evImageFailed Parameters
pEventCode The event code
Sent to the device control when an image is ready for processing.
Parameters
evImageReturned pDevicePhoto Image from Camera
pEventCode The event code
Sent when the device failed to take a photo.
evPhotoFailed Parameters
pEventCode The event code
Sent when an image is returned from camera ready for processing.
Parameters
evPhotoReturned pDevicePhoto Image from Camera
pEventCode The event code
Standard evExecuteContextMenu evOpenContextMenu

140
Device Control

Beep Device Action


To make the device play a given sound sample, you need to assign the constant
kJSDeviceActionBeep to the $action property. This is one way communication with the
device which will result in the device playing a sound sample. To specify which sound to
play, you need to set the $soundname property to the name of the sound sample to be played
which must be complied into the wrapper application. The wrapper contains a default sound
called “Notify”.
Example
On evClick
Calculate $cinst.$objs.oDevice.$soundname as “Notify”
Do $cinst.$objs.oDevice.$action.$assign(kJSDeviceActionBeep)

Get Barcode Device Action


You can return a Barcode or QR code by assigning the constant
kJSDeviceActionGetBarcode to the $action property. If the action is successful an
evBarcodeReturned event is sent to the Device Control and the barcode data is returned in
the pDeviceBarcode event parameter; the barcode data is usually a string containing
Alphanumeric characters, such as a product number or name, or in the case of a QR code it
could be a website URL.
Example
; event method for “Scan” button
On evClick
Do
$cinst.$objs.oDevice.$action.$assign(kJSDeviceActionGetBarcode)
The event method for the Device Control could be:
On evBarcodeReturned
Do
iProducts.$search(iProducts.iProdQrCode=pDeviceBarcode,kTrue,kFal
se,kFalse,kFalse)
If iProducts.$line=0
Do iProducts.$line.$assign(iProducts.$linecount) ;; other
End If

Do iProducts.$loadcols()
Calculate iAmount as 1

If iProdName='Other'
Calculate iProdName as pDeviceBarcode ;; show the value of
the barcode
End If

141
Chapter 3—JavaScript Components

Vibrate Device Action


To make the device vibrate you need to assign the constant kJSDeviceActionVibrate to the
$action property. This is one way communication with the device which will result in the
device vibrating for a short period of time.
Example
On evClick
Do $cinst.$objs.oDevice.$action.$assign(kJSDeviceActionVibrate)

Get GPS Device Action


To receive location (GPS) data from the device you need to assign the constant
kJSDeviceActionGetGps to the $action property. The evGpsReturned event is sent when the
location data has successfully been returned. The event parameter pDeviceGps will contain
the returned data which is formatted as a string containing longitude and latitude data
separated by a colon “:”. If the device fails to obtain location data or the device does not
support location tracking, the returned data will be a longitude and latitude of zero, i.e.
“0.0:0.0”.
Example
On evClick
Do $cinst.$objs.oDevice.$action.$assign(kJSDeviceActionGetGps)
On evGpsReturned
Calculate $cinst.$objs.oMap.$latlong as pDeviceGps

Take Photo / Get Image Device Action


To take a photo with the device (if a camera is present) or to return an image from the
device’s gallery the kJSDeviceActionTakePhoto or kJSDeviceActionGetImage constants
need to be assigned to the $action property. The $dataname property of the Device
component needs to be assigned to an Instance Variable of type Binary to hold the incoming
image from the device. If the device is successful in returning an image, the $event
evPhotoReturned or evImageReturned will be called to indicate that the operation has been
successful and the instance variable in $dataname will contain base64 encoded image data.
In the event of the device failing to return an image or the user cancels the request, the event
evPhotoFailed or evImageFailed will be sent.
Example
On evClick
Do $cinst.$objs.oDevice.$action.$assign(kJSDeviceActionTakePhoto)
In this case the instance variable iImage is a Binary variable. The $deviceimage property is
set to iImage. There is another Binary variable called ipic which is associated to a picture
component. By copying the returned image in iImage into the picture component variable
you can display the image returned from the device.

142
Device Control

On evPhotoReturned
Calculate iPic as iImage

Get Contacts Device Action


To obtain information from the contacts database on the device the
kJSDeviceActionGetContacts constant must be assigned to the $action property. To
accommodate the contact database the $dataname property needs to be assigned to an
Instance Variable of type List. The properties starting with $contact... determine which
contact fields will be obtained from the device: setting these properties to true or false will
determine if that specific field is returned from the device.
The evContactsReturned event is triggered when the contact database has been returned,
and in the case of the device failing to obtain the contact database the evContactsFailed
event is triggered.
Example
On evClick
Do $cinst.$objs.oDevice.$action.$assign(
kJSDeviceActionGetContacts)
; retrieve info from the Contact list
On evContactsReturned
Set reference lNameRow to iDeviceList.name.1
Calculate iNameRow.FirstName as lNameRow.givenName
Calculate iNameRow.MiddleName as lNameRow.middleName
Calculate iNameRow.Surname as lNameRow.familyName
Calculate iNameRow.Prefix as lNameRow.honorificPrefix
Calculate iNameRow.Suffix as lNameRow.honorificSuffix
Calculate iNameRow.Nickname as iDeviceList.nickName

Contacts data structure


 displayName: The name of this Contact, suitable for display to end-users (String).
 name: An object containing all components of a person’s name.
formatted: The complete name of the contact (String).
familyName: The contacts family name (String).
givenName: The contacts given name (String).
middleName: The contacts middle name (String).
honorificPrefix: The contacts prefix (example Mr. or Dr.) (String).
honorificSuffix: The contacts suffix (example Esq.) (String).
 nickname: A casual name to address the contact by (String).
phoneNumbers: a list of all the contact's phone numbers.
type: A string that tells you what type of field this is (example: 'home') (String).

143
Chapter 3—JavaScript Components

value: The value of the field (such as a phone number or email address) (String).
pref: Set to true if this ContactField contains the user's preferred value (Boolean).
 emails: a list of all the contact's email addresses.
type: A string that tells you what type of field this is (example: 'home') (String).
value: The value of the field (such as a phone number or email address) (String).
pref: Set to true if this ContactField contains the user's preferred value (Boolean).
 addresses: a list of all the contact's addresses.
pref: Set to true if this ContactAddress contains the user's preferred
value (Boolean).
type: A string that tells you what type of field this is (example: 'home') (String).
formatted: The full address formatted for display (String).
streetAddress: The full street address (String).
locality: The city or locality (String).
region: The state or region (String).
postalCode: The zip code or postal code (String).
country: The country name (String).
 ims: a list of all the contact's IM addresses.
type: A string that tells you what type of field this is (example: 'home') (String).
value: The value of the field (such as a phone number or email address) (String).
pref: Set to true if this ContactField contains the user's preferred value (Boolean).
 organizations: a list of all the contact's organizations.
pref: Set to true if this Contact organization contains the user's preferred
value (Boolean).
type: A string that tells you what type of field this is (example: 'home') (String).
name: The name of the organization (String).
department: The department the contract works for (String).
title: The contacts title at the organization (String).
 birthday: The birthday of the contact (Character).
 note: A note about the contact (String).
 photos: a list of the contact's photos.
type: A string that tells you what type of field this is (example: 'home') (String).
value: The value of the field (such as a phone number or email address) (String).
pref: Set to true if this ContactField contains the user's preferred value (Boolean).
 categories: a list of all the contacts user defined categories.
type: A string that tells you what type of field this is (example: 'home') (String).
value: The value of the field (such as a phone number or email address) (String).
pref: Set to true if this ContactField contains the user's preferred value (Boolean).
 urls: a list of web pages associated to the contact.
type: A string that tells you what type of field this is (example: 'home') (String).

144
Droplist Control

value: The value of the field (such as a phone number or email address) (String).
pref: Set to true if this ContactField contains the user's preferred value (Boolean).

Make a Call Device Action


To make a phone call from the device the kJSDeviceActionMakeCall constant is used.
Before assigning this action the phone number for the call should be specified in the
$communicationaddress property.
Example
Do $cinst.$objs.oDevice.$communicationaddress.$assign(“0123456789”)
Do $cinst.$objs.oDevice.$action.$assign(kJSDeviceActionMakeCall)

Send an SMS Device Action


To send an SMS (Short Message Service) from the device the kJSDeviceActionSendSMS
constant is used. Before assigning this action the phone number for the SMS should be
specified in the $communicationaddress property, and contents of the message should be
specified in $communicationdata.
Example
Do $cinst.$objs.oDevice.$communicationaddress.$assign(“0123456789”)
Do $cinst.$objs.oDevice.$communicationdata.$assign(“A message”)
Do $cinst.$objs.oDevice.$action.$assign(kJSDeviceActionSendSMS)

Droplist Control
The Droplist control displays a dropdown list from which the end user can make a selection;
the contents of the list can be supplied from a default list or a list variable which can be
built dynamically.
You can specify a default list of options in the $defaulttext property, which is a comma-
separated list of options; $defaultline is the default line (set to 1) which is selected when the
form is opened (only when $defaulttext is used). Alternatively, you can assign the name of a
list instance variable to $dataname to populate the list; $listcolumn specifies which column
of the list variable is used to display the list. The $::listheight specifies the height of the
droplist.
When a line in the droplist is selected an evClick is generated with the selected list line
reported in pLineNumber.

Example
The jsUserForm in the Holidays sample app uses a droplist to allow users to select an
employee to view their holiday leave requests. The $dataname of the empList Droplist

145
Chapter 3—JavaScript Components

control is set to iEmployeeList which is built via the $construct method when the form is
opened.
; buildEmpList class method in the jsUserForm
Do iEmployeeList.$definefromsqlclass('sEmployee') ;; the schema
Do iEmployeeList.$sessionobject.$assign(iSQLObjRef)
Do iEmployeeList.$select()
Do iEmployeeList.$fetch(kFetchAll)

Do iEmployeeList.$cols.$add(iEmpFullName)
Calculate lTotal as iEmployeeList.$linecount
For lNum from 1 to iEmployeeList.$linecount step 1
Calculate iEmpFullName as con(
iEmployeeList.[lNum].FirstName,kSp,
iEmployeeList.[lNum].LastName)
Do iEmployeeList.[lNum].$assigncols(,,,,,iEmpFullName)
End For
Do iEmployeeList.$line.$assign(1)
Calculate iName as iEmployeeList.iEmpFullName
The droplist control contains a $event method which is triggered when the user selects a line
in the list; the code in the event method redraws the holiday list for the selected employee:
On evClick
Do method buildHolidayList
Calculate iName as iEmployeeList.[pLineNumber].iEmpFullName
Do $cinst.$objs.pagePane.$objs.holidayList.$redraw()
Do $cinst.$objs.pagePane.$objs.empName.$redraw()
The buildHolidayList class method builds the list of holiday requests for the selected
employee and redraws the form.

Edit Control
The JavaScript Edit control is a standard single line edit field which you can use to display
data or allow the end user to enter data into. The Edit control can handle all types of
character data stored in the instance variable specified in $dataname. When kTrue (the
default), $issingleline makes the edit control only allow data entry on a single line,
otherwise when kFalse the field can be extended downward to allow data entry on multiple
lines. When kTrue, the $ispassword property ensures a place-holder character is displayed
when the end user enters something in the field (only applies when $issingleline is kTrue).
The $borderradius property lets you add rounded corners to the edit control. It can be set to
up to four pixel values separated by -, in the order topleft, topright, bottomright, bottomleft.

146
Edit Control

If bottomleft is omitted the topright value is used. If bottomright is omitted the topleft value
is used. If topright is omitted the topleft value is used.
The $effect property lets you set the type of border for the edit control and is one of the
kJSborder… constants. The kJSborderDefault setting means the control has the default
border type as specified by the current client operating system and browser type. For some
clients the border may change when the state of the control changes.
The $linkedobject property allows you to link a list control to the edit control to create a
special type of list called a “Linked List” which updates itself automatically as the user
types into the edit control: see the List Control section for more information.

Content Tips
The Edit control has the $::contenttip property which is a text string which is displayed in
the edit field when it is empty and before the end user has entered any text. Using content
tips may help the user understand what content should be entered into fields in the forms in
your application. For example, for a Last name field you could enter ‘Enter your last name’
into $::contenttip to prompt the end user for their last name. As soon as the end user starts to
type something into the field the content tip will disappear.

Numeric Data Entry Validation


Entry fields (and data grids) validate numeric data as it is entered, for JavaScript remote
form variables with a numeric data type. When the end user tries to enter invalid data into
the field, such as an alphabetic character, the data is rejected, i.e. it cannot be entered into
the field, and the field is highlighted momentarily to indicate an error (the default action is
to show a red border).
When leaving the entry field, the value is normalized: so for integer data it is constrained to
the valid range or for other numbers it is rounded to the correct number of decimal places;
also, leading zeroes are removed, and so on.

Negative Numbers and Uppercase


The $negallowed property for Edit controls allows for the display of negative number
values. If this is kFalse and the end user tries to enter a negative sign, the sign will be
rejected. When set to kTrue, the $uppercase property forces uppercase for character data.

Events
The Edit Control reports the evBefore and evAfter events, so you can detect when the focus
is about to enter or leave a field in the $event method and process the event accordingly. In
addition, the evKeyPress event is reported allowing you, amongst other things, to create a
“Linked List”: see the List Control section for more information about linked lists. Note that

147
Chapter 3—JavaScript Components

you must enable any of the events for the Edit control in its $events property before any of
the events are reported.

File Control
The File Control allows end users to upload or download files. The control itself is invisible
and to enable the upload or download functions, you need to assign an action, at runtime, to
the $action property. The Upload and Download actions are represented by the constants
kJSFileActionUpload and kJSFileActionDownload.
When in upload mode the File control opens a standard Upload dialog to allow the end user
to select a local file to upload. There are various properties to allow you to change the text
and error messages on the Upload dialog.
For downloads, the File control can provide a standard hyperlink pointing to the file to be
downloaded, or you can assign a row variable to the $dataname of the control containing the
binary data of the file to download. The download function is supported for mobile devices,
and if the browser can interpret the contents of the file it is shown in a new browser window
or tab.

Using Timer and File controls


Note that if a Timer control is present on the page, timer events will not occur while a file
upload dialog is open, or while file download is in progress.
Mobile limitations or issues
Support for the Upload or Download function on mobile devices depends very much on the
device itself and the mobile operating system. Therefore if you intend to include an upload
or download function in your app, you should test your app thoroughly on all devices you
wish to support. With this in mind, we are aware of the following limitations or issues
regarding different mobile operating systems.
Upload does not work on iOS because the input element to select a file does not become
enabled since iOS does not support it. Download works via the hyperlink because mobile
Safari has been implemented to support hyperlinks. However, the other download
mechanism does not work: on iOS for example, the download actually transfers the data to
the client, but then the browser does not carry out any action with the data, so the
downloaded file is lost.

Uploading Files
To enable the upload function you must set the $dataname property of the File component
to a two-column row variable: Column1 should be of type List, and column2 should be of
type Character ($dataname should be set before the upload action if triggered). The value
assigned to column2 should be the name of a task variable of Binary type which will receive

148
File Control

the binary data when the upload is complete. Column1 will receive MIME header list
information when the upload is complete.
To trigger the upload dialog, you need to assign kJSFileActionUpload to the $action
property. This action opens a file upload dialog which has two formats: one for up to date
browsers, and the other for browsers which do not support XMLHttpRequest2, i.e. Internet
Explorer and Opera. When a file has uploaded an evFileUploaded event is generated and
the List and Binary task variable assigned to $dataname are populated. When the dialog
closes the control generates evFileUploadDialogClosed.
The $maxfileuploadsize specifies the maximum size in bytes of a file to be uploaded to the
server. Zero means no limit. Some clients (IE and Opera) cannot enforce this limit. See
example below for details on how to upload a file.
While the Upload dialog is open, you can close it by assigning kJSFileActionCloseUpload
to the $action property (note this does not generate evFileUploadDialogClosed).

Downloading Files
In its simplest form, the File control can provide a hyperlink to allow the user to download a
file located on the internet. In this case, you would set the $visible property of the control
set to kTrue, set $hyperlinkurl to the URL of the file, and $hyperlinktext to the text for the
hyperlink. The URL does not have to be a file download URL, it can be any file on the
internet and will open in a new browser window or tab. The File control will display the
download as a standard hyperlink on the remote form.
You can also use the File control to download a file from a binary file or one stored in your
database. To enable this functionality, you need to assign kJSFileActionDownload to the
$action property. In this case, $dataname of the control must be a row variable, with
Column1 as the file name, Column2 the media type (e.g. text/plain;charset=utf8), and
Column3 the name of a remote task variable which should be a binary containing the file
data or character containing a file path.

Example
A File control is used in the jsContacts form in the Contacts sample app to allow end users
to upload a photo of their contacts. The File control is placed somewhere on the form, its
$dataname is set to iFileRow, an instance row variable, and the evFileUploaded and
evFileUploadDialogClosed events are enabled in the $events property of the control. The
iFileRow variable is setup in the $construct method of the form, as follows:
Do iFileRow.$define(MimeList,"Binary Variable")
Calculate iFileRow.C2 as "tData"
MimeList is a local list variable, and tData is a task variable of type Binary – it’s important
to note that the second column of iFileRow is of type Character, and is set to the Name of
the binary task variable. Elsewhere on the form is a picture control to display the photo, its

149
Chapter 3—JavaScript Components

$dataname is iPicture, and a button to allow the end user to select an image file and initiate
the upload process. The code for the button is:
On evClick
Do $cinst.$objs.fileControl.$action.$assign(kJSFileActionUpload)
This assigns the kJSFileActionUpload action to the fileControl object which opens the
Browse/Upload dialog. The File control has an $event method which detects when a file has
been uploaded and the upload dialog has been closed:
On evFileUploaded
Calculate iPicture as tData
; transfer the pic data to iPicture
On evFileUploadDialogClosed
Do method setPicBtnTitle (kHavePic) ;; changes the button text
When an image is selected by the end user and the file is uploaded the image data is loaded
into the tData task variable, as defined in the second column of the iFileRow row variable,
which is then transferred to the iPicture variable assigned to the picture field on the form.
The Save button saves the contact record including the image file uploaded by the user.

HTML Object
The HTML Object lets you display an HTML page or fragment on the remote form. The
$html property contains the HTML content for the control. This must start with an element
declaration such as <div...> or <style>. The $ctrlname is the name of the control.
The following method constructs some HTML and assigns it to the HTML control called
HTML.
; lHTML is a local var of Character type
Begin statement
; ===== Styles =====
Sta: <style>
Sta: p {color: #00F; margin: 0 2em; padding: 1em; background-color:
#fff; border: #DDD solid 2px;}
Sta: h1, h2 { color: #666; margin-left: 0.5em;}
Sta: img {margin: 5px 0 5px 50px;}
Sta: </style>

; ===== Content =====


Sta: <div>
Sta: <h1>HTML Control</h1>
Sta: <p>
Sta: You can display HTML in the HTML control.<br />
Sta: This is the Second line of content.<br /><br />

150
HTML Object

Sta: <i>And you can do italic etc!</i>


Sta: </p>
Sta: <h2>Pictures</h2>
Sta: <p>You can embed pictures.</p>
Sta: <img src="/images/cat.jpg" width="200" height="176" alt="cat"
/>
Sta: </div>
End statement
Get statement lHTML
; the html form object is called HTML
Calculate $cinst.$objs.HTML.$html as lHTML
You can embed any of the standard HTML tags into the $html property, including links,
styles, and tables. The following text could be added to an HTML control which is placed
next to a check box control to allow end users to popup a window containing competition
rules that are stored in a static html page:
<p>I have read and agree to the <a href="rules.html"
target="_blank">competition rules</a></p>

Events
The HTML Control reports the evBefore and evAfter events, as well as evClick and
evDoubleClick.

151
Chapter 3—JavaScript Components

Style and Attribute Placeholders


You can inherit the effects and font attributes that you set for the HTML object in the
Property Manager in design mode by inserting various placeholders in the $html property.
The placeholders take the format %<letter>, for example, insert %f to inherit the font
specified in $font, or %t to inherit the text color set in $textcolor. Most of the placeholders
should be inserted into an html element using the style tag, while others are attributes and
can be inserted directly into an HTML element.

Placeholder Type Description Property


%b attribute back color and alpha $backcolor and $alpha
%d style hide system focus $disablesystemfocus
%e attribute effect $effect
%f style font $font
%h style horz scroll $horzscroll must be kTrue
%j style font align $align
%p style position coordinates of omnisobject
%s style font style $fontstyle
%t style text color $textcolor
%v style vert scroll $vertscroll must be kTrue
%z style font size $fontsize

For example, you can set $html to <div %e></div> and the text in the control will take on
the effect from $effect (or $linestyle or $bordercolor, as these are effect properties).
The %d placeholder inserts “outline:none;” when disable system focus for the control is
true, thereby disabling the focus around the control. This placeholder has to be placed in the
<div> tag for the control, e.g. <div style="%d">.
To use the font specified in the HTML object in a paragraph in your HTML insert: <div><p
style="%f">SOME TEXT</p></div>. For example, the following HTML produces some
text rendered in plain or default HTML paragraph style and second paragraph of text that
uses the font setting specified in $font in the HTML object, which in this case is set to
“Verdana,Arial,Helvetica,Sans-serif”:
<div><p>PLAIN TEXT</p><p style="%f”>STYLED TEXT</p></div>
Produces the following:

152
Hyperlink Control

HTML object in Paged Panes and Subforms


If the HTML object appears in a Paged Pane or Subform (that is, inside any container field),
you will need to add the “white-space:normal” parameter to the <div> tag containing your
Html to allow the text to wrap correctly inside the object. For example, the following <div>
tag will contain text etc within a 300px width:
<div style="width:300px; white-space:normal">
; your HTML
</div>

Hyperlink Control
The Hyperlink Control allows you to present a list of options to the end user, where each
option in the list is displayed as a web-style hyperlink; each link option corresponds to a
line in the underlying list variable used to populate the list. If the whole list does not fit
inside the control, the list will “pop up” when the end user passes the mouse over the
control. The $extraspace property specifies extra spacing between links.
The options in the Hyperlink list are based on the contents of a list variable (which requires
a different format to the existing web client Hyplinks component). The first column in the
list specified in $dataname is the text displayed for each option listed in the control, unless
$listcolumn is specified which is the column of the list variable used to populate the control.
When the end user clicks on the list an evClick is triggered with the line number reported in
pLineNumber. You can use the value of pLineNumber in your event method to trigger an
action. You can create an empty line by putting ”-“ (hyphen) in the first column.
If $isvertical is kTrue the list pops up vertically, and if $shouldunderline is kTrue the links
are underlined. The $selectedtextcolor property specifies the color of the text when the
mouse is over it.

Example
There is an example library showing how you can build a dynamic hierarchical list using the
Hyperlink control in the new JavaScript Component gallery on the Omnis website at:
www.tigerlogic.com/omnis

Label Object
The Label object lets you add standard labels to the fields on your remote form. The text for
the label is entered into the $text property. The font and alignment of the label is setup
under the Text tab in the Property Manager.
The Label object also has the $dataname property which means its text can be populated
dynamically. If $dataname is set, its value overrides the value in the $text property, and

153
Chapter 3—JavaScript Components

actually sets $text, so if you read $text when using a label with a data name, the value of
$text will become the content of the variable in $dataname.

List Control
The standard List control allows you to display a single column list on your form allowing
end users to select a particular line. For lists with many columns you may prefer to use a
data grid, or for a more compact single-column list you can use a droplist. If you want to
include an icon next to the text in each list line you can use a Tree list by including your
data and icon references at the top-level of the list data without using any child data.
The contents of a standard List is taken from the instance variable (of List type) specified in
the $dataname of the control. In this case, the first column of the list contents is used to
populate the list control. You can build the list via the $construct method of the remote
form; the list can be built from your database or from a number of static values, as follows:
Do iListvar.$define(iCol) ;; defines the list
Do iListvar.$add("Value1") ;; add the values
Do iListvar.$add("Value2")
Do iListvar.$add("Value3")
Do iListvar.$line.$assign(1) ;; selects the first line
You can control the color for selected lines by setting $selectedlinecolor; use kColorDefault
for the default selected line color for the client OS. The $evenrowcolor property sets the
background color of even numbered rows displayed in the list; kColorDefault means use the
same color as the odd numbered rows ($backcolor).
If $ischecklist is kTrue each list line has a checkbox which allows the end user to select or
de-select the line.
When the user selects a line the evClick event is reported with the pLineNumber parameter
reporting the selected line number. You can use the value of pLineNumber in your event
method behind the list to trigger an action.
See the ‘Programming Lists’ chapter in the Omnis Programming manual for more
information about using list variables in your code.

Lists and Client Methods


Searching Lists
You need to prefix the column name with $ref for a search to work in a client method. For
example:
Do iList.$search($ref.iCol="ABC")

154
List Control

Smart Lists and the JavaScript Client


The JavaScript Client does not support smart lists in client executed methods, insofar as if
you change the list in some way on the client, it will no longer be a smart list when the
updated data is sent from the client back to the server. Smart lists work as expected in server
executed methods.
Adding columns
The $addcols() method allows you to add one or more columns to a list or row variable. It
has the following parameters:
list.$addcols(cName,type,subtype,maxlen,...)
The parameter count must always be a multiple of four. Each new column must be specified
with the following four parameters:
 cName
the name of the new column
 data type
the Omnis data type represented by one of the type constants, such as kCharacter; all
data types are allowed except the Object data type (kObject), since lists of objects are
not recommended (you should use object references)
 subtype
the subtype of the new column; only applies to some major types
 maxlen
for some major types such as Character you can specify the maximum length

List Scrolling
Data Grids have $vscroll and $hscroll properties which allow you to scroll a list vertically
or horizontally at runtime in the client browser; note these properties are write-only
meaning that you cannot return their values at runtime. The vertical or horizontal scroll
value assigned using $vscroll or $hscroll is the pixel offset for a list.

Linked Lists
You can link a List control to an Edit control to create a “Linked List” that can be updated
as the end user types into your remote form. The combination of an Edit control with key
presses enabled and a List control allow you to create a dynamic list that has the ability to
update in response to what the end user types into the edit box. A Linked List is in effect
like a Combo box, but with the extra ability to update itself as the user types. To enable this
feature, edit controls can detect certain key presses and can be linked to a list control, while
for lists themselves there is a property to display selected lines only.

155
Chapter 3—JavaScript Components

Detecting Key Presses


Edit controls have an event called evKeyPress. It has a single event parameter, pKeyList,
which is a three column list containing the keys entered since the last evKeyPress event (or
since typing started) with a row for each key in the order the keys were pressed. The new
Key press detection was added to support Linked Lists, but it could be used by itself for
other purposes.
Each key in the list is either a data character or one of a limited set of system keys (note that
not all keyboard keys are supported, such as function keys are not supported). Transitions in
shift state, ctrl state, and so on, do not result in a key in the list, so if the user types Shift+a,
the character in the list will be A. The supported system keys are:
 Backspace
 Tab
 Escape
 Insert and Delete
 Up, Down, Left, and Right arrow key
 Page Up and Page Down
 Home and End
 Return
The columns in the list are as follows:
 Colum 1: If the key is a system key, column 1 is the keyboard constant value
representing the key, such as kEscape. Otherwise column 1 is #NULL.
 Colum 2: If the key is a data key, column 2 is the character data for the key. Otherwise
column 1 is #NULL.
 Colum 3: Is the sum of the following keyboard modifier constants, representing the
state of these modifiers at the point the key was added to the list: kJSModShift,
kJSModCtrl, kJSModAltOrOption, kJSModCmd.
In addition, there are some properties which control when evKeyPress events are generated.
The Omnis preference $keyeventdelay is the minimum number of milliseconds (0-2000)
between evKeyPress events. The first evKeyPress will also be delayed for this duration.
This allows you to throttle keyboard events in the case where they will be executed on the
server, and therefore reduce the load on the server. If true, the preference $systemkeys
specifies that evKeyPress events include system keys which do not change the value of the
data. If false, only system keys such as backspace are included as they potentially change
the data.
While the user is typing, the edit control in the user interface remains enabled (unlike
normal event processing where the entire user interface is usually disabled). The value of

156
List Control

the instance variable associated with the edit control reflects the current content of the entry
field when evKeyPress is generated.

Creating Linked Lists


The Edit Control has the $linkedobject property which is the name of a list control on the
current remote form used to display suggestions to the user if the Edit control enables the
evKeyPress event. You need to add the code to populate the list in response to evKeyPress,
based on the current value of the instance variable specified for the Edit control.
When the end user types into the Edit control, the linked list will appear automatically. It is
not necessary to process any events for the list control, since the dynamic list behavior is
determined automatically by being linked in this way. Therefore you would expect the
following to happen when end users are using a dynamic linked list:
 Clicking on a line in the open list will set the edit control to the value of the clicked
line.
 Pressing up or down arrow when the focus is on the list control will set the value of the
edit control to the new current line of the list.
 Pressing the down or up arrow when the edit control has the focus and when the list is
not visible will open the list, set the edit control value to the selected line in the list, and
move focus to the list.
 Typing into the edit control when the list is closed will open the list and keep focus on
the edit control.
 All the following will close the list: pressing return when the list has focus; pressing
escape, or clicking away from the list or the edit control.
Optimizing the Linked List
The list property $selectedlinesonly specifies that only the selected lines in a list will be
displayed (this only applies when $ischecklist is false), which in the context of Linked lists
allows you to filter the content of a list that is linked to an Edit control. You should
optimize the $event method for the edit control in the following way:
 Make $event for the Edit control execute on the client.
 On evKeyPress, if the list of suggestions is empty (or no longer suitable for the data),
call a server method to build the list (with lines selected based on the value of the edit
control).
 In subsequent evKeyPress events that can use the pre-built list, perform a list $search to
change the selected lines to the ones which are suitable for the new value of the edit
control.
In this way, the list of suggestions is cached on the client, and updates simply by changing
the selected lines with a search in your code.

157
Chapter 3—JavaScript Components

When $selectedlinesonly is true, the processing involving the usual click events and so on
all use the line number of the data in the list, not the lines displayed in the list.
Note that if you use the $evenrowcolor property when $selectedlinesonly is true, the even
row color applies to the numbers obtained by counting the displayed lines, rather than using
the line numbers of the data in the list.

Map Control
The Map Control allows you to place a Google map on your remote form. In order to use
the Map control, you should register with Google to obtain a map API key, which can be
entered in the $apikey property of the control.
Important Note: By signing up to Google Maps and using the maps in your deployed
application, you and your end users must agree to the general “Terms of Use” for Google
Maps: there is a link to these Terms of use on the map displayed in the Map control.
TigerLogic cannot be held responsible for any third-party products or services and will not
be liable for any damage or loss resulting from your use of the Google Maps content or the
products.
Apart from the $apikey property, there is no further configuration needed to display a basic
Google map in your remote form, but to make the map really useful you will probably want
to display specific locations, add markers on the map, or allow end user interaction with the
map: all of these are possible with the Map control and are described below.

Map Location and Zoom Level


The $latlong property allows you to specify the center location of the map as
“latitude:longitude”, for example, a value of 40.749305:-73.985775 will center the map on
New York. If you do not set $latlong initially (by setting the property in the Property
Manager in design mode or in the $construct method of the form), the map will open at
some unspecified location, usually the default location setup in Google on the client device.
The $::zoom property lets you set the zoom level of the map: the range is 0 to 21, with zero
showing the largest area (the whole world) and 21 the smallest possible area. The default
zoom level is 8 which shows a reasonable amount of detail for the current center location of
the map.

Map Type and Controls


The $maptype property lets you set the type of map – this can be set to a constant:
kJSMapTypeRoad (default), kJSMapTypeSatellite, kJSMapTypeHybrid, and
kJSMapTypeTerrain. The end user can change the map type using the map type control
shown on the map, assuming the $maptypecontrol property is enabled.

158
Map Control

The other standard map controls, including the pan control, scale control, and the street
view control are enabled using the properties $pancontrol, $scalecontrol, and
$streetviewcontrol, respectively (these are all enabled by default): note you can only change
these properties at runtime if the map control itself is enabled ($enable = kTrue).
The zoom control can be further controlled by setting the $zoomcontrol property: it can be
set to kJSMapZoomOff, kJSMapZoomDefault (the default), kJSMapZoomSmall, and
kJSMapZoomLarge. The latter two settings correspond to a simple Plus|Minus button
(Small) or the same button with a vertical slider control (Large) for finer adjustment of the
map zoom level.

Map Markers
You can place a marker or set of markers on the map by
assigning a row or list containing marker information to
the $mapmarkers property. For each marker you must
define the latitude and longitude of the marker location in
the first column of the setup list in the format
latitude:longitude (e.g. “40.749305:-73.985775”), and in
subsequent columns you can specify the marker title
(shown when you hover over the marker), the tag or title
for the popup (shown when you click on the marker), and
html content for the popup. If the third and fourth columns
are empty for any marker defined in the list, the marker
will not popup when clicked. (See the Events section about how to add markers via user
clicks.)
The following code adds markers to a map indicating the Empire State Building and Central
Park in New York, it then centers the map on the Empire State Building, and sets a zoom
level of 12 which shows a reasonable level of detail in this case:
; create vars map_markers (List), marker_latlong, marker_title,
marker_tag, marker_html (Chars)
Do map_markers.$define(
marker_latlong,marker_title,marker_tag,marker_html)
Do map_markers.$add(
"40.749305:-73.985775","Empire State Building","Empire State
Building","<div id='content'><h3 id='firstHeading'>Empire State
Building</h3><div id='bodyContent'><p><b><img src='http://nyc-
architecture.com/MID/esb1.jpg'></b></p></div></div>")
Do map_markers.$add(
"40.766225:-73.972514","Central Park","NY Central Park","<div
id='content'><h3 id='firstHeading'>Central Park</h3><div
id='bodyContent'><p><b>Central Park Info</b></p></div></div>")
Do $cinst.$objs.map.$mapmarkers.$assign("map_markers")
Do $cinst.$objs.map.$latlong.$assign("40.749305:-73.985775")
Do $cinst.$objs.map.$::zoom.$assign(12)

159
Chapter 3—JavaScript Components

Events
There are various events available in the map control to allow you to detect when and where
the map was clicked (evMapClicked, reports latitude and longitude of the click), when the
map is dragged by the end user (evMapMoved, reports the latitude and longitude of the new
center location), when the map is zoomed using the zoom control (evMapZoomed), or when
a map marker is clicked (evMarkerClicked). None of these events are enabled by default, so
you have to enable them in the $events property for the control using the Property Manager.
The following $event method could be placed behind a map control to detect when the map
is clicked, or when a marker is clicked (assuming a marker has been added), or if the map is
moved or zoomed. The add_markers Boolean variable is linked to a checkbox on the
window to allow the end user to enable or disable the ability to add markers. When the map
is clicked, the evMapClicked event reports the position in pLatlong, and a marker definition
is added to the map_markers list. The message variable is assigned to a field on the form to
show either the new center of the map, the new zoom level, or which marker has been
clicked.
; $event method for map control
; define vars map_markers (List), marker_latlong, marker_title,
marker_tag, marker_html, message (Chars), add_markers (Bool),
marker_no (Long int = 0)
On evMapClicked
If add_markers ;; linked to checkbox on window
Calculate marker_no as marker_no+1
Do map_markers.$define(
marker_latlong,marker_title,marker_tag,marker_html)
Do map_markers.$add(
pLatlong,con("Marker ",marker_no),
con("Marker ",marker_no),con("This is marker ",marker_no))
Do $cinst.$objs.map.$mapmarkers.$assign("map_markers")
End If
Calculate message as con(
pick(add_markers,"Map clicked here: ",
"Marker added here: "),pLatlong)

On evMapMoved
Calculate message as con("Center is now: ",pNewCenter)

On evMapZoomed
Calculate message as con("New zoom level: ",pNewZoom)

On evMarkerClicked
Calculate message as con("Marker clicked: ",pMarker)

160
Navigation Bar Control

Navigation Bar Control


The Navigation Bar Control provides a standard navigation bar which end users can use to
navigate to different parts of your application. The navigation bar has a main title in the
middle of the control, and it can have a left and/or right button which responds to user
clicks. The Nav bar can be linked to a Paged Pane via the $linkedobject property to allow
you to display different panes in your form in response to clicks in the nav bar. Actions for
the nav bar can be stacked up using the $push property: see the example below.
The Nav Bar has a number of properties for setting the color, fonts and style of the bar and
buttons ($button.. properties), together with the following properties:

Property Description
$initiallefticonid if this is not zero, and $initiallefttext is empty, the first navigation
bar item has a button on the left hand side, displaying this icon
$initiallefttext if this is not empty, the first navigation bar item has a button on the
left hand side, displaying this text
$initialrighticonid the icon for the initial navigation bar button on the right
$initialrighttext the text for the initial navigation bar button on the right
$initialtitle is the initial title displayed on the navigation bar
$lefthidden if true, the left hand (back) button is hidden for the current
navigation bar stack item
$linkedobject the name a paged pane on the current remote form, used in
conjunction with the $push property
$push At runtime, allows you to assign a 2-5 column row to the paged pane
referenced in $linkedobject: col1 is the page number of the paged
pane, col2 is the title for pushed item, col3 is the text for right button
(pass empty for no right button), col4 is the or icon id for the image
for right button, and col5 can be non-zero to hide the left button
$righticonid if this is not zero, and $righttext is empty, the current navigation bar
item has a button on the right hand side, displaying this icon
$righttext if this is not empty, the current navigation bar item has a button on
the right hand side, displaying this text
$::title the title for the current navigation bar stack item

Events
The Nav Bar reports evClickInitialLeftButton when the initial left button has been clicked,
and evClickRightButton when the right button has been clicked.

161
Chapter 3—JavaScript Components

The events evPushFinished and evPopFinished are triggered when the push or pop
animations complete. Both events have one event parameter which is the associated page
number that has been pushed or popped.

Example
The following Navigation Bar has a main title and a button on the right which is used to
display some information on the second pane of a paged pane.

The Nav Bar is placed across the top of the form and its various properties under the
General and Appearance tabs in the Property Manager are set, as follows:

$events set to receive evClickRightButton events


$linkedobject set to pPane, the name of the paged pane
$push can only be assigned at runtime; see below
$initialtitle set to “Main Page”
$initialrighticonid set to 1794, the id of an icon in Omnispic
$initialrighttext set to “Info”

The $event() method for the Nav Bar ($name = oNav) traps a user click on the right button,
and has the following event code:
On evClickRightButton
Do $cinst.$doPush(2,'Info','','','')
The $doPush method is a class method in the remote form and has the following
parameters, variables, and code.
; PaneNo (Short Int)
; Title, RightBtnText, RightBtnIcon, NoLeftBtn (all Character)
; lRow is local var of type Row
Do lRow.$define(
'New class','Title','text for right btn',
'icon for right btn','no left btn')
Do lRow.$assigncols(
PaneNo,Title,RightBtnText,RightBtnIcon,NoLeftBtn)
Do $cinst.$objs.oNav.$push.$assign(lRow)
The effect of assigning to the $push property is to change the pane number in the paged
pane specified in the $linkedobject property which, in this case, displays some information
for the end user on the second pane.

162
Page Control

Page Control
The Page Control links to a Paged pane on a remote form and allows the end user to change
the current page in the linked paged pane by swiping over the page control or clicking for
non-touch screens. The paged pane linked to the Page control is specified in the
$linkedobject property. In this case, when the page control is clicked the linked paged pane
control will select the next available pane automatically.
The Page control also gives the end user a visual clue as to the current selected pane in the
linked page pane object, since the highlighted dot in the control changes to reflect the
current page in the linked paged pane.

Property Description
$::currentpage the current page number
$linkedobject the name of a paged pane object on the current remote form that
links to the iPage control
$::pagecount the number of pages

When the page indicator changes in the Page control an evPageChanged is triggered
containing the number of the new page in pValue.

Paged Pane
The Paged Pane provides a very convenient method to show a number fields or controls on
separate panes, or to break down an entry form into more manageable parts whereby each
pane contains a small number of fields. The $pagecount property specifies the number of
panes, and $currentpage specifies the current pane. In design mode, you have to set
$currentpage to the number of the pane you wish to add fields to, or you can right-click the
background of the paged pane and select the number of the pane you want to edit. You can
set $effect to select different border effects for the control (a kJSborder... constant).
You can link a paged pane to a Navigation Bar, Page Control, or Tab Bar control so when
the nav bar, page or tab changes the current pane of the paged pane changes accordingly. To
link a paged pane to one of these controls, set the $linkedobject property of the Nav bar,
page control or Tab bar to the name of the paged pane.
By setting $scrolltochangepage to kTrue the pages are laid out horizontally, and the end
user can change the current page by scrolling horizontally (for touch devices the end user
can change panes by tapping on the current one); in this case, an evUserChangedPage is
triggered with the new page number reported in pPageNumber.
The $borderradius property lets you add rounded corners to the Paged pane. It can be set to
up to four pixel values separated by -, in the order topleft, topright, bottomright, bottomleft.

163
Chapter 3—JavaScript Components

If bottomleft is omitted the topright value is used. If bottomright is omitted the topleft value
is used. If topright is omitted the topleft value is used.

Using $dataname
The Page Pane control has a $dataname property which you can use to set the value of
$currentpage. When the form is opened or redrawn the numeric value of $dataname is used
to set the current page. If $dataname is empty or returns an invalid page number, the control
uses the page number in $currentpage.

Page Panes in Complex grids


You can use a page pane in a complex grid. You can set the value of $currentpage by
assigning a column in the complex grid list to $dataname of the page pane. Therefore each
row in the complex grid could display a different page in the page pane control.
In this case, controls within the page pane control will also get their data from the complex
grid control, if their $dataname refers to a column in the list used to build the complex grid.

Picture Control
The Picture control allows you to display an image in your form: you can display an image
file in a folder, an image from a database, or an icon, depending on the combination of
settings of $dataname, $mediatype and $iconid. If $mediatype is empty (and $iconid is
zero), the $dataname of the Picture control is a URL to the image to be displayed, relative
to your html page containing the JavaScript Client. If $mediatype is specified, then
$dataname is the name of a binary instance variable containing the image data: in this case,
$mediatype can be set to one of the standard image types, e.g. image/png, image/jpeg or
image/gif. Alternatively, $iconid can be set to a URL referencing an image file in the
‘html/icons’ folder, overriding the $dataname and $mediatype properties. For backwards
compatibility, the picture control can display an icon in an icon data file (Omnispic) or
#ICONS by setting $iconid to a numeric icon ID.
$picturealign is a kPAL... constant which, together with $horzscroll and $vertscroll,
identifies where the picture will be positioned in the control. If true, $noscale ensures the
images displayed in the control are not scaled.

Example
In the Webshop sample app, the product images are shown in a Picture control embedded
in the Complex grid control on the main jsShop remote form. In this case, $mediatype is set
to JPG and the $dataname of the control is iProductList.product_picture which holds the
image data for each product.

164
Pie Chart Control

Pie Chart Control


See Bar Chart Control.

Popup Menu Control


The Popup menu is a menu that pops up when the user clicks on the header of the control,
or, when $hotwhenmouseover is true, the menu will pop up when the end user’s mouse
hovers over the control. The contents of the popup menu can be a remote menu class
specified in $::menuname, or taken from a list variable specified in $::listname; when
specifying one of these properties, the other property must be empty.
When using a list variable to populate the popup menu, the data in the column specified in
$coltext is used for the menu options. The $colenabled property is the column name for the
menu line enabled state, and $colcommandid is the column name holding the menu line
command id.
You can add an icon to the popup menu by setting $iconid to the ID of an icon in an icon
file or #ICONS. You can place the icon before or after the menu title by setting
$textbeforeicon.
The menu will normally popup when the user clicks on the control, but you can make the
menu popup when the end user’s mouse passes over the control (make it “hot”) by setting
$hotwhenmouseover to kTrue. In addition, if you set $hottitleclicks to kTrue, clicking on
the control will generate an evClick event.
You can control the position of the popup by setting $menupos to one of the constants:
kJSPopMenuPosBottom, kJSPopMenuPosRight, or kJSPopMenuPosTop.
When the menu is clicked the evClick event is triggered with the selected line reported in
pLinenumber. You can use the following $event method to trap the line number:
On evClick
If pLineNumber>0 ;; a line was selected
;; Do something
End If
You can use an HTML <select> tag for the user interface by setting $usehtmlselect to
kTrue.

165
Chapter 3—JavaScript Components

Progress Bar Control


The Progress Bar control lets you display a progress bar in your remote form. The current
value of the progress bar is reported in the $::value property which is a value between 0 and
the value of $max inclusive. The color of the bar representing the completed amount can be
set in $progresscolor, which only applies when the standard HTML5 progress control is not
available.
The progress control does not store a value (like the fat/web client control). Rather,
$sendcarryon provides a mechanism to send an evCarryOn event to the progress control. To
generate an evCarryOn event, assign kTrue to $sendcarryon. The event processing code for
evCarryOn can assign $sendcarryon to kTrue again, to generate the next evCarryOn.
You can add a Cancel button to your form to allow the end user to break the long process,
but the Cancel button itself must be named in the $alwaysenabledobject remote form
property so it remains enabled during the long process.

Example
The following example assumes the progress control has been added to a remote form and a
button is used to initiate some process and send a carryon event to the progress itself. The
initial values for $::value and $::max of the progress control are 0 and 100 respectively. The
following code could be behind a button:
On evClick
;; initiate some process and
Calculate iCancelled as kFalse
Calculate iValue as 1
Do $cinst.$objs.ProgressBar.$sendcarryon.$assign(kTrue)
The evCarryOn event is sent to the progress bar which has the following event method:
On evCarryOn
If not(iCancelled)
Calculate iValue as iValue+1
Do $cinst.$objs.ProgressBar.$::value.$assign(iValue)
If iValue<100
Do $cinst.$objs.ProgressBar.$sendcarryon.$assign(kTrue)
End If
End If

166
RadioGroup Control

RadioGroup Control
Radio Groups present a number of mutually exclusive buttons that can be either on or off:
selecting one of the radio buttons deselects all other buttons in that group. The variable you
assign to a radio group should be numeric. Its value is within the range $minvalue and
$maxvalue inclusive and directly corresponds to which button in the group is selected, that
is, the first button selects the first value in the range, the second button the second value,
and so on. The labels for the buttons are assigned in $text which is a comma-separated list.
The Radio group has the following properties:

Property Description
$dataname a numeric variable
$horizontal If true, the radio column order is horizontal
$columncount The number of columns shown for the radio group
$minvalue The minimum value for the radio group
$maxvalue The maximum value for the radio group
$text Comma-separated list of labels assigned to the buttons

The evClick event is reported with pNewValue containing the value selected.

Example
The Webshop app uses a Radiogroup control to allow the end user to select a group or
category of products to be shown in the main product list. (To examine this control and its
properties and methods, open the webshop library and the jsShop remote form.) The
$minvalue and $maxvalue of the radiogroup are set to 0 and 8, respectively (although the
groups are generated dynamically in the form), and the numeric variable iRadioGroup with
an initial value of 1 is assigned to $dataname. When the form is opened, the $construct()
method behind the radiogroup calls a $build method.
; radiogroup control is called ‘filter’ containing
; $construct method which is run when the form opens
Do iGroupList.$definefromsqlclass($tables.T_qGroups)
Do $cfield.$build()

167
Chapter 3—JavaScript Components

The $build method generates a list of product groups from the database, which is then
concatenated into a single comma-separated list and assigned to the $text property of the
radiogroup.
; $build method behind the radiogroup
Do iGroupList.$selectdistinct()
Do iGroupList.$fetch(kFetchAll)
For iGroupList.$line from 1 to iGroupList.$linecount() step 1 ;;
loop through the list
Calculate text as con(
text,mid($prefs.$separators,3,1),iGroupList.product_group)
;; uses the localized separator (possibly semicolon)
End For
Calculate text as mid(text,2,len(text))
Do $cfield.$minvalue.$assign(1)
Do $cfield.$maxvalue.$assign(iGroupList.$linecount())
; $maxvalue of radiogroup is set to the number of groups in list
Do $cfield.$text.$assign(text)
When the form is opened the main product list is built using a method behind the product
list itself (also called $build) and the list initially contains the Appetizers only. A group of
radio buttons is created, each item representing a different group or category of food or
drink; the initial value of the radiogroup is set to 1 selecting the first item in the group.

When the end user clicks on the radiogroup, to select another product type, the click is
detected in the $event method in the radiogroup control, the number of the radio button
clicked is passed in pNewVal, and the product list is rebuilt based on the selected product
group; note a Where clause is created based on the selected group and sent to the $build
method behind the main productList control.
; $event method for Radiogroup
On evClick
Calculate whereClause as con(
'WHERE product_group =
',kSq,iGroupList.[pNewVal].product_group,kSq)
Do $cinst.$objs.productList.$build(whereClause)

168
Rich Text Editor Control

Rich Text Editor Control


There is a new JavaScript control that allows the text in a field to be edited by the end user
– this is very useful for applications in which you want to allow end users to edit content
and will be suitable for many types of web and mobile apps.
The JavaScript Rich Text Editor Control (jsrich) is available in the JavaScript Component
Store and can be used instead of a regular edit or multi-line edit field. The text data for the
control is stored in the instance variable assigned to $dataname. You can allow text editing
in the control by setting $showcontrols to kTrue where upon the text content in the field will
become editable: on mobile devices this places the cursor in the field and opens the soft
keypad ready for typing. The text editing controls in the field will appear at the top of the
control and will allow the end user to format the text, including bold, italic, underline, and
so on. The text data in the control is HTML markup and can include formatted text such as
ordered (numbered) and unordered lists (bullets). End users can also insert images using the
Paste option.
Properties
Together with the standard component properties, the Rich Text Editor Control has the
following properties:

Property Description
The name of an instance variable to store the text, or a column in an
$dataname
instance row variable
$showcontrols Set to kTrue to show the Rich text editing toolbar

Localizing the Rich Text Editor


There are various strings in the Rich Text Edit control that can be localized in the string
table for the remote form containing the control. You must use the following string table ids
to replace the default text for the controls in the text editor.
Tooltips for buttons
rt_bold rt_subscript rt_italic
rt_superscript rt_underline rt_strikethrough
rt_justifyleft rt_removeformat rt_justifycenter
rt_indent rt_justifyright rt_outdent
rt_justifyfull rt_textcolor rt_insertorderedlist
rt_backgroundcolor rt_insertunorderedlist

169
Chapter 3—JavaScript Components

Text displayed on controls


rt_fontsize and rt_fontfamily.

Slider Control
The Slider control provides a graphical thumb component that the user can drag to control
the numeric setting of another component in your form, such as a volume control. The
current value of the slider is reported in the property $val according to where the slider is
positioned. You can specify the range for the slider in the $min and $max properties, while
$step is the size of each step the slider takes between the min and max values. The slider
also has these properties:

Property Description
$vertical If true, the slider is a vertical slider
$sliderhorziconid The id of the icon to use for a horizontal slider handle
$sliderverticonid The id of the icon to use for a vertical slider handle
$horzmargin The horizontal drawing margin
$vertmargin The vertical drawing margin

The Slider reports three events: evStartSlider (when the control is starting to track),
evEndSlider (when the control has finished tracking), and evNewValue (when the value has
changed). You can detect these events in the $event() method for the component. These
events all pass the current value of the Slider in the pSliderValue parameter. As the user
drags the Slider thumb the evNewValue event is triggered and pSliderValue is sent to the
$event() method for the Slider.
To use the values of the slider in your remote form you can trap the slider events in the
$event method of the slider control and transfer the current values to instance variables in
your form, as follows:
On evStartSlider
Calculate iStartValue as pSliderValue
On evEndSlider
Calculate iEndValue as pSliderValue
On evNewValue
Calculate iNewValue as pSliderValue

170
Subform

Subform
The Subform control allows you to place another remote form inside the main remote form;
the concept of the subform is similar to embedding an iframe into an HTML page where
you can embed another form or page. You could, for example, create a single “main” form
and a number of other remote forms loaded at runtime into a subform control, to create a
powerful and interactive web application with many subforms or layers.
When you have placed the subform control on your remote form, you specify the initial
remote form to appear in the subform in the $classname property. Alternatively, you can
switch subforms at runtime by assigning a new remote form to $classname to switch the
current form displayed in the subform control, as follows:
; oSub is the name of the Subform control on the main Remote form
Calculate $cinst.$objs.oSub.$classname as NewFormName
Note you can also create subforms dynamically in a Subform Set which are described in the
Remote Forms chapter.

Example
The Holidays sample app uses a subform to display either the User or Admin form. When
the main jsHolidays remote form is loaded, its $construct() method calls a class method to
setup the initial subform to be shown which, in this case, is the User form. In addition, there
are buttons on the main Holidays form to allow the end user to switch forms; for example,
the code behind the User button is:
; $event method for User button on jsHolidays
On evClick
Do method setSubForm (kUserForm)
Calculate iAdminBtnState as kTrue
Calculate iUserBtnState as kFalse
Do $cinst.$objs.adminBtn.$enabled.$assign(kTrue)
Do $cobj.$enabled.$assign(kFalse)
The setSubForm method has the following code to switch forms:
If pOption=kAdminForm ;; test if Admin or User
Do $cinst.$objs.subForm.$classname.$assign("jsAdminForm")
Else
Do $cinst.$objs.subForm.$classname.$assign("jsUserForm")
End If

171
Chapter 3—JavaScript Components

$dataname and Subforms


If the remote form class inside the subform field has only one field you can override its
dataname using the $dataname property for the subform field. For example, your subform
class may contain a single headed list field that takes its data from a particular list variable.
However you can change the list assigned to the headed list by setting the subform field’s
$dataname property to the name of another list. You could do this in the $construct()
method of the subform field.

$construct and Subforms


Opening a remote form containing a subform field or any number of subform objects creates
an instance of each form, which belong to the same task as the parent remote form instance.
Omnis calls the $construct() methods of all the subform classes first in tabbing order, then
the $construct() method of the parent form instance. The reverse happens on closing the
parent form, with the subforms being destructed after the parent form instance.
You can send parameters to the subform’s $construct() method by including a list of
parameters in the $parameters property when you create or modify the subform field.

Multiple Subforms and Caching


The $multipleclasses property tells Omnis to keep a set of remote form instances open for
use in the subform object, rather than constructing a new instance each time the class is
changed. When you assign a new remote form name to $classname at runtime, the new
remote form is downloaded to the client and displayed in the client’s browser. If the
$multipleclasses property is enabled, the previous remote form is cached and hidden on the
client, otherwise the remote form instance is destroyed. If any previous remote forms have
been cached in this way using $multipleclasses, you can switch back to them
instantaneously, otherwise they have to be reloaded each time you assign to $classname of
the subform object.

Referencing Subform Instances


A subform control has the $subinst property (object) which is the instance contained within
the subform control. You can use this property to get a reference to the instance in a
subform object and therefore change properties within the instance. If the subform property
$multipleclasses is set to kTrue, you must use $subinst(cClassName) to get a reference for
the appropriate instance. For example, where a subform control has a single subform class
the following code will return a reference to the form instance in the subform:
Set reference item to $cinst.$objs.subfrm.$subinst
Do item.$setcolor(kRed)
or when you may have assigned multiple classes to the subform control ($multipleclasses is
set to kTrue):

172
Switch Control

Set reference item to $cinst.$objs.subfrm.$subinst("classname")


Do item.$setcolor(kRed)
Note that the item returned will be null if the instance does not exist.

Subform Container Notation


You can use $cinst.$container to obtain the instance containing a subform instance, where
in the current context $cinst is a subform. The $container property returns the object
containing the referenced object. This notation will work in server methods (for all clients) ,
and client-side methods for the JavaScript Client only. For examples:
Set reference item to $cinst.$container
Do item.$getList() Returns iList
; and
Calculate $cinst.$container().iSelected as iList.C1

Switch Control
The Switch control is like a check box insofar as it represents an On / Off value (1 or zero);
when the end user clicks the switch the value of the control’s variable alternates between 1
and zero so the control is useful for representing preferences which can be Enabled or
Disabled. The variable you specify in the $dataname property should be a Number or
Boolean variable. The $switchon and $switchoff properties let you specify the icon IDs for
the images to be used when the switch is either on or off.

Example
There is an example library showing the Switch control with a range of different ON/ OFF
images in the new JavaScript Apps Gallery on the Omnis website at:
www.tigerlogic.com/omnis

173
Chapter 3—JavaScript Components

Tab Control
The Tab Control allows the end user to select a tab which can correspond to a specific
option in your application. The $tabcount property lets you specify the number of tabs; it
can be set to zero in design mode, and the number of tabs assigned at runtime using the
notation. The $currenttab property specifies which tab is highlighted and its value will
change as the end user selects a tab: assigning a new value to this property at runtime will
change the highlighted tab.
In design mode, you can specify the properties for a particular tab by making it the “selected
tab” in the $selectedtab property, under the “Tab” tab in the Property Manager. The text for
a tab is specified in the $tabtext property: you can add a line break by inserting //. The size
of the tab (i.e. the width for horizontal tabs) is determined by the width of the text on the
tab. However, you can set $fixedtabsize to kTrue to fix the size of the tabs, and set
$maxfixedtabsize to set the tab width or height. You can hide or show a tab using the
$tabvisible property, and you can disable or enable a tab using $tabenabled; for example,
you can set these properties for individual tabs to kFalse in design mode and at runtime set
these properties to kTrue to show and enable the tabs.
There are many properties under the Appearance tab in the Property Manager to control the
general appearance of the Tab Control and the tabs themselves. The tabs have angular
corners by default, but you can round the corners by setting $tabborderradius. You can
create a vertical aligned set of tabs by setting the $side property: you can orient the tabs on
the left or right. The $tabsjst property determines the position of the tabs within the control.

Tab Icons
By default, the tabs display text only, but you can add an icon to the tabs by selecting the
position of the text and icon by setting $tablayout. For example, you can set $tablayout to
kJSTabsLayoutIconLeft to add an icon to the left of the tab text, and then set $tabiconsize
to set the width of the space allowed for the icons.

Reordering Tabs
In design mode, you can move or re-order the tabs in the control by entering a number into
the $movetab property; in effect, the number of the selected tab will become the number
you entered, and the other tabs are shuffled along. This is useful if you have setup multiple
tabs and need to move a tab easily without having to redefine each tab again.

Linking Tabs to Panes


The Tab Control can be linked to a Paged Pane by setting $linkedobject to the name of a
Paged Pane control, so when different tabs are clicked, the pane in the linked Paged Pane is
changed automatically. Assigning a new value to the $currenttab tab property of the Tab
control at runtime will also change the current pane in the linked Paged Pane control.

174
Tab Control

The base edge of the tab control does not normally have a border, and when the tabs are
linked to a paged pane the tab control updates the paged pane border so that there is the
appearance of a gap below the current tab. If you want to add a border under the tabs you
need to set $baseedgewidth to 1 or more.

Tab Menus
The Tab Control can also be linked to a Remote Menu class; clicking on a tab will trigger
the corresponding line in the menu. To implement this, the $trackmenus property must be
kTrue. The $tabmenu property is the name of a remote menu class for the selected tab (the
tab with number $selectedtab). If assigned at runtime, the menu instance must already be
present on the client (via a $tabmenu or $contextmenu property in the class data when the
form was loaded).
You can control the color of the menu lines and text using the $tabmenu… properties under
the Appearance and Text tabs in the Property Manager, or in your code for the control.

Events
When the end user clicks on a tab the value of $currenttab will change and an
evTabSelected event is triggered, with the new tab number reported in pTabNumber. This
event needs to be enabled in the $events property for the control to be reported.

Example
The Contacts sample app users a Tab control in the main jsContacts remote form to allow
the end user to switch from viewing a list of contacts to a form showing details of individual
contacts. In this case, the Tab control is linked to a page pane which displays the contact list
or contact details view. The $linkedobject property of the contactTabStrip control is set to
‘pagePane’ (the name of the page pane) and the $tabtext for each tab is defined as
‘Contacts’ and ‘Details’ respectively. In addition, the evTabSelected event is enabled in the
$events property of the Tab control. The code for the Tab control $event method is:
; $event method for Tab control
On evTabSelected
If pTabNumber=2
Do method loadRecord (iContactList.$line)
Do $cinst.$objs.saveBtn.$enabled.$assign(kTrue)
Else If pTabNumber=1
Calculate iNewContact as kFalse
Do $cinst.$objs.saveBtn.$enabled.$assign(kFalse)
End If
If the Details tab is clicked, the second tab, the second pane in the page pane is displayed
and the details for the currently selected contact are loaded using the loadRecord class
method.

175
Chapter 3—JavaScript Components

Timer Control
The Timer is an invisible component that triggers an evTimer event after a specified time
while $running is set to kTrue. You can specify a $timervalue, which is interpreted as an
interval in seconds or milliseconds according to $useseconds, which should be set to kTrue
for seconds or kFalse for milliseconds (the default).

Example
In the Webshop sample app it would be possible to use the Timer control to rebuild the
Orders list periodically; in this case, you could use the Timer object to run a method at a
given interval to rebuild the Orders list in the jsShopOwner remote form. In reality, the
Orders list is rebuilt every time a new order is placed, but using the Timer object could be
used to regulate the rebuilding of the Orders list.
To implement a Timer in the Webshop app, you would need to enabled the evTimer event
in the $events property of the Timer control. The $useseconds property is set to kTrue and
$timervalue is set to 2 (to give an interval of 2 seconds). The $construct() method of the
Orders list (a data grid) includes a line of code to start the timer:
; $construct method for Orders list/data grid
Do iOrderList.$definefromsqlclass($tables.T_qOrders)
Do $cinst.$objs.timer.$running.$assign(kTrue) ;; possible using
a timer object
Do $cfield.$build()
The $build() method behind the Orders list builds the list when the form is opened, but
when used with the Timer object it can be used to rebuild the list as well. The $event
method for the Timer object is run every 2 seconds, and has the following code:
On evTimer
Do $cinst.$objs.dataGrid.$build()

Trans Button Control


The Trans button can display a different icon and/or background color when the end user’s
mouse hovers over the control, or when the button is tapped on touch devices. In all other
respects the Trans button is like a standard push button control, insofar as it generates a
single evClick event when the button is clicked which can be used to initiate an action in
your code. Note the evClick event must be enabled in the $events property for the control
for it to be reported.
The Trans button has several properties prefixed “$hot” that relate to the appearance of the
button for the hover action. You can specify two icons for the Trans button: one to represent
the “off” state which is specified in $iconid, and the other to represent the “over” state

176
Tree Control

which is specified in $hoticonid – if no $hoticonid is specified the $iconid is used. You can
also specify a different background color for the hover action in $hotbackcolor, and an
alternative border color in $hotbordercolor.

Tree Control
The Tree Control provides a graphical way of displaying a list of items in a hierarchical
format. Each node can have a check box or its own icon. The $dataname property for a tree
list is the name of a list variable containing the content (data) and structure of tree list. The
list can contain the entire data for a tree list when the form is opened in the client, or when a
tree list is in “dynamic” mode the content can be built as nodes are expanded by the end
user. Tree lists have the following additional properties:

Property Description
$checkbox If true, and $multipleselect is also true, the tree control has check
boxes that can be used to select nodes
$currentnodeident The current node ident for Dynamic tree lists only: see below
$datamode Controls how the list content is used to structure the tree list, a
constant:
kJSTreeFlatList, kJSTreeFlatListWithTags
kJSTreeFlatListOld, kJSTreeFlatListOldWithTags
$iconurlprefix All icons used in the tree (as a result of $showicons being true) must
come from a single icon directory; the default is icons/omnispic/
$multipleselect If kTrue allows the end user to select more than one line; should be
enabled for tree lists with $checkbox enabled
$nodeaction Performs an action on the tree node, only for Dynamic mode: see
below
$nodedata List for tree node when building dynamically: see below
$showicons If true, the tree control shows node icons from location in
$iconurlprefix
$showlines If true, the tree control displays dotted lines connecting nodes
$twostate If true, and the tree control has checkboxes (see $checkbox), selection
of each node is independent

By default the rows in a tree list are spaced automatically, based on the font size of the
control, but $extraspace allows you to add extra space in between the lines in the list. The
$extraspace property is the number of pixels added to the normal font height of a row in the
list, or zero for no extra space.

177
Chapter 3—JavaScript Components

Tree List Data Format


The format or “mode” of the data is set in the $datamode property which controls how the
list content is used to structure the data in the tree list. There are several different data
modes to format a tree list, plus the Dynamic mode, represented by the following constants:
 kJSTreeFlatList
The first N columns represent a node in a tree of depth N. The last 5 columns are node
properties: iconid,ident(int),expanded(bool),textcolor(zero means $textcolor),tooltip
 kJSTreeFlatListWithTags
The first N columns represent a node in a tree of depth N. The last 7 columns are node
properties: iconid,ident(int),expanded(bool),textcolor(zero means $textcolor), tooltip,
tag(char), enterable(bool)
 kJSTreeFlatListOld
A list with the same structure as the plug-in client tree kTreeDataFlatList
 kJSTreeFlatListOldWithTags
A list compatible with the plug-in client kTreeDataFlatListWithTags
 kJSTreeDynamicLoad
the tree list content can be built dynamically; see below

Tree Events
When the user selects a node the evClick event is reported, while a double click reports an
evDoubleClick. In both cases, the id and tag of the selected node is reported in the
pNodeIdent and pNodeTag parameters. Note you cannot get click or double click events for
nodes which are enterable, as the click puts them into edit mode.
For enterable nodes, the evRenamed event is reported if the end user has renamed the node.
evRenamed has node ident, node tag, old name and new name as event parameters.

Dynamic Tree Lists


The content inside a Tree List Control can be built dynamically as the end user expands a
node. In previous versions, the entire contents of the tree list had to be built and sent to the
client, including the contents for all unexpanded nodes, which for large lists created quite an
overhead. Building the tree list data and displaying content in a tree list can now be better
optimized with the ability to build node contents “on the fly” as required.

Creating Dynamic Trees


To use a Tree Control in dynamic mode you need to set its $datamode property to
kJSTreeDynamicLoad. Note that dynamic mode can only be used for ‘single-select’ trees,
and attempting to assign kJSTreeDynamicLoad to $datamode will fail if $multipleselect or
$checkbox for the tree control is kTrue.

178
Tree Control

As in previous versions, a dynamic tree still requires a list identified by $dataname, but the
list need only contain the initial content of the tree, that is, the content for the root or parent
nodes. After the list content is changed, the tree reloads its content from the list.
Dynamic trees also use lists to set the content of expanded nodes and to add nodes
programmatically to the tree. The lists all have the same structure: each list represents an
ordered set of nodes with the same parent (or no parent in the case of the $dataname list),
and the columns are as follows:
 Column 1: Text. The text displayed for the node.
 Column 2: Icon. Only used when $showicons is set to kTrue. This is a line number in
the list identified by $nodeiconlist, or zero if the node does not have an icon.
$nodeiconlist is described below.
 Column 3: Ident. A unique positive integer that identifies the node. Cannot be the same
as the ident of any other node in the tree. The tree control throws an exception
(resulting in a message box displayed on the client) if you try to use a duplicate ident.
 Column 4: Tag. A string associated with the node. Any value that is useful to the
developer. Need not be unique.
 Column 5: Tooltip. The tooltip string for the node, displayed when the user hovers the
mouse over the node. Leave empty for no tooltip, although on some browsers nodes
may inherit their tooltip from their parent node if the tooltip is empty.
 Column 6: Text color. The text color for the node (an integer RGB value). Zero means
use the $textcolor of the tree.
 Column 7: Flags. Integer flags. A sum of zero or more of the following constants:
 kJSTreeFlagEnterable. The node text can be edited (this works with the existing
evRenamed event).
 kJSTreeFlagHasChildren. The node has children.
 kJSTreeFlagExpanded. The node will be immediately expanded. If you set this
flag you must supply the child nodes using a node list supplied as the children
column.
 kJSTreeFlagDiscardOnCollapse. If set, when the user collapses the node, the
tree deletes the node contents. This means that the next time the user expands the
node, the tree will generate an evLoadNode event; evLoadNode is described later
in this document.
 Column 8: Children. If the kJSTreeFlagHasChildren is present, you can pre-populate
the node content by using a nested list to specify the children. If you do not supply any
children using this list, then you can supply them later by using the evLoadNode event
(see below). The content of this column is ignored if the kJSTreeFlagHasChildren is
not present. You can nest children lists arbitrarily deep (within reason).

179
Chapter 3—JavaScript Components

$nodeiconlist allows you to specify the icons to be used with the tree. These must be
available when the tree is updated from the dataname list. $nodeiconlist must be the name of
an instance variable list with at least one column which must be a character column
containing icon URLs. You can populate each URL in the node icon list using the iconurl()
function, for example:
Do iNodeIcons.$define(iNodeIcon)
Do iNodeIcons.$add(iconurl(1710))
Do iNodeIcons.$add(iconurl(1711))
Do iNodeIcons.$add(iconurl(1712))

Populating Expanded Nodes


Dynamic trees have the event evLoadNode which allows you to populate the tree on
demand, by only populating node content when a node is expanded. When using the
kJSTreeDynamicLoad mode for $datamode, evLoadNode is generated so that you can set
the content of the node by setting the $nodedata property which is the name of a list
containing the expanded node content. For other settings of $datamode, evLoadNode is
generated when the user expands a tree node.
The evLoadNode event has two parameters, pNodeIdent and pNodeTag, corresponding to
the node that is being expanded. In the event processing for evLoadNode, you can set a new
tree property, $nodedata, to a node list representing the content of the node (with the above
column format); if the event processing fails to set this property, the tree control sets the
node content to empty.
The list assigned to $nodedata can specify nested children if desired.
$nodedata is a runtime-only property that can only be set.

Manipulating Tree Nodes


Dynamic trees support ‘node actions’ to allow you to manipulate the nodes in a Tree List
programmatically. For example, you can expand or collapse a node, and you can add, delete
or rename modes. You execute a node action by assigning a row variable to the $nodeaction
property of the tree. The supported actions are as follows:
 kJSTreeActionExpand
row(kJSTreeActionExpand, ident). Expands the node with the specified ident if it is not
already expanded.
 kJSTreeActionCollapse
row(kJSTreeActionCollapse, ident). Collapses the node with the specified ident if it is
not already collapsed.
 kJSTreeActionRename
row(kJSTreeActionRename, ident, newname). Renames the node with the specified
ident to the new name.

180
Tree Control

 kJSTreeActionDelete
row(kJSTreeActionDelete, ident). Deletes the node with the specified ident (also
recursively deletes node children). If the current node is deleted, an evClick event will
be generated to inform the application of the new current node.
 kJSTreeActionAdd
row(kJSTreeActionAdd, ident, position, nodelist). Adds the nodes in the nodelist to the
tree, where ident specifies the parent node of the nodes in nodelist; to add a new root
nodes specify ident as zero. The position parameter can be one of:
 -1 to add the new nodes before any existing children of the node specified by ident
 0 to add the new nodes after any existing children of the node specified by ident
 a child node ident. New nodes are added after the child node with this ident. If no
such node exists, the new nodes are added after any existing children.
$nodeaction is a runtime-only property that can only be set.
Collapsing a Node
The tree control now generates evCollapseNode when the user collapses a node. This
applies to all trees, not just dynamic trees.

The Current Node


The current (selected) node in the tree is no longer represented by a list line. Instead, there
is a new property, $currentnodeident that applies to dynamic trees. When the user changes
$currentnodeident (by clicking on a node), the control generates evClick. In addition, the
developer can assign $currentnodeident (and read its value in client-executed methods).
$currentnodeident is a runtime-only property.

181
Chapter 3—JavaScript Components

Video Control
The Video control allows you to play a video within your remote form. The video can be
hosted on YouTube or you can play a video through a Flowplayer client.
The Video control allows you to play a video within your remote form. You can play videos
hosted on YouTube, or you can play video files directly accessed by a URL, using the
browser’s HTML5 video playing capabilities. The Video control has the following
properties:

Property Description
$dataname If $youtube=kTrue, this is a list containing YouTube ids; the id of the
video in the first column of the first row is played
If $youtube=kFalse, this is a 2 columned list containing URLs to video
files in Column 1 and media types in column 2
$showcontrols If true, the control displays video controls such as the play and pause
buttons
$flowplayerline If not zero, the line number in the $dataname list of the video content
to be used for the fallback Flowplayer object
$flowplayerurl The URL of the Flowplayer to be used as a fallback when HTML5
video is not available
$youtube If true, the control will play a movie from youtube.com; row 1 of
column 1 of the $dataname list is the YouTube video id
If false, the control will use HTML5 video (or Flash if HTML5 is not
supported) to play video files from URLs

YouTube
If you set the $youtube property to kTrue, the $dataname for the video control should be a
list containing YouTube ids: the data in the first column of the first row in the list is used to
reference the video. Note the YouTube id is not the full URL on youtube.com, but just the
id on the end of the URL, e.g. 'Ff-qlTlSkc0'.

HTML5
If you set $youtube to kFalse, the $dataname should be a 2-columned list. The first column
should contain URLs to the video files, located somewhere on the internet or the Omnis
App Server, and the second column should state the media type. For example:

182
Video Control

Do iList.$define('VideoURL','VideoType')
Do iList.$add('videos/myVideo.mp4','video/mp4')
Do iList.$add('videos/myVideo.ogv','video/ogg')
Do iList.$add('videos/myVideo.webm','video/webm')
Not all browsers are able to play all video file types, so you should provide the video in
multiple formats and populate the list with the URL to each file and type. When the client
connects, the browser will play the first video file it is able to play from the list.

Flowplayer
Not all browsers support HTML5 video so it is possible to play your video using
Flowplayer which uses Flash. To do this, you should point the $flowplayerurl property to a
Flowplayer object, which you can download from flowplayer.org. You then need to set
$flowplayerline to the line in your list of video files defined in $dataname which contains
the video file that can be played in Flowplayer.

183
Chapter 4—Creating Apps using iOS Client

Chapter 4—Creating Apps


using iOS Client
You can create web and mobile apps using the JavaScript Client that will run on all iOS
devices, including iPhone, iPad, and iPod touch. You can run such apps in the web browser
on the iOS device, or there is a wrapper application that allows you to create standalone
apps that will run on iOS devices. However you may wish to use an entirely native iOS
environment in your iOS mobile app, in which case you can create apps using the Omnis
iOS Client that uses remote forms that are tailored to iOS with a native set of components
for iOS.
To create an app using the native iOS Client, you have to create a remote form and set its
$client property to kClientiOS: you can do this manually or create an iOS remote form
using the New Class>>iOS Form option, or Class Wizards>Remote Forms>Templates
option in the Studio Browser. Once you switch a remote form to iOS, or created an iOS
form using a wizard or template, the Component Store will display the native iOS
components. Once you have placed iOS components on the remote form, it cannot be
converted back to a non-iOS remote form, or used on any other mobile platforms. However
you can add iOS remote forms to the same Omnis application (library) that contains
JavaScript Client based remote forms, and re-use the underlying methods and schema
classes for your iOS remote forms.
Many of the techniques required for building iOS apps, and in particular for creating Omnis
remote forms, are the same as those for creating web and mobile apps using the JavaScript
Client. These techniques are discussed in the previous chapters in this manual, however
there are several features that are unique to the iOS Client support which are covered in this
chapter.

184
Requirements

Requirements
Development Software
You can design remote forms for iOS in the OS X or Windows version of Omnis Studio.
That is, the iOS remote form components are available on both platforms, but you will need
an OS X computer to build your app, and an iOS device to test your app.
To build device and simulator apps, and to run the latest version of Xcode and the SDK
from Apple, you will need OS X 10.6 (Snow Leopard) or above.
You will also need a copy of iTunes to sync your computer with your iOS device.

iOS and supported devices


General references to “iOS” or an “iOS device” usually refer to any device running the
latest version of iOS from Apple. The iOS Client runs on the following devices from Apple
including:
 iPhone®
 iPad™
 iPod touch®
The majority of iOS features available in Omnis will work on all iOS devices, but you will
need to check the specification of individual devices and take into account the different
screen sizes for different devices when designing your remote forms. We strongly urge you
to test your Omnis iOS apps on all the devices you wish to support before deploying your
application.

iOS Developer Program and Distribution


You need to sign up to the Apple iOS Developer Program to obtain the necessary files from
Apple to build your Omnis iOS app. To distribute your iOS app, within your organization or
at a client site, you need to use one of the approved Distribution methods which usually will
allow you to deploy your iOS app to a specified number of devices. Further details about
distribution are available from Apple Inc, and are outlined later in this chapter.

185
Chapter 4—Creating Apps using iOS Client

Creating Remote forms for iOS


Designing remote forms using iOS Client is more-or-less the same as designing standard
remote forms for the web or any other platform in Omnis Studio. However, remote forms
for iOS use the native iOS controls so you need to “switch on” the iOS functionality and
components in the remote form, using the $client remote form property.
If you open an existing remote form, containing standard non-iOS specific components, the
$client property will be grayed out and you will not be able to switch the remote form to an
iOS enabled form. Similarly, an iOS enabled remote form that contains iOS specific
components cannot be switched back to a standard web remote form. For this reason, you
will have to create your iOS remote forms from scratch, since the iOS components and
standard JavaScript components are not interchangeable.
To create a remote form for iOS
 Click on the New Class option in the Studio Browser, scroll down and click on the
iOS Form option

Or you can
 Click on the Class Wizard option, then Remote Form, and then Templates in the
Studio Browser, then select the NewiOSRemoteForm option

Both these options will create a new remote form with the $client property already set to
kClientiOS, plus the $height and $width of the remote form will be set for the different
values of $screensize.
Or you can create a remote form from scratch:
 Create a new remote form using the New Class>>RemoteForm option in the Studio
Browser

 Click on the background of the remote form and in the Property Manager set the $client
property to kClientiOS

In addition, for all of the above options, you will need to create a Remote Task:
 Create a new remote task using the New Class>>RemoteTask option in the Studio
Browser

 Set the $designtaskname property of your remote form to the name of the remote task
you created

When you create or switch a remote form to iOS, the Component Store will display iOS
Components only, under the ‘iOS Components’ group, replacing the standard JavaScript
components, while the remote form design window will display a mobile device image in

186
Creating Remote forms for iOS

the border and the title bar. The iOS components are located in the ioscomp folder in your
Omnis development tree.

The iOS remote form (right) and the Omnis Component Store (left)
showing the twenty or so iOS components
From here on, you will find the layout and visual design of forms for iOS very familiar,
although you set the behavior of components in a different way. You can design your
remote form for iOS in the same way as you would for a standard web-based remote form.
When you open a remote form from the Studio Browser, the Component Store will display
the appropriate components depending on the type of remote form you open, either a remote
form for iOS, or for web browsers, or some other client device.
There are several properties you need to set to specify the behavior, event handling and
other functionality in your iOS remote form; these are listed in the iOS Form Properties and
Methods section below.

187
Chapter 4—Creating Apps using iOS Client

Screen size and form layout


By default, the $screensize property is set to kSSZiOS320x480Portrait, but you can switch
the form to kSSZiOS320x480Landscape to design an alternative layout. This screen size is
supported on the iPhone and iPod touch, while the kSSZiOS768x1024Portrait and
kSSZiOS768x1024Landscape screen sizes are for iPad.
You can design different layouts for the different sizes and orientations and store them in
the same remote form. In other words, each layout uses the same set of fields (and methods)
and the remote form class stores the position of the fields for each screen size/orientation
setting. If you have created a form layout for portrait and landscape and the end user tilts the
device, the layout of the Omnis remote form will change automatically (unless you have set
the portrait only property in the client configuration file).
Window title bar
When designing for different screen sizes you must take account of the iOS title bar. For
example, the screen size of an iPhone is 320 x 480 pixels, but by default the title bar at the
top of the remote form is visible, giving you a possible screen area of 320 x 460 pixels in
portrait mode (the title bar is 20 pixels high). The $designshowmobiletitle remote form
property (under the Appearance tab in the Property Manager) lets you hide or show the
window title on the iOS device.
Form width and height
The $width and $height properties of the form are independent of the current screen size
and orientation, so you can change their values if required, taking into account whether or
not the title bar is visible. The settings of $width and $height for each size/orientation you
set up are stored in the remote form class, along with the position of all fields and other
components for each layout.
You will notice that the area defined by $width and $height is shown as a black area and
indicates the window area visible on the client; the area beyond the visible area is dotted.
You cannot place fields beyond the area defined by the $width and $height properties using
your mouse, although you can set the value of $left and $top for an object (either in the
Property Manager or using the notation) to place any object outside the visible form area.
The default values for the iPhone $screensize setting are $width = 320 and $height = 460
for Portrait mode, and $width = 480 and $height = 300 for Landscape mode. Note this takes
account of the window title bar (which is visible by default) so if you hide the design
window title bar, you’ll need to add 20 pixels to the $height setting.

188
Creating Remote forms for iOS

Client-Side Scripting
You can run certain methods in an iOS based remote form containing calculations, switch
statements, event handling, and other programming constructs.
To enable a method to run on the client, you can Right-click/Cmnd-click on the method and
select the 'Execute on Client' option. If a method contains code that cannot be executed on
the client, Omnis will not allow you to set the 'Execute on Client' option. When you have
enabled a method to run on the client, it will be shown in pink in the method editor.

Debugging Methods
You can debug your methods as you are testing your application on the client device by
setting breakpoints in your code. You can right click on a method line and select the
Breakpoint option to set a breakpoint. When you test the application on your client device
and the breakpoint is encountered in your code, method execution is halted at the breakpoint
and the application is temporarily suspended on the device. At this point, you can switch
back to Omnis on your development computer and step through the live code, inspecting
variable values (Right-click on the variable name anywhere in your code and select the
Variable <varname> option), commenting and uncommenting code (using Ctrl-; and Ctrl-‘),
and so on. When execution has completed in the Omnis method editor, the app will resume
operation on the client device.

189
Chapter 4—Creating Apps using iOS Client

Getting App and Device Information


The $construct() method for remote forms and remote tasks is passed a row variable
parameter, typically called pParams. To use pParams, you must declare it in the parameters
tab of the variables pane for $construct(). The row variable contains the connection
parameters for the remote form and/or remote task and may contain useful information for
your application. The pParams variable has the following columns:

pParams column Description


OmnisPlatform The client platform, e.g. IPHONEU
WebServerUrl The URL of the Web Server through which your iOS client
application connects to the Omnis Server; during development
this will be the IP address of your computer and the port number
of your development copy of Omnis
WebServerScript The path or location of the Omnis Web Server plug-in, usually
located in your cgi-bin or scripts folder, e.g. /cgi-bin/omnisnph-
cgi.exe; during development, this will be /webclient which
means Omnis will use its own built-in web server
OmnisLibrary The name of the Omnis library containing your iOS app
OmnisClass The name of the remote form in your Omnis library
OmnisServer the IP address and port number of the Omnis Server; during
development this will refer to your local computer IP address
and local copy of Omnis Studio
ClientLocale The locale of the client device, e.g. en_GB
MobileScreenWidth The screen width of the current client device
MobileScreenHeight The screen height of the current client device
ClientInfoIphone (iOS forms/tasks only) the iOS device type, e.g. ‘iPod1,1’ for a
first generation iPod
UDID (iOS forms/tasks only) The unique ID of the current iOS device

To view the pParams row variable in design mode, you can set a breakpoint in the
$construct() method and open/test your remote form. Switch to the Omnis debugger, click
on the Parameters pane in the method editor, right-click the pParams variable and select the
‘Variable pParams…’ option. A small popup window will show the columns in the pParams
row variable.

190
Creating Remote forms for iOS

Device type
For iOS remote forms or associated remote tasks, the ClientInfoIphone parameter contains a
character string reporting the iOS device type. The ClientInfoIphone parameter may be one
of the following values (note other device types may be added in future):

ClientInfoIphone Description
i386 iPhone Simulator
iPhone1,1 iPhone
iPhone1,2 3G iPhone
iPhone2,1 3GS iPhone
iPhone3,1 4 iPhone
iPod1,1 1st Generation iPod
iPod2,1 2nd Generation iPod
iPod3,1 3rd Generation iPod

The following code within the form $construct() could be used to return the current device
type:
Calculate deviceType as pParams.ClientInfoIphone

Unique Device Identifier (UDID)


The pParams row variable contains the UDID parameter which is the unique ID of the
current iOS device. The following code within the form $construct() could be used to return
the UDID:
Calculate deviceID as pParams.UDID

191
Chapter 4—Creating Apps using iOS Client

The UDID is useful for identifying individual devices or end users, allowing you to store
some information in your app, such as the configuration of a Tabbar as selected by an end
user, against individual UDIDs.

Component Transparency
All iOS components have the $alpha property which specifies the transparency of the
component, with 0 being completely transparent and 255 being opaque; for most controls,
$alpha is set to 255 by default. Some components also have the $backalpha property which
controls the transparency of the background part of the control, rather than the foreground
elements or data in the control.

Component Icons
Several of the iOS components allow you to use icons to enhance the user experience. This
includes standard pushbuttons (iButton control), as well as the navbar, segmented, tabbar,
and toolbar controls, where you can use an icon to represent a single button, segment, or
tab. You can use an icon from any of the Omnis icon datafiles or the #ICONS system table
in your library, although the latter is advised. The icon for a component or button is
specified in its $iconid property. The icon used must support Alpha values to be displayed
in iOS.
Alpha icons
You must use icons with alpha values in components on iOS remote forms; non-Alpha icons
are not supported for iOS components and will not display correctly. Therefore when you
choose an icon for a component, by clicking on its $iconid property, you must choose an
Alpha compatible icon from an Omnis icon datafile or the #ICONS system table in your
library.

Icon pages
If you use an icon in any iOS component, such as a button or toolbar, you must specify the
icon page name for the icon in the $iconpages property of the remote form. If the icon page
is not listed in the $iconpages property, the icons will not be sent to the client and will not
be displayed. So for example, if you have created your own icon page in #ICONS, you must
check its name to the $iconpages property of the remote form.

Creating your own icons


You can view or edit the icons in one of the Omnis icon datafiles, such as #ICONS, using
the Omnis Icon Editor (open via the Tools>>Icon Editor option). You can add your own
icons using the same tool, which is described in detail in the Omnis Programming manual in
the Library Tools chapter.
To view the Alpha version of an icon page, you select the icon page and click on the large
blue “A” icon on the right hand side on the Icon Editor window, as shown above. Pages that

192
Creating Remote forms for iOS

support Alpha icons are indicated in the Pages list using a small blue “A” icon, as shown
above.
To create a new page, click on “New Icon Page” and make sure you select the “Solid &
Alpha” option. In addition, you must check the boxes for 32x32 and 48x48 if you intend to
add icons for this size.
Importing Images to an Icon file
When importing your own Alpha compatible icons into an Icon Page you must use the
“Paste From File” option to import each Alpha image: you cannot use Copy and Paste from
another image application since the Alpha properties may not be imported successfully
using this method.
To import an Alpha icon, such as a PNG file, place your cursor in the icon field in the Icon
Editor (as above), select Paste from File from the Edit menu, and select the image file you
wish to import. Assign an ID to the icon and save the icon page. Note you can only add an
icon of a particular size if the page supports that size: you can change the icon size support
in the Page Options for a page.

#ICONS and icon pages


In most cases, you are advised not to edit or change the Omnis icon datafiles (Omnispic and
Userpic), since many of the icons in these files are used in the Omnis environment itself.
Rather you are advised to add your own icons to the #ICONS table in your library. You can
open the #ICONS file by double-clicking it in the Studio Browser (it is in the System
Classes folder in your library), or you can open it from within the Icon Editor.
You should also try to limit the number of icon pages used in your iOS app since all icon
pages that contain icons in use (and listed $iconpages) are sent to the client – if many icon
pages are sent to the client, this may create an unnecessary burden on network traffic.
Therefore you may want to add all the icons you need for your app to a single icon page in
your #ICONS table – this will be more efficient and easier to maintain, especially if you are
using the Omnis VCS to manage your library.

Styles
You can assign styles to iOS components based on the Field Styles defined in your library
in the #STYLES system class. The definition for iOS styles are added under the kiOS
section of the #STYLES system class.

Fonts
There is a new system class #IOSWFONTS to handle fonts on iOS devices. A new column
called iOS has been added to the Window font table to allow you to map fonts used in
desktop, web, and mobile forms, including iOS forms. (Note there is no equivalent font
mapping for reports on mobile devices since Omnis reports do not run on mobile devices.)

193
Chapter 4—Creating Apps using iOS Client

Subforms, multiple forms and superclasses


You can add subforms to your remote forms allowing you, in effect, to embed one or more
remote forms into a single remote form or application window. Using a single “main” form
and a number of other forms loaded at runtime into a subform, would allow you to create a
powerful and interactive iOS app.
The subform component is a standard Omnis component, but is available in the ‘iOS
Components’ group in the Component Store. When you have placed the subform on your
remote form, you specify the remote form to appear in the subform in its $classname
property. The subform field can be linked to a navbar or tabbar component using the
$linkedobject property, and depending on what the end-user clicks on, you can switch forms
back and forth accordingly.
You can use multiple forms in the iOS app by switching from the initial form to another
remote form using the $changeform() method.
You can use an empty remote form as the superclass of an iOS remote form and a non-iOS
remote form simultaneously, which allows you to share code between iOS and non-iOS
remote forms.

Paged panes
You can use a Paged pane in your iOS apps to simplify the user interface by placing a small
number of fields and controls on separate panes and switching panes as appropriate.
Like the subform, the paged pane is a standard Omnis component and is available in the
‘iOS Components’ group in the Component Store. The paged pane can also be linked to a
navbar or tabbar component via the $linkedobject property in the navigation component.

Setting form properties


When designing a remote form, you often need to click on the background of the form to set
its properties in the Property Manager. This may be difficult if your form is completely
filled with components and no form background is available to click on, as is often the case
for mobile forms. To select the form in this case, you can use the Field List (right-click
anywhere on the form, open the Field List and check the form name to open the Property
Manager for the form), or if you click on any individual component, then shift-click it to
deselect it, the focus will be returned to the form and its properties will be shown in the
Property Manager.

Client Commands
There are a number of Client Commands you can use in remote forms in the iOS client:
these are executed using the remote form method $clientcommand() which has the general
syntax:

194
Creating Remote forms for iOS

Do $cinst.$clientcommand("commandname",row-variable)

iOS Preferences
The following client commands allow you to save and load end-user data on the client, such
as user preferences.
savepreference
Saves a value (as a character string) as a named preference on the client. You could use this
to store a username or a password for logging onto your app.
Do $cinst.$clientcommand("savepreference",row-variable)
Where row-variable is row(preference name, preference value).
loadpreference
Loads a named preference value from the client preferences into an instance variable.
Do $cinst.$clientcommand("loadpreference",row-variable)
Where row-variable is row(preference name, instance variable name (e.g. a quoted string
containing the name of the variable)).

195
Chapter 4—Creating Apps using iOS Client

iOS Form Properties and Methods


Remote forms for iOS have all the properties and methods of a standard remote form
together with a number of iOS specific properties, as well as some additional events. See the
Omnis Notation Reference manual, or the Omnis Help (press F1), for a full description of
the standard remote form properties and methods not listed here.

iOS Form Properties


Remote forms for iOS have many of the standard properties of a remote form together with
a number of iOS specific properties described here.
$designshowmobiletitle Hides or shows the title bar; if you deploy the form without the
window title bar you need to disable the title bar in the client
configuration; see below; in addition, if you hide the title, you’ll
need to add 20 pixels to the $height of the form
$designtaskname You need to create a remote task and set this property to the
remote task name; this is required to test or run the form
$events You have to enable specific events for the remote form,
otherwise they will not be reported; see the Remote Form
Events section below
$iconpages a comma separated list of icon pages that contain icons you
have used for any components in your remote form; the icon
pages listed here are sent to the client so it is usually more
efficient to add all the icons you need for your iOS app to a
single icon page, which must support Alpha (use the Omnis
Icon Editor to add/edit icon pages); note icons/icon pages can
be stored in #ICONS in the library
$client Set this to kClientiOS to “switch” the remote form to an iOS
compatible form; the form has to be empty to set this property;
the Component Store will display the iOS components
$screensize Specifies the screen size and orientation of the form;
for iPhone and iPod devices this is
kSSZiOS320x480Portrait
kSSZiOS320x480Landscape
for iPad this is
kSSZiOS768x1024Portrait
kSSZiOS768x1024Landscape
Note you also need to set the $height and $width of the form for
each size/orientation that you use in the form

196
iOS Form Properties and Methods

iOS Form Methods


Remote forms for iOS have many of the standard methods of a remote form, as well as a
number of iOS specific methods listed here. For example, $showmessage() can be used to
display an OK message on the client.

Method Description
$beginanimations() $beginanimations(iDuration
[,iCurve=kiOSAnimationCurveEaseInOut, iRepeatCount=0,
bAutoReverse=kFalse]) after calling this method, assignments to
some properties are animated for iDuration milliseconds by
$commitanimations()
$clientcommand() allows you to execute various functions on the iOS client, such as
Yes/No messages and client preferences; see earlier in this chapter
$commitanimations() $commitanimations() animates the relevant property changes that
have occurred after the matching call to $beginanimations()
$redraw() $redraw([bSetcontents=kTrue, bRefresh=kFalse, bBobjs=kFalse,
bExcludeSubForms=kFalse]) redraws remote form; Do
$cinst.$redraw() redraws the form; bSetContents loads the control
data only, bRefresh refreshes the screen, bBobjs redraws
background objects, bExcludeSubForms excludes child controls
which are subforms from bSetcontents (note that they cannot be
excluded from bRefresh due to the way operating system redraws
work)
$senddata() $senddata(iVar1[,iVar2,...]) specifies the instance variables to be
sent to the client after executing an event or $construct on the
server (see remote task class property $enablesenddata for details
of when $senddata applies)
$setcurfield() $setcurfield(vNameOrIdentOrItemref) sets the current field on the
client computer which is useful for data entry forms; when this is
set the focus is placed in the field and on iOS the soft keypad is
initiated; $setcurfield(‘’) removes the focus from the current field
$showmessage() $showmessage(cMessage [,cTitle]) Displays an OK message on the
client computer using the specified cMessage and cTitle
$showurl() $showurl(cURL) Opens the URL in the appropriate application on
the client machine. Note that the Omnis client will immediately
close as a consequence

Remote task methods


Together with the remote form methods, you can use the standard remote task methods in
your iOS apps, including $openform() and $changeform(). For example, the following

197
Chapter 4—Creating Apps using iOS Client

method can be placed behind a button to allow the end user to navigate back to the previous
screen; in this case, the app appears to ‘remember’ the last page and uses the $openform()
method to reopen the last form:
On evClick ;; the last form visited is saved in tLastPage
Do $openform(
$ctask.tLastPage,kFormTransTypeFade,kFormTransDirNone)
Note the $openform() method in this case has three parameters: the name of the form to be
opened, as well as the transition type and direction specified using one of the
kFormTransType.. and kFormTransDir.. constants.
See the Omnis Notation Reference manual or the Omnis Help (press F1) for a full
description of the remote task methods.

iOS Form Events


iOS enabled remote forms report the following events:

The animation has completed


Parameters
evAnimationsComplete
pEventCode The event code

The remote form is about to become visible on the client


Parameters

evFormToTop pEventCode The event code


A kSSZ... constant for the current screen
pScreenSize
size on the client

The orientation of the screen displaying the form has


switched between portrait and landscape
Parameters
evScreenOrientationChanged pEventCode The event code
A kSSZ... constant for the current screen
pScreenSize
size on the client

An existing remote form, contained in a subform that has


$multipleclasses set to kTrue, is about to become visible on
the client
evSubFormToTop
Parameters
pEventCode The event code

198
iOS Form Events

Note Context menu events (evExecuteContextMenu and evOpenContextMenu) are not


available to iOS enabled forms.

Events for iOS Components


The new iOS components have events which can be handled in the same way as with
previous Omnis applications using the On <event> command in the $event() method of the
component. However the event handling methods cannot be run in the client and must
therefore be executed on the Omnis Server. Events for each component are listed in their
respective section in the iOS Components section below.

Event Handling Methods


If you double-click on a component or the form background, the method editor will open
showing the event handling method for the component or form. In most cases, the On
<event> command is added to the method, allowing you to add your own code to handle the
event or multiple events.

Enabling Events
You should remember to enable any events that you wish to report for any individual
component or the remote form itself by enabling the event in the $events property for the
component or form. If an event is not enabled in the $events property, it will not be
reported, even if you have added code to handle the event in the $event method of the
component or form.
To enable an event, select the component or form background, open the Property Manager
(press F6), and click on the $events property to open the event droplist. Select the event you
wish to report from the list of possible events for the component or form.

199
Chapter 4—Creating Apps using iOS Client

iOS Components
There are several new components for remote forms that you can use on iOS devices, and
many of them will be familiar to iPhone/iPad users. When the components are instantiated
on the device itself, the native iOS components are used. The following section lists all the
iOS specific components available for remote forms. In addition, you can use the Paged
Pane and Subform components for iOS forms.

Example Omnis iOS app


This release includes an Omnis iOS app that allows you to play an Anagram based word
game. The example app shows the features of some of the new iOS components, including
how you write Omnis code to control how they behave. Some of the following sections use
code snippets from the example application, which you can further examine in Omnis itself
looking at the comments to navigate around the app.

iActivity Control
iActivity provides an animated image to show some activity on the client, for example,
during a long list calculation or search operation. You assign kTrue to the $animating
property to display the animated image. The $hidewhensstopped property controls if the
control is hidden when animation stops.
The following method can be used to display the activity component, which could be called
or triggered by some event in your application.
Do $cinst.$objs.oActivity.$animating.$assign(kTrue)

Events
The iActivity control has no events.

200
iOS Components

iButton Control
The Button field responds to user clicks reported as the evClick event which can be handled
in the $event() method of the button. The button can display an icon, specified in the
$iconid property, and/or a single line of text. If you use an icon for the button, you must
specify the icon page for the icon in the $iconpages property of the remote form. In
addition, the icon must support Alpha.
The $disabledtextcolor property lets you set the color for the button text when the button is
disabled. Setting it to kColorDefault means $textcolor is used.

Events
evClick a user generated click

The following method can be placed behind a button control, which, in this case, allows the
user to switch to another form.
; code behind Scores button
On evClick
Calculate tLastPage as 'rfTitle' ;; Store this page so we can
come back here from the scores page
Do $ctask.$openform(
'rfScoreboard',kFormTransTypeFlipLeft,kFormTransDirFromLeft)

iDateTime Control
The iDateTime component provides a “spinner” field to allow the end user to select dates
and/or times. You can assign a Date/Time instance variable to the $datename property of
the control to load the date/time selected by the user. The $pickerstyle property specifies the
style of the date time picker. The following image shows the default Date/Time picker style
showing the current date.

Events
evClick a user generated click

201
Chapter 4—Creating Apps using iOS Client

You can create an instance variable in your form called iDate with the Subtype ‘Date Time
D m y’ and assign the variable to the $dataname property of the Datetime control. In the
$construct() method of your form you can use the following method to assign today’s date
to the variable.
Calculate iDate as #D
When the form is opened the Datetime control will display today’s date. When the user
selects a different date, the selected date will be held in the iDate variable. For example, you
could ask the end user to select their date of birth and the following code would calculate
the end user’s age this year.
Calculate lAge as ddiff(kYear,iDate,#D)
Do $cinst.$showmessage(con('You are ',lAge,' years old this year.'))

iImageView Control
The iImageView comp can be used to display an image, either a TIFF, JPEG, GIF, PNG,
BMP, ICO, CUR, or XBM image. The control supports the drag and pinch gestures which
allow the end user to zoom into and move the image within the picture control.
The $dataname of the control must be set to a Binary variable containing the image data;
you cannot use an Omnis picture variable. Alternatively, the variable in $dataname can be
an integer which references an icon id to display an icon from one of the Omnis icon
datafiles or #ICONS in your library.
The iImageView control has the following properties:

Property Description
$getimagedata (runtime only) assign a kiImageSource... constant to this property to
instruct the client to prompt the user for an image from the specified
source, and send an evImageSelected event with the image data in
pImageData
$getrawimage (runtime only) assign a kiImageSource... constant to this property to
instruct the client to prompt the user for an image from the specified
source, and use the selected image to set $rawimage
$imagealign specifies where the image will be positioned when $noscale is kTrue and
the image entirely fits in the bounds of the control
$maxzoom The maximum zoom factor that can be applied to the current image by
the pinch gesture (1-16)
$rawimage if set, this raw PNG image is used instead of the databound object

202
iOS Components

Events
evImageSelected Sent to the control when the action requested by assigning
$getimagedata completes; the pImageData parameter contains
the binary image data selected by the user

The following method can be placed behind a toolbar control that allows the end user to
select images from the photo or camera library on their device. The $getimagedata property
must be assigned at runtime and can be used with either kiImageSourcePhotoLibrary or
kiImageSourceCameraRoll to specify the image source.
; oPic is the image control, its dataname is iPic which is a binary
variable
On evClick
Switch pToolbarButton ;; contains the tab number clicked
Case 1
Do $cinst.$objs.oPic.$getimagedata.$assign(
kiImageSourcePhotoLibrary) Returns #F
Case 2
Do $cinst.$objs.oPic.$getimagedata.$assign(
kiImageSourceCameraRoll) Returns #F
End Switch
Do $cinst.$redraw()
The event method behind the image control loads the image held in pImageData and assigns
it to the iPic binary variable behind the image control.
On evImageSelected
Calculate iPic as pImageData
Do $cinst.$redraw()

203
Chapter 4—Creating Apps using iOS Client

iLabel Control
The iLabel control provides a simple text label.

Property Description
$adjustsfontsizetofitwidth if true, and $numberoflines is one, the object reduces the font
size in order to fit the text string into its bounding rectangle -
the property $minimumfontsize specifies the smallest value to
which the font size can be reduced
$linebreakmode a kiOSLineBreakMode... constant that specifies how lines
break when drawing text
$minimumfontsize the smallest value to which the font size can be reduced when
$adjustsfontsizetofitwidth is true and $numberoflines is one
$numberoflines the number of lines to be used to render the text. Zero means
use as many as necessary

Events
The iLabel control has no events.

iMap Control
The iMap control provides a Google map interface to allow the end user to search for
locations or for you to show locations in your app. The end user can drag and pinch the map
image to change location and zoom of the map. Using the map control together with other
controls, such as the table control which could list a number of locations, you can create
very interactive location based Omnis apps.
You can display the map with a specified location, adding your own annotation pins and/or
popup location markers. The iMap control generates a number of events in response to the
end user touching the map or markers.

204
iOS Components

The iMap control has the following properties:

Property Description
$addannotation Adds pin annotations to the map. Assign a list with columns
(nLatitude, nLongitude, cTitle [,cDesc]). nLatitude and
nLongitude are degrees where positive numbers are North and
East, or negative numbers are South and West. cTitle is the title
for the marker with cDesc the optional description
$centermap Centers the map to the location. Assign a row with columns
(nLatitude, nLongitude, nSpan). nLatitude and nLongitude are
degrees where positive numbers are North and East or negative
numbers are South and West. nSpan is the number of degrees of
latitude and longitude to display
$desiredaccuracy A kiMapLocationAccuracy... constant which indicates the level
of accuracy you require for evHeadingChanged and
evLocationChanged events. Greater accuracy requires more time
and power
$enableheadingevents If true, heading events are sent from the device to the server (the
device must support heading events)
$enablelocationevents If true, location events are sent from the device to the server (the
device must support location events)
$headingfilter The minimum angular change (measured in degrees) required to
generate new heading events. Set this to zero to indicate no
filtering of evHeadingChanged events
$locationfilter The minimum distance (measured in meters) the device must
move laterally before another evLocationChanged event is
generated. Set this to zero to indicate no filtering of
evLocationChanged events
$mapcanscroll If true, the map can scroll
$mapcanzoom If true, the map can zoom
$maptype The type of map, a constant: kiMapTypeStandard,
kiMapTypeSatellite or kiMapTypeHybrid
$nexttouchevent If kTrue, the next touch on the map sends an evLocationTouch
event. pLongitude and pLatitude are sent as parameters
$showannotation Assign an annotation number (a 1-based index into the added
annotations) to show the callout bubble for the annotation; the
number usually relates to the order of the list you may have
assigned to $addannotation. If the annotation is not currently
visible, assigning this property has no effect
$showuserlocation If true, the map shows the users location

205
Chapter 4—Creating Apps using iOS Client

Events
The iMap control generates a number of events which you can detect in your event handling
methods for the control. Here is a summary of the events; the next section provides full
details and parameters for each event.
 evAnnotationTouched
Sent to the control when an annotation is touched
 evLocationChanged
Sent to the control when the location changes or when $enablelocationevents changes
value to kTrue. You can use $locationfilter to restrict the generation of
evLocationChanged events
 evHeadingChanged
Sent to the control when the heading changes or when $enableheadingevents changes
value to kTrue. You can use $headingfilter to restrict the generation of
evHeadingChanged events
 evLocationOrHeadingError
Sent to the control when an error occurs while trying to get location or heading data
 evLocationTouch
Sent to the control when $nexttouchevent is kTrue. After the event $nexttouchevent
will be set to kFalse

206
iOS Components

Event Description and parameters

Sent to the control when an annotation is touched


Parameters
evAnnotationTouched
pEventCode The event code
pAnnotationRow The row number of the annotation touched

Sent to the control when the location changes or when


$enablelocationevents changes value to kTrue. You can use
$locationfilter to restrict the generation of evLocationChanged
events
Parameters

pEventCode The event code


The latitude in degrees (positive for
pLatitude
North or negative for South)
The longitude in degrees (positive for
pLongitude
East or negative for West)
pAltitude The altitude in meters
The radius of uncertainty for the location,
pHorizontalAccuracy
measured in meters
evLocationChanged
The accuracy of the altitude value in
meters. The value in the altitude property
could be plus or minus the value
pVerticalAccuracy
indicated by this property. A negative
value indicates that the altitude value is
invalid
The instantaneous speed of the device in
pSpeed
meters per second
The direction in which the device is
travelling. Course values are measured in
degrees starting at zero for due north and
pCourse
continuing clockwise around the
compass. A negative value indicates that
the course value is invalid
pDescription A text string representing the location or

207
Chapter 4—Creating Apps using iOS Client

Event Description and parameters


heading data

Sent to the control when the heading changes or when


$enableheadingevents changes value to kTrue. You can use
$headingfilter to restrict the generation of evHeadingChanged
events
Parameters
pEventCode The event code
The heading (measured in degrees) relative
pMagneticHeading
to magnetic North
evHeadingChanged The heading (measured in degrees) relative
pTrueHeading
to true North
The maximum deviation (measured in
degrees) between the reported heading and
pHeadingAccuracy the true geomagnetic heading. A negative
value means that the reported heading is
invalid
A text string representing the location or
pDescription
heading data

Sent to the control when an error occurs while trying to get


location or heading data
Parameters
pEventCode The event code
The system error code for the problem
evLocationOr encountered when getting location or
HeadingError heading data. If the user has denied access
pSystemErrorCode
to the information, the control sets
$enablelocationevents and
$enableheadingevents to kFalse
The system error text for the problem
pSystemErrorText encountered when getting location or
heading data

Sent to the control when $nexttouchevent is kTrue. After the event


evLocationTouch $nexttouchevent will be set to kFalse
Parameters

208
iOS Components

Event Description and parameters

pEventCode The event code


The latitude in degrees (positive for North or
pLatitude
negative for South)
The longitude in degrees (positive for East or
pLongitude
negative for West)

iMap example
Consider an example app that contains an
iMap control and a table containing a
number of locations, plus a toolbar for
adding markers. The contents of the table
list could be built on the fly or from a
database, which is the case in this example.
The following code samples show how you
can build the location list and show each
location with an annotation pin.
The first task would be to create a database
session, logon to the database and build the
list of locations. In this case the locations
are held in an Omnis database located in the
same folder as the app, and standard SQL
code is used to build the list based on the
Markers table.
; $getAnnotation class method
; Instance var: iAnnList (List)
; oMap is the map control on the form
Do iAnnList.$clear()
Do $cinst.$objs.oMap.$addannotation.$assign('')
Do iStmt.$execdirect('SELECT * FROM Markers') Returns #F
Do iStmt.$fetch(iAnnList,kFetchAll)
Do $cinst.$objs.oMap.$addannotation.$assign(iAnnList)
Do $cinst.$redraw()

209
Chapter 4—Creating Apps using iOS Client

In this example, the iAnnList list variable has the following data.

The list of annotation data is assigned to the map control by assigning it to its
$addannotation property. The data list must contain columns for the Latitude and Longitude
of the locations, a Title for the location marker, and an optional description. In our example
there is a fourth column containing the type of accessory marker to be displayed in the
location list on the form. The Latitude and Longitude parameters are specified as the
number of degrees where positive numbers are North and East, and negative numbers are
South and West.
In this example, the remote form startup code centers the map and displays the second pane
of a paged pane control showing the table of locations. The instance variable iCurrentPos is
a Row based on the schema table in our database (set the subtype of the variable to the
name of the schema class), with the columns Latitude, Longitude, and Span. The value of
iCurrentPos is hard coded in this case and assigned to the $centermap property of the map
control.
Do iCurrentPos.$assigncols(52.3,1.65,4)
Do $cinst.$objs.oMap.$centermap.$assign(iCurrentPos)
Calculate $cinst.$objs.oPane.$currentpage as 2
Do $cinst.$redraw()

210
iOS Components

In this example, event handling code has been


placed behind the table control, so when the end
user taps the list or the accessory icon either the
corresponding marker is displayed or the map is
centered on the chosen location. Here is the code
behind the table control.
On evTableRowAccessoryClicked
Do iCurrentPos.$assigncols(
iAnnList.[pRow].Latitude,
iAnnList.[pRow].Longitude,
iSpan)
Do
$cinst.$objs.oMap.$centermap.$assi
gn(
iCurrentPos)
Do $cinst.$redraw()
The evTableRowAccessoryClicked event returns the row number of the Accessory icon the
user has tapped in pRow which can be used to get the Latitude and Longitude from the list
of annotations in iAnnList. The selected location in iCurrentPos is then assigned to the
$centermap property and the map is centered automatically on the location.
The other event handling method behind the table is called when the end user taps a line in
the table.
On evTableRowClicked
Do $cinst.$objs.oMap.$showannotation.$assign(pRow)
The evTableRowClicked event returns the row number the user has tapped in pRow which
can be assigned directly to the $showannotation property of the map control.
You can add location markers to the map using the evLocationTouch event to detect where
the end user has tapped and adding the location returned in the event to the list of
annotations. In our example, a button is used to enable the touch event for the map control
and two fields are provided to allow the end user to enter a name and description. Here is
the method behind the ‘Place Marker’ button:
On evClick
Calculate $cinst.$objs.oMap.$nexttouchevent as kTrue
Calculate $cinst.$objs.oPane.$objs.bCancel.$enabled as kTrue
Calculate $cobj.$enabled as kFalse
Do $cinst.$setcurfield('eName')
The method enables the touch event, enables the cancel buttons, disables itself, and sets the
edit focus in the name field. Doing the latter will open the soft keyboard prompting the end
user to enter a name. When the end user has entered a name and description for the marker,
they can tap the device which will now trigger the evLocationTouch event. The event
handling method is placed behind the map control and has the following code:

211
Chapter 4—Creating Apps using iOS Client

On evLocationTouch
Do iAnnList.$add(
pLatitude,pLongitude,iName,
iDesc,kiTableCellAccessoryDisclosureButton)
Do iStmt.$execdirect('INSERT INTO Markers
VALUES(@[pLatitude],@[pLongitude],@[iName],@[iDesc],2)')
Returns #F
Do $cinst.$getAnnotation() ;; builds the annotation list
The evLocationTouch event returns the selected location in the pLatitude and pLongitude
parameters which can be used to add the location to the list and insert the new location into
the database. The $getAnnotation() class method is called to rebuild the annotation list and
redraw the form including the new location marker.

iMultiLineEdit Control
The iMultiLineEdit control is a field for displaying multiple lines of text from the variable
specified in $dataname. The $autocapital property controls the capitalization of entered text,
while $autocorrect specifies if auto correction is used.
See the section on the iSingleLineEdit Control for further information about using edit
fields in remote forms.

Events
evAfter Sent to a field when it ceases to be the target field
evBefore Sent to a field when it becomes the target field

212
iOS Components

iNavigationbar Control
The iNavigationbar component provides a standard iOS navigation bar which end users can
use to navigate to different parts of your application. The navigation bar has a main title in
the middle of the control and can have a left and/or right button which respond to user
clicks.

Property Description
$initiallefticonid if this is not zero, and $initiallefttext is empty, the first navigation
bar item has a button on the left hand side, displaying this icon
$initiallefttext if this is not empty, the first navigation bar item has a button on the
left hand side, displaying this text
$initiallefttype specifies the type of button displayed on the left hand side of the
first navigation bar item
$initialrighticonid if set to kinavigationbarbuttontypeimage, the first navigation bar
item has a button on the right hand side, displaying this icon
$initialrighttext if set to kinavigationbarbuttontypetext, the first navigation bar item
has a button on the right hand side, displaying this text
$initialrighttype specifies the type of button displayed on the right hand side of the
first navigation bar item
$initialtitle is the initial title displayed on the navigation bar
$lefthidden if true, the left hand (back) button is hidden for the current
navigation bar stack item
$linkedobject the name of a subform or paged pane object on the current remote
form, used in conjunction with the $push property of the navbar. If
you use a subform, $multipleclasses for the subform must be ktrue
$navigationbarstyle specifies the appearance of the navigation bar
$push allows you to assign a 2-4 column row to the object referenced in
$linkedobject, col1 is the page number of a paged pane or classname
of the linked subform, col2 is the title for pushed item, col3 is the
text or icon id for right button (pass empty for no right button), and
col4 can be non-zero to hide the left button
$righticonid if this is not zero, and $righttext is empty, the current navigation bar
item has a button on the right hand side, displaying this icon
$righttext if this is not empty, the current navigation bar item has a button on
the right hand side, displaying this text
$righttype specifies the type of button displayed on the right hand side of the
current navigation bar item
$tintcolor the color of the navigation bar

213
Chapter 4—Creating Apps using iOS Client

Property Description
$title the title for the current navigation bar stack item

If you use icons in your navbar you must specify the icon page for the icon(s) in the
$iconpages property of the remote form.
Events
evClickInitialLeftButton The initial Left Button has been clicked
evClickRightButton The Right Button has been clicked

Example Navigation bar

Consider the Help form in the Anagrams example application. The Help form has a navbar
which allows the end user to select different help topics. The navbar itself is linked to a
paged pane field which displays the help topics on individual panes. The $linkedobject
property of the navbar specifies the name of the paged pane, in this case, called oPane.
The $construct() method of the Help form builds a list containing information about the
pages of the tab pane, including the arguments needed for the $push property of the navbar.
Do iPageList.$define(Page,Title,Rightbtn,HideLeft)
Do iPageList.$add(1,'Info','Manual Play',1)
Do iPageList.$add(2,'Manual Play','Anagram',0)
Do iPageList.$add(3,'Anagram','',0)
The navbar control itself is placed across the top of the form and its various properties
under the General and Appearance tabs in the Property Manager are set, as follows:

$events set to receive evClickRightButton events


$linkedobject set to oPane, the name of the paged pane
$push can only be assigned at runtime; see below
$initialtitle set to “Main”
$initialrighttype set to kiNavigationbarButtonTypeText
$initialrighttext set to “Manual Play”

The $event() method traps a user click on the button on the navbar, and has the following
event code:
On evClickRightButton
Do $cinst.$pushPage(iPage+1) ;; page number is incremented
and passed to the $pushPage method

214
iOS Components

The $pushPage method is a class method and gets the details for the new page from
iPageList (built in the $construct of the form, as above) and passes the details to the $push
property of the navbar.
; pPage receives the page number
; lRow is local var of Row type
; iPage stores the current page number
Calculate lRow as iPageList.[pPage]
Do $cinst.$objs.oNav.$push.$assign(lRow)
Calculate iPage as pPage
The effect of the $push property is to change the pane number in the paged pane control
specified in the $linkedobject property; in the case of the example app, an initial click by
the end user will display the second pane in the Help form.

iPage Control
The iPage control links to a Paged pane on the remote form and allows the end user to
change the current page in the linked paged pane by flicking or swiping over the page
control. The paged pane to link to the iPage control is specified in the $linkedobject
property.

The iPage control also gives the end user a visual clue as to the current selected pane in the
linked page pane object, since the highlighted dot in the control changes to reflect the
current page in the linked paged pane (the screenshot shows page 3 selected).

Property Description
$currentpage the current page number
$linkedobject the name of a paged pane object on the current remote form that
links to the iPage control
$pagecount the number of pages

Events
evPageChanged The page has changed;
pValue = the new page

Paged Pane Control


The standard Omnis paged pane can be used in iOS-enabled remote forms. The paged pane
provides a very convenient method to show alternative fields or controls, or to break down

215
Chapter 4—Creating Apps using iOS Client

an entry form into more manageable parts whereby each pane contains a small number of
fields.
Several of the other iOS controls can link to a paged pane, by setting the control’s
$linkedobject property to the name of the paged pane. You can link a paged pane to the
iNavigationbar, iPage, and iTabbar controls.
In addition to the standard paged pane properties, you can set $effect to select different
border effects for the control, and by setting $scrolltochangepage to kTrue the end user is
able to can change the current page simply by flicking or wiping horizontally across the
paged pane.

iProgress Control
The iProgress control lets you indicate the progress of an operation such as a complex
search, calculation, or loop. The $progressstyle sets the style of the progress bar. The $min
and $max properties specify the maximum and minimum values for the progress range,
while $val is the current value in the progress range (between $min and $max).

Events
evClick a user generated click

The following method could be placed behind a button to trigger the progress control, but
could equally be triggered by another event in your code.
; the $min and $max of ‘progress’ are set to 0 and 1000
On evClick
For count from 1 to 1000 step 1
Do $cinst.$objs.progress.$val.$assign(count)
End For
Do $cinst.$showmessage('Done!')

216
iOS Components

iSearchBar Control
The iSearchBar component provides an entry field in the search bar style. The text entered
by the user is held in the variable specified in $dataname and can be used as the source for a
search.

Property Description
$autocapital controls the capitalization of text entered
$autocorrect controls how the iOS device corrects the entered text
$contenttip the text displayed in the field when it is empty, to help the user
understand what content should be entered
$dataname the data name of the object
$prompt the text shown above search bar; increase the height of the searchbar
control itself to make the text visible
$searchbarstyle sets the visual style of the searchbar (only applies if $tintcolor is
kColorDefault)
$showsbookmark enables the bookmark icon in the search bar; note you can detect a
click on the bookmark with evBookmarkClick which must be enabled
in the $events property
$showscancel enables the cancel button in the search bar
$tintcolor the color of the search bar

Events
evAfter Sent to a field when it ceases to be the target field
evBefore Sent to a field when it becomes the target field
evBookmarkClick The user has pressed the bookmark button
evClick a user generated click

The following Searchbar control works in conjunction with a Webview control to allow the
end user to browse web pages within your Omnis application. The $dataname of the
searchbar is set to iUrl, a simple Character instance variable.

217
Chapter 4—Creating Apps using iOS Client

The code in the $event() method for the Searchbar assigns the contents of the control held
in iUrl, along with a Webview command constant, to a row variable which is itself assigned
to the $execcommand property of the Webview control.
On evClick
Do lCommand.$define('','')
Calculate lCommand.1 as kiWebViewCommandLoadPage
Calculate lCommand.2 as iUrl ;; the text in the Searchbar
Do $cinst.$objs.oBrowser.$execcommand.$assign(lCommand)
Do $cinst.$setcurfield('')
Do $cinst.$redraw()

218
iOS Components

iSegmented Control
The iSegmented component is similar to the tabbar in so far as it provides a number of
buttons or segments for the user to click. You can detect which segment the user has clicked
on and execute the appropriate code.

Property Description
$currentsegment the number (1 - $segmentcount) of the current segment (this
specifies the segment affected by segment specific properties);
$movesegment moves the segment by assigning a number in the range 1 to
$segmentcount, which changes $currentsegment to the assigned
number (not assignable in class notation)
$segmentcount the number of segments (must be at least one);
$segmentenabled if true, the segment is enabled and generates a click event when
the user presses it;
$segmenticonid the icon displayed on the current segment, if $segmenttext is not
empty, $segmenticonid is ignored;
$segmentlist a list containing segment-specific properties, one line per
segment;
$segmentstyle specifies the appearance of the control;
$segmenttext the text displayed on the current segment, if this is not empty,
$segmenticonid is ignored;
$segmentwidth the width of the segment in pixels, otherwise if zero, the control
automatically sizes the segment;
$selectedsegment the number (1 - $segmentcount) of the currently selected
segment, or zero if no segment is selected (only relevant if
$showselectedsegment is kTrue);
$showselectedsegment if true, the control highlights the selected segment
($selectedsegment specifies the highlighted segment);
$tintcolor the color of the control (only applies if $segmentstyle is
kiSegmentStyleBar and $tintcolor is not kColorDefault);

If you use icons in the segmented control you must specify the icon page for the icon(s) in
the $iconpages property of the remote form.
Events
evClick a user generated click;
pSegment = the number of the segment clicked

219
Chapter 4—Creating Apps using iOS Client

The following Segmented control has been configured to work in conjunction with a
Webview control to provide a web browser in a remote form.

The Segmented control has the following properties set:

$event evClick is enabled


$segmentstyle set to kiSegmentStyleBar
$selectedsegment set to 0 for no selection
$segmentcount is 4
$currentsegment you have to set this to 1 to 4 to assign an icon or text to
each segment; in the above example, icons 3002, 3003,
1614, and text ‘HOME’ are used respectively

See the iWebView section for the example code used behind such a Segmented control.

220
iOS Components

iSingleLineEdit Control
The SingleLine Edit Field is for displaying or receiving a single line of text from the
variable specified in $dataname. In most cases the variable will be character based, but the
single-line edit can display numeric data; see below. Like all remote form fields, the
variable specified in $dataname for the edit field must be an instance variable.

Property Description
$adjustsfontsizetofitwidth if true, the object reduces the font size in order to fit the text
string into its bounding rectangle, while $minimumfontsize is
the smallest value to which the font size can be reduced when
$adjustsfontsizetofitwidth is true
$autocapital controls the capitalization of text entered
$autocorrect controls how the iOS device corrects the entered text
$clearbuttonmode controls when the clear button is displayed in the field which
allows the end user to clear any data in the field; this is one of
the kiOSViewMode… constants
$contenttip the text displayed in the field when it is empty, to help the
user understand what content should be entered
$effect The effect or border style of the edit field; for iOS this is one
of the kiOSBorder… constants
$dataname the data name of the object
$securetextentry if true, each character is hidden which is useful for password
text entry

Events
Single line edit fields do not report any special events other than the standard evAfter,
evBefore, and evClick.

evAfter Sent to a field when it ceases to be the target field


evBefore Sent to a field when it becomes the target field
evClick a user generated click

221
Chapter 4—Creating Apps using iOS Client

Using Edit fields with the keyboard


When a remote form containing edit fields is
opened on the client, the edit focus is placed
in the first available edit field and the built-
in alpha-numeric keyboard is opened
automatically ready for data entry. The end
user can use all the editing features they
would expect on an iOS device within an
Omnis entry field, such as clicking and/or
dragging to select text, copying & pasting
text, predictive text, and so on.
For a single line edit field, you can set the
$clearbuttonmode property to
kiOSViewModeWhileEditing to enable the
Cancel button during editing to allow the
end user to clear the contents of the field (as
shown).

Setting the edit focus


The edit focus is placed in the first available edit field according to the values of the $order
property for each field in the form. You can specify that a field is the first edit field by
changing its $order property to 1; note the $order values of the other fields in the form are
reordered accordingly when you change the $order for a field. Alternatively, you can use
the $setcurfield() method to specify which edit field gets the focus; this can be done in the
$construct() of the form to put the edit focus in a particular field when the form is opened.
For example, the following method will put the edit focus in the FirstName field and open
the keyboard for data entry when the form is opened.
; $construct of the form
; $cinst is the remote form instance
Do $cinst.$setcurfield('FirstName')
You can cancel the edit focus, and by doing so close the soft keyboard, by setting the
current field in the form to null. To do this you can use the following method:
Do $cinst.$setcurfield('')
When the end user taps the ‘Done’ button in the keyboard an evClick event is generated, so
you can use the above code in the $event() method for a field to cancel the edit focus and
close the keyboard.
Displaying Numbers
Single line edit fields can display number variables as well as character based data. If an
integer variable is assigned to an edit field (in $dataname), the field will use a numeric
keyboard when it gets the edit focus.

222
iOS Components

If a numeric variable allows decimal points, such as Number 2dp, the standard keyboard is
opened, but on the numeric page, and will only allow the input of numbers and the decimal
point character (in this case, no other characters can be inserted).

iSlider Control
The Slider is a convenient and intuitive way for the end user to select a value or setting,
such as a numeric value or percentage, since the position of the button corresponds to the
current value of the variable assigned to the control.

The $sliderstyle property sets the style of the slider bar. The $min and $max properties
specify the minimum and maximum values for the slider range, while $val is the current
value in the slider range (between $min and $max). When the end user drags the thumb
button and the slider is changed, the evSliderChanged event is triggered with pValue
containing the current value.

Events
evSliderChanged The slider value has changed;
with pValue = the new value

The following method can be placed behind a slider control to set the $alpha property of an
image field called oPic.
On evSliderChanged
Calculate $cinst.$objs.oPic.$alpha as pValue

iSwitch Control
The Switch component provides an ON / OFF button. The instance variable specified in
$dataname will be set to value=1when the end user pushes the switch on, and set to zero
when the switch is turned off.

Events
evClick a user generated click

223
Chapter 4—Creating Apps using iOS Client

The following method can be placed behind the Switch component to trap whether the
switch is on or off and run some code as appropriate.
On evClick
Switch iSwitch ;; iSwitch (Short int)
Case 1 ;; switch is on
; Do something
Default ;; switch is off
; Do something else
End Switch

iTabbar Control
The Tabbar component allows the user to select a tab which can correspond to a specific
option in your application. You can specify the number of buttons on the tabbar, while for
each button you can use one of the standard types or specify your own. The tabbar can be
linked to a paged pane or subform so when different buttons are clicked the pane or subform
can be changed accordingly. You can also allow the end user to reconfigure or reorder the
buttons in the tabbar.

Property Description
$config the tabbar configuration specified by the user, which allows you to store
the configuration set by the user (using the value of the pConfig event
parameter in the evConfigDone event)
$currentobject the number of the current button in the range 1 - $objectcount; setting
this in design mode allows you to set the button specific properties for
each button
$linkedobject name of a subform or paged pane to link to the tabbar. If this is not
empty, when the user selects an object, it sets $classname or
$currentpage for the linked object to $objectlink instead of generating a
click event
$moveobject moves the button by assigning a number in the range 1 to $objectcount,
which changes $currentobject to the assigned number; this provides a
convenient method for you to move buttons (in design mode only)
$objectbadge the badge text used to mark the item; this can be useful for adding
information to the button to help the user make a selection
$objectcount the number of buttons on the tabbar (this must be at least one)
$objectenabled if true, the button is enabled and generates a click event when pressed
$objectflags a combination of the kiTabbarButtonFlagInitiallyVisible and
kiTabbarButtonFlagAlways constants that control when the tabbar
button is visible in its initial state prior to the user configuring the tabbar
$objecticonid the icon displayed on the current button (only significant if $objecttype

224
iOS Components

Property Description
is kiTabbarButtonTypeUser)
$objectlink When the user selects this object, the object sets $classname or
$currentpage for the object to $objectlink; only significant if
$linkedobject is not empty
$objecttext the text displayed on the current button (only significant if $objecttype is
kiTabbarButtonTypeUser)
$objecttype the type of the button specified by one of the kiTabbarButtonType..
constants; to define your own tabbar button use
kiTabbarButtonTypeUser and set $objecttext and $objecticonid
$openconfig set this to kTrue to open a dialog for the user to customize or reorder the
buttons in the tabbar. On completion, evConfigDone is sent with the new
configuration in pConfig and invisible items in pMoreList. Changes to
screen orientation are disabled while the dialog is displayed
$selectedobject the number (1 - $objectcount) of the currently selected button, or zero if
no button is selected

Events
evClick a user generated click;
pTabbarButton = the number of the tabbar button clicked
evConfigDone pConfig = the new configuration of the tabbar specified by the user
which is a row containing button IDs in the new order
pMoreList = 2 column list; col1 is the icon ID, col2 the text

Button Icons
For most tabbar buttons you can use the standard button types available in $objecttype and
specified using one of the kiTabbarButtonType.. constants. You can however specify your
own tabbar buttons using the kiTabbarButtonTypeUser object type. In this case, the
$objecttext and $objecticonid properties are enabled which allow you to define your own
button, including your own text and icon. Note that you must use icons that include Alpha
properties for tabbar buttons, since the alpha values in the icon image are used to render the
button image, and in this special case, the color values in the image are ignored.
If you use icons from an icon datafile or #ICONS in your tabbar, you must specify the icon
page for the icon(s) in the $iconpages property of the remote form.
Tabbar position and size
In addition to setting the tabbar specific properties, you can set the $edgefloat property of
the control to kEFposnTopToolbar or kEFposnBottomToolbar to position and “fit” the
control to the top or bottom of the form, respectively.

225
Chapter 4—Creating Apps using iOS Client

Most of the standard tabbar buttons require a minimum height to display the icon and text
correctly. In this case, you will find that you cannot resize the height of the tabbar below 49
pixels, although you can set $height of the control if you need to specify a height.
Tabbar configuration
When you create the tabbar control in development mode, the configuration or order of the
tabbar buttons is stored in the object, but at runtime you can allow the end user to change
the order of the buttons. By setting the $openconfig property to kTrue, you can open a
configuration dialog on the client, allowing the end user to drag the buttons to reorder them.
The following method could be placed behind a standard button to open the configuration
dialog:
On evClick
Do $cinst.$objs.oTabBar.$openconfig.$assign(kTrue)
When the end user has finished reordering the tabbar and clicked the Done button, the
evConfigDone event is sent to the tabbar with the new configuration in pConfig, which is a
comma-separated row containing the button numbers in the new order.
You can save the new configuration into the $config of the tabbar using the following
method placed behind the tabbar itself:
On evConfigDone
Calculate $cinst.$objs.oTabBar.$config as pConfig
If you wish to store the new configuration permanently you will need to store the new
values returned in pConfig onto the server, together with the ID of the device, and load it
when the individual client device reconnects. See the Getting App and Device Information
section earlier in this document.

Example Tabbar
Consider the Scoreboard remote form in the Anagrams example application. A tabbar is
used to allow the end user to select which set of scores to display in the scoreboard.

The $objectcount property is set to 7 to display seven tabs, with a text value for each tab
specified in $objecttext; you have to set $currentobject to edit the properties of each tab.
The $objecttype property controls the type or style of each button in the tabbar, and in this
case each tab is set to kiTabbarButtonTypeUser which means the button is user defined.
Many of the other types provide a predetermined button or icon for specific purposes.

226
iOS Components

The tabbar reports an evClick with pTabbarButton containing the number of the clicked tab
which you can use to trigger an action depending on the code in the $event() method for the
control. For example, in the Anagrams example app the tab number is used to return a list of
scores for the selected number of letters.
; contains instance vars iList (list), iPath (Char)
; iSess (Object based on OMSQLSESS), iStmt (Object no subtype)
On evClick
Do iList.$clear()
Do iSess.$logon(iPath,'','','ScoreSess') Returns #F
Calculate lLetters as pTabbarButton+2
; pTabbarButton +2 since the tabbar starts on ‘3 letters’
Do iStmt.$execdirect('Select * From Scores where
Letters=@[lLetters]') Returns #F
Do iStmt.$fetch(iList,kFetchAll)
Do iSess.$logoff()
Do iList.$sort($ref.RealTime,kFalse) Returns #F ;; Sort into
time order although the time is not displayed
Do $cinst.$redraw()
Note that when the data is fetched from the database, in this case an Omnis datafile, the
form needs to be redrawn using the $redraw() method, which is a method of a remote form
instance, referenced using $cinst. See below for details about the table control used on the
scoreboard remote form.

227
Chapter 4—Creating Apps using iOS Client

iTable Control
As well as providing a method for displaying lists of data, the iTable component can be
used for the main interface of your iOS app, since it can provide a hierarchical set of
options, complete with graphical symbols and icons, for users to navigate their way around
your application. Many iOS apps use a Table based interface in preference to the menu &
button based approach found in traditional desktop and web applications.

Property Description
$altcolor1 & $altcolor2 the alternating row colors of the table
$dataname the list variable name for the content of the table
$grouped set to kTrue to enable grouped mode
$iconcolumn the column number of the list column containing the icon id
of the icon to display for each row, or zero if icons are not
required
$label1bold / $label2bold sets label 1 or 2 to bold
$label1column the column number of the list column containing the first text
string to display for each row
$label1size / $label2size the font size of label 1 or 2
$label1textcolor / the text color of label 1 or 2
$label2textcolor
$label2column the column number of the list column containing the second
text string to display for each row, or zero if a second text
string is not required
$rowflagscolumn the column number of the list column containing flags which
control various options for the row, with each flag’s column
value a kiTableCellAccessory... constant, or zero if
accessories are not required
$rowht the default height of a row
$tablestyle the style of the table, a kiTableStyle... constant

If you use icons in the table you must specify the icon page for the icon(s) in the $iconpages
property of the remote form.
The iTable component is able to display both standard “flat” lists and “grouped” lists.
Standard flat lists are defined as you would any other list, containing columns and simple
rows of data. In this case, you assign the flat list to the $dataname of the iTable component
and define how the data is interpreted by setting its various properties, including $tablestyle
to specify how the list determines the structure of the table (one of the kiTableStyle...
constants), $iconcolumn to specify the icon, $label1column and $label2column for column
labels, and $rowflagscolumn.

228
iOS Components

Events
evTableRowAccessoryClicked pRow = a reference to the list row clicked
pSection
evTableRowClicked pRow = a reference to the list row clicked
pSection

Consider the Scoreboard remote form in the Anagrams example application. A table is used
to display the scores for any given number of letters, selected by the user clicking on a
tabbar above the table.

The iTable control itself has no methods behind it and it does not trap events since the data
is built by the end user clicking on the tabbar (see the iTabbar section). However, its visual
appearance has been specified using various General and Appearance properties in the
Property Manager, as follows:

$dataname Set to the list variable iList


$name Scoreboard is the simple name of the control
$altcolor1 / $altcolor2 Set to blue and black respectively
$label1column / Set to 1 and 2 respectively which correspond to the
$label2column first and second columns in the list
$tablestyle kiTableStyleDoubleTextHorizontal

In addition to the General and Appearance properties, you can set the properties of the text
labels and row background displayed in the table under the Text tab in the Property
Manager.

$font Courier New


$label1bold / $label2bold Both set to kTrue
$label1size/ $label2size Set to 14 and 12 respectively
$label1textcolor / Set to white and red respectively
$label2textcolor

Note you can examine the $construct() method in the rfScoreboard remote form to see how
the table (list) data is built and displayed initially.

229
Chapter 4—Creating Apps using iOS Client

Using Grouped Lists with iTable


Together with the simple two-column table using a flat list, you can create tables containing
multiple groups of data for more powerful or complex end-user selections. To create such a
table, you need to enable the $grouped property of the table and construct a list containing
the grouped structure. The different groups in your table are stored in separate lists and
added to the main list specified in $dataname and used to construct the table.
The image shows a typical grouped table; each group
has a heading and any number of subheadings. Under
each subheading, you can display an icon and a
description. The end user can scroll the list and, in
this particular example, push on a line in the table to
select a new window or subform.
To create a grouped list in your code, like the one
shown, you define and populate a flat list containing
all the lines you want to include in a single group,
add that to the main list in its first column, and add a
name for the group in its second column. In the
following method, both ‘Group’ and ‘iMainList’ are
list variables.

; Instance var iMainList (List)


; Local vars: Group (List), Title, Text1, Text2, IconID (Chars) and
Flag (Number Short Int)
Do iMainList.$define(Group,Title)
; Group 1
Do Group.$define(Text1,Text2,IconID,Flag) ;; Column order as
defined in 'Appearance' tab
Do Group.$add('WebView','Internet
browser',k32x32+2174,kiTableCellAccessoryDisclosureIndicator)
Do Group.$add('Pictures','Loading of pictures from your
device',k48x48+1711,kiTableCellAccessoryDisclosureIndicator)
Do iMainList.$add(Group,'Media') ;; Add this list to our main
list, and call the group 'Media'
; Group 2
Do Group.$define(Text1,Text2,IconID,Flag)
Do Group.$add('Entry Fields','Inputting text into entry
fields',k32x32+2115,kiTableCellAccessoryDisclosureIndicator)
Do Group.$add('Table','Table to display a
list',k32x32+1603,kiTableCellAccessoryDisclosureIndicator)
Do Group.$add('Date Time','Using the Datetime
roller',k32x32+2108,kiTableCellAccessoryDisclosureIndicator)
Do iMainList.$add(Group,'Data') ;; Add this list to our main
list, and call the group 'Data'

230
iOS Components

iMainList is assigned to $dataname of the table, and its $grouped property is set to kTrue.

iToolbar Control
The iToolbar provides a row of buttons to allow the end user to select an option in your
application. You must specify the properties for the toolbar control itself, and for each
button in turn by setting $currentobject.

Property Description
$events enable evClick to report user clicks
$tintcolor the color of the toolbar
$toolbarstyle specifies the appearance of the toolbar

The button properties are as follows.

Property Description
$currentobject the number (1 - $objectcount) of the current button (this specifies the
button affected by button specific properties)
$moveobject moves the button by assigning a number in the range 1 to $objectcount,
which changes $currentobject to the assigned number (not assignable in
class notation)
$objectcount the number of toolbar buttons (this must be at least one)
$objectenabled if true, enables the button and generates a click event when the user
presses it
$objecticonid the icon for the current button (only significant if $objecttype is
kiToolbarButtonTypeImage), the alpha values in the source image are
used to create the image, and opaque values are ignored
$objectselected if true, the object is the currently selected object in the group of
kiToolbarButtonTypeSegmented objects to which it belongs (ignored
unless $objecttype is kiToolbarButtonTypeSegmented)
$objectstyle specifies the style of the button (only significant if $objecttype is
kiToolbarButtonTypeText or kiToolbarButtonTypeImage)
$objecttext the text on the current button (only significant if $objecttype is
kiToolbarButtonTypeText or kiToolbarButtonTypeSegmented)
$objecttype indicates the type of the button
$objectwidth the width of the button in pixels, if zero, the control automatically sizes
the button (ignored unless $objecttype is kiToolbarButtonTypeText,
kiToolbarButtonTypeImage or kiToolbarButtonTypeFixedSpace)

If you use icons in your toolbar you must specify the icon page for the icon(s) in the
$iconpages property of the remote form.

231
Chapter 4—Creating Apps using iOS Client

Events
evClick a user generated click;
pToolbarButton = the number of the toolbar button clicked

The following toolbar has two buttons allowing the end user to select images from their
Photo Albums collection or Saved Photos folder.

The $event() method behind the toolbar can detect which button is clicked using the
pToolbarButton event parameter and act accordingly. For example, a toolbar with 3 buttons
could have the following code:

On evClick
Switch pToolbarButton ;; contains the number of the clicked button
Case 1
; Do this
Case 2
; or do this
Case 3
; or this
End Switch
Do $cinst.$redraw()

232
iOS Components

iWebView Control
The iWebView component allows you to display a web page and/or run some Javascript.
You can load or reload a web page, perform a Forward or Back web command, or run some
Javascript by assigning a 2 column row variable to $execcommand to execute a command.
Column 1of the row variable must contain an integer or a kiWebViewCommand... constant,
while column 2 has info specific to the command, as follows:

kiWebViewCommandLoadPage loads the page with the URL specified by column 2


of the row assigned to $execcommand. Sends
evResult when the page has loaded
kiWebViewCommandReloadPage reloads the current page displayed by the control.
Set column 2 of the row to an empty string. Sends
evResult when the page has reloaded
kiWebViewCommandForward navigates to the next URL in the sequence of
visited URLs. Set column 2 of the row to an empty
string. Sends evResult when the page has loaded
kiWebViewCommandBack navigates to the previous URL in the sequence of
visited URLs. Set column 2 of the row to an empty
string. Sends evResult when the page has loaded
kiWebViewCommandRunJavaScript runs the JavaScript specified in column 2 of the
row. Sends evResult when the script finishes
execution

When the page has loaded, reloaded, or the Javascript has executed, the control sends the
evResult event which contains the pResult parameter, a 2 column row containing the status
and result of the command executed.

233
Chapter 4—Creating Apps using iOS Client

Events
The evResult event is sent to the iWebView control when the command assigned to
$execcommand finishes executing. The pResult parameter is a row variable, where column
1 contains the value of a kiWebViewStatus... constant (see below), and column 2 contains
either error information or the URL of the page that has been loaded or the result of running
the JavaScript.

kiWebViewStatusOk indicates the command completed successfully, for


kiWebViewCommandRunJavaScript, the result of
the script is in col2 of pResult, for all other
commands, the loaded URL is in col2 of pResult;
kiWebViewStatusLoadInProgress means the command could not be executed because
the control is currently loading content;
kiWebViewStatusLoadError means an error occurred during command execution,
column 2 of pResult contains a character string which
further describes the error;
kiWebViewStatusInvalidParameter means the parameter value (passed to the command
using column 2 of the value assigned to
$execcommand) is invalid;
kiWebViewStatusCannotExecute means the control cannot go forward or back to the
next or previous URL

The following remote form contains a iWebview control called oBrowser together with a
Searchbar and Segmented control to allow the user to view web pages within your Omnis
application.

234
Creating an Omnis iOS App

There is no specific code behind the oBrowser control, rather the code to load or search for
pages is behind the Segmented or Searchbar controls. The following code is placed in the
$event() method for the Segmented control; the method sets a row variable depending on
which segment was clicked and the contents of the row variable is assigned to the
$execcommand property of the oBrowser Webview control.
; lRow (Row var), Command (Short int), Value (Char)
On evClick
Do lRow.$define(Command,Value)
Calculate lRow.Value as ''
Switch pSegment ;; the segment clicked
Case 1 ;; Back Pressed
Calculate lRow.Command as kiWebViewCommandBack
Case 2 ;; Forward Pressed
Calculate lRow.Command as kiWebViewCommandForward
Case 3 ;; Refresh Pressed
Calculate lRow.Command as kiWebViewCommandReloadPage
Case 4 ;; Home pressed
Calculate lRow.Command as kiWebViewCommandLoadPage
Calculate lRow.Value as 'http://www.tigerlogic.com/omnis'
End Switch
Do $cinst.$objs.oBrowser.$execcommand.$assign(lRow)
Do $cinst.$redraw()

Creating an Omnis iOS App


In order to test and deploy your application you need to create an iOS app which can be
installed on your own iOS device or an end-user’s device. This can only be done on an
OS X computer using the tools from Apple. To get all the necessary tools, you must sign up
to the iOS Developer Program with Apple, at the following address:
 http://developer.apple.com
If you wish to deploy your applications onto iOS devices, you must sign up to one of the
paid options under the iOS Developer Program, as you will require the code signing
certificates and provisioning profiles available via the program. You can create and test
your applications using the iPad or iPhone simulator, which are available if you sign up to
the free version of the iOS Developer Program.
When you are ready to deploy your application you will need to consider which distribution
method within the iOS Developer Program is appropriate to your app and target market.
The following section describes how you can build your Omnis iOS app for testing on the
simulator or your iOS device itself.

235
Chapter 4—Creating Apps using iOS Client

Configuring Xcode
 Go to the Apple website and log into the iOS Developer Program

 Download and install the latest Xcode with the iOS SDK (which also provides you with
the iPhone/iPad simulator)

 Go to the Omnis website (www.tigerlogic.com/omnis) and download the clientbuild.zip


file

 Extract the contents of clientbuild.zip to your computer

 Locate the clientios.xcodeproj and open it in Xcode

For all builds, whatever the target, you should select “Distribution” as the “Active
Configuration” in the “Overview” droplist.

Creating a Simulator App


Use the ‘omnisios_simulator’ target in the clientbuild project to build a Simulator App. You
will have to setup the iOS app using the Settings section in the simulator itself as described
below. The app is placed in the ../clientbuild/build/Distribution-iossimulator folder.
You can sign up to the iOS Developer Program free of charge to create an app that you can
run on the simulator.

Creating a Device App for testing on your device


You must sign up to one of the paid options in the iOS Developer Program to create an app
that you can deploy to physical iOS devices. When you have signed up to the program you
can create your code signing certificate(s) and provisioning profile(s) which you will need
to create a device app.
Use the ‘omnisios_device’ target in the clientbuild project to build an app for running on
your iOS device (rather than the simulator). The Omnis iOS application file is called
‘Omnis.app’ and is placed in the ../clientbuild/build/Distribution-iosdevice folder. This must
now be installed on the iOS device.
You will have to setup the iOS app using the Settings section on your device itself as
described below.
Note that the Simulator and Device targets contain a “Settings.bundle” which will add an
Omnis entry in the “Settings” on your device; this is required to allow you to setup your app
for testing.

236
Testing your Omnis iOS app

Installing your Omnis iOS app on your device


Assuming you have created the ‘Omnis.app’ file, you will need the iTunes application,
available to download from Apple, to install your iOS app onto your device for testing.
 Install iTunes, if you don’t already have it, from www.apple.com/itunes

 Connect your iOS device to your computer via a cradle or USB cable, and let it sync
with iTunes

 Locate your mobile provisioning profile and drop it onto your device in iTunes

 Locate your Omnis.app which you built in the previous section, and drop it onto your
device in iTunes

 Then sync your iOS device with iTunes, and your Omnis app will be installed on the
device

Your Omnis iOS app should now be installed on your device, and the app should appear in
the list of apps on your device. However, before you can use it, you must configure the app.

Testing your Omnis iOS app


Having installed the Omnis iOS app onto your device you need to configure it to enable it to
connect to Omnis Studio and your Omnis library. For developing and testing your iOS app,
your device needs to connect to your local development computer running Omnis Studio
and your library.
Note that for end-user deployment, your iOS app needs to connect to the Omnis App Server
which will usually be at a remote location: furthermore, clients are setup using the
config.xml settings file (see later), not using the following method.
To setup your App for development and testing
 Click on “Settings” on your iOS device, and scroll down to the Omnis entry, and select
it

 Set Design Mode “Enable” to ‘On’

This allows you test your form on your local computer in the usual manner using the Test
Form option or Ctrl-T.
 In the ‘IP address:Port’ field enter the IP address of the computer you are using for
development and the $serverport number of your local copy of Omnis Studio in the
format IP Address:Port, e.g: 193.456.82.311:5555

237
Chapter 4—Creating Apps using iOS Client

Note your iOS device needs to be able to connect to a wireless network that can
communicate with this IP address and port

IP address
To obtain the IP address of your development computer under OS X, open the "System
Preferences" dialog, click on "Network" under the “Internet & Network” section, then select
your network (Ethernet, AirPort, etc) and click on the TCP/IP option.
Under Windows, you can run the ipconfig command at the command prompt.

Omnis Server Port setting


The Omnis Server port setting is in the main Omnis preferences ($root.$prefs). To view the
Omnis preferences, click on “Studio x.x” in the top left corner of the Studio Browser
window, and click on “Prefs” to open the Omnis preferences in the Property Manager. Click
on $serverport to view or set the server port for your local copy of Omnis Studio. It can be
any integer number in the range 1 to 32767, but we advise you to use a four digit number
over 5000 to avoid any of the standard ports in use.
You can also set the Saved state delay in seconds here in the Settings file, but for initial
testing you are not required to set this.

Testing your iOS remote form


To test your iOS remote form, you can press Ctrl-T in Omnis when your remote form is the
top window, or you can Right-click on the background of the remote form and select “Test
Form”.
IMPORTANT: In order for the Test Form option to work, the Omnis iOS client must be
open and running on your device. If the remote form and your device are setup correctly,
the remote form will open on your device.

Debugging your iOS app


As with any Omnis development, you can set breakpoints in your code and step through any
methods that you want to debug. So for example, you can set a breakpoint in your iOS
remote form and when the breakpoint is encountered method execution is halted and the app
is paused on the client. You can switch to Omnis on your development computer and step
through your code. When you have executed all the methods on the stack, execution is
passed back to the client.

Multi-tasking and form persistence


If you are running iOS 4.x and your device allows multi-tasking (see Apple’s web site for
details of which devices allow multi-tasking), your app will enter the background rather
than terminate when you press the Home button. In this case, when you start the app again it
will resume where it left off, because it is still running in the background; if a message was

238
Testing your Omnis iOS app

being sent to the server when you pressed the home button, the app will resend it when it
comes back to the foreground.
If you are running an earlier version of iOS or if your device does not allow multi-tasking,
then pressing the home button will terminate the app.
Saved State
When you close the Omnis app on your device, as part of the terminate processing, the app
saves the exact state of the form, its controls and their data in a file on the device. At the
same time, Omnis retains the remote form instance on the Omnis Server (or in your local
copy of Omnis during development). If you then re-open the Omnis app, the form is re-
instated at the same stage as when you closed the app. This “saved state” stores the exact
state of the controls, any data you or the end user has entered, and so on, so when you
restart the client, the form appears exactly as when you closed the app. Remember that the
remote task instance on the server has timeout properties, which could mean that the server
instance has closed when the app eventually reopens.

Saved State timeout


You can set a timeout to control whether or not the current state of the remote form is saved
at all or for how long the state is saved. The timeout is an integer value in seconds. If it is
zero, the state of the remote form is not saved, and the application attempts to disconnect
when it is closed.
The saved state for a remote form contains the time at which it was saved. If the difference
between the time when the application restarts and the time in the saved state is greater than
or equal to the timeout, the application being restarted discards the saved state.
To set the timeout, you can use one of the following methods.
 For design mode testing, you can set the saved state timeout for the Omnis app in the
‘Settings’ on the device.
 For a deployed application, the following member appears in the <Application>
element in config.xml:
<iPhoneSavedStateTimeout seconds="nnn"/>
 In your code, you can use the new $clientcommand method, as follows:
Do $cinst.$clientcommand("setsavedstatetimeout",row(timeout in
seconds))
The timeout in force (from the config file or set later by calling $clientcommand) when the
application saves the state is part of the saved state.

239
Chapter 4—Creating Apps using iOS Client

Deploying your Omnis iOS app


When you deploy your application to your target market, the application needs to start
automatically. In other words, you want users to be able to open your app without having to
change any settings. In this case, a configuration file called config.xml is included within
your iOS app which contains all the necessary settings to connect the client app to the
Omnis Server running your Omnis library. The “Settings.bundle” available in the
‘Simulator’ and ‘Device’ targets is not present in the ‘Distribution’ target which is used to
create your release application.
Before you compile the app, you will need to customize the config.xml file. There is a
separate manual on the Omnis website which describes the customization of the config.xml
file and wrapper applications.
For information about setting up your Omnis Server, your Omnis application (library), and
Web Server for remote deployment of your Omnis iOS app, see later in this manual.

240
HTML Forms and Remote Tasks

Chapter 5—Ultra-thin
Omnis
In addition to accessing the Omnis App Server via the JavaScript Client, Omnis Studio lets
you interact with your Omnis application using standard HTML forms. This approach is
often referred to as “Ultra-thin Omnis” since the client’s browser uses standard GET and
POST methods without any other client access layers.
In the Ultra-thin Omnis environment, the HTML form sends parameters and data directly to
the Omnis App Server via the Omnis web server plug-in located in the cgi-bin or scripts
folder. When the ‘Submit’ button in your HTML form is pressed, the Omnis web server
plug-in is executed and passed all the form’s parameters. The Omnis web server plug-in
sends the request to the Omnis App Server, which creates an instance of the specified
Remote Task Class and calls its $construct() method.

HTML Forms and Remote Tasks


The parameters required in the GET request in your HTML form contain the necessary
criteria for interacting with the Omnis remote task in the Omnis library on the Omnis App
Server. Your HTML contains the location of the web server plug-in, the port number, the
remote task name, the Omnis library name, as well as the specification for the fields in the
form. For example, the following constructs a form with the GET method :
<form method="GET" action="/cgi-bin/omnisapi.dll">
<input type="hidden" name="OmnisServer" value="PortNumber">
<input type="hidden" name="OmnisClass" value="RemoteTaskName">
<input type="hidden" name="OmnisLibrary" value="LibraryName">
<p><input type="password" name="pPassword" size="20"></p>
<p><input type="text" name="pQuery" size="80"></p>
<p><input type="submit" value="Submit" name="B1">
<input type="reset" value="Reset" name="B2"></p>
</form>

241
Chapter 5—Ultra-thin Omnis

The form has the special parameters:


 OmnisServer
specifies the port number or service name of the Omnis App Server, that is, the value
specified in the $serverport preference in the Omnis App Server.
 OmnisClass
the name of the remote task class to which this form is to connect (not a remote form as
is the case with JavaScript Client based applications).
 OmnisLibrary
the internal name of the library containing the remote task class on the Omnis App
Server; the default is the library file name minus the .lbs extension
The following example HTML source code implements a feedback form. The Omnis
specific parameters are marked in bold; the remainder of the source specifies the form fields
and text labels in the form, including a standard Submit button.
<form method="GET" action="/cgi-bin/omnisapi.dll">
<input type="hidden" name="OmnisClass" value="tFeedback"> ;; the remote
task name
<input type="hidden" name="OmnisLibrary" value="FeedbackApp"> ;; the
library name
<input type="hidden" name="OmnisServer" value="5912"> ;; the port number
<table border="0" cellspacing="0" cellpadding="0" width="760">
<tr>
<td width="788" valign="top"><div align="right">
<p><strong><font face="Arial">Developer
Name:</font></strong></td>
<td width="564" height="25"><font face="Arial">
<input type="text" name="Name" size="27"></font></td>
</tr>
<tr>
<td width="788"><div align="right">
<p><strong><font face="Arial">Serial
No:</font></strong></td>
<td width="564" height="25"><font face="Arial">
<input type="text" name="Serial" size="27"></font></td>
</tr>
<tr>
<td width="788" valign="top"><strong><font face="Arial">
<div align="right">
<p>Platform:</font></strong></td>
<td width="564" height="23"><table border="0"
cellspacing="0" cellpadding="0" width="520">
<tr>
<td width="135"><font face="Arial">
<input type="checkbox" name="Macintosh" value="YES">
<strong>Macintosh</strong></font></td>

242
HTML Forms and Remote Tasks

<td width="385"><font face="Arial">


<strong><input type="checkbox" name="Windows"
value="YES">Windows</strong></font></td>
</tr>
</table>
</td>
</tr>
<tr>
<td width="788" valign="top"><strong><font face="Arial">
<div align="right"><p>Client:</font></strong></td>
<td width="564" height="23">
<table border="0" cellspacing="0" cellpadding="0"
width="601">
<tr>
<td width="136" height="13"><font face="Arial">
<input type="checkbox" name="ActiveX" value="YES">
<strong>ActiveX&nbsp;&nbsp; </strong></font></td>
<td width="135" height="13"><font face="Arial">
<strong><input type="checkbox" name="Netscape"
value="YES">Netscape </strong></font></td>
<td width="330" height="13"><font face="Arial"><strong>
<input type="checkbox" name="RAWHTML"
value="YES">RawHTML</strong></font></td>
</tr>
</table>
</td>
</tr>
<tr>
<td width="788" valign="top"><strong><font face="Arial">
<div align="right">
<p>Comments:</font></strong></td>
<td width="564" height="249" valign="top">
<font face="Arial"><textarea rows="11" name="Comments"
cols="57"></textarea></font></td>
</tr>
</table>
<div align="center"><center><p><font face="Arial">
<input type="submit" value="Send Comments" name="B1"></font></p>
</center></div>
</form>

In the above example, the HTML form uses the “GET” method. You can also use the
“POST” method. The main difference lies in how the data is transmitted to the server, and
this is reflected in cases where the URL generated by the form is displayed in the location
bar of the user’s browser. A “GET” method is equivalent to requesting the URL
/cgi-bin/omnisapi.dll?OmnisClass=…&OmnisLibrary=…&…

243
Chapter 5—Ultra-thin Omnis

whereas a “POST” method is equivalent to posting to the URL


/cgi-bin/omnisapi.dll
and sending content which specifies the parameters. If the URL is being displayed in the
location bar, you might choose to use “POST” in order to hide the parameters from the user.

Secure Sockets
You can use secure sockets (HTTPS) if you have installed an SSL certificate on your web
server. Omnis will use a secure connection to connect the client to the web server if you
prefix the location of your HTML forms with “https://”. In addition, remote tasks have the
$issecure property that lets you turn secure mode on and off dynamically, by assigning to
the property for the current task at runtime.

Using Task Methods to Process


Requests
Omnis passes a single parameter to the $construct() method of a remote task instance
created by a request from an HTML form. This parameter called pParams is a row variable,
and it has a column for each parameter in the HTML form.
The code contained in the $construct() method of your remote task could literally do
anything you like and depends on the functionality of your application. Having passed in the
row variable to your $construct() method you can use any type of Omnis programming to
process the information submitted by the user and pass back whatever content or data you
wish. Typically and with most complex web applications your library will contain many
different methods that can be called from your remote tasks, most of which could be located
in object classes to allow reuse of your code. See the Omnis Programming manual for
information about programming Omnis methods and using object classes.
The column names in the row variable are the same as the form parameter names, and the
values are either the values of the parameters in the form (e.g. hidden fields may have
default values), or the values entered by the user. You can use the columns values in the
pParams row variable (i.e. values in the form parameters) as input to what you do in
$construct().
The following $construct() method is contained in a remote task that handles Studio
evaluation download form requests. The method contains a parameter variable called
pParams of Row type that receives the values from the form. The row variable contains a
column for each field in the form, including the fields Email, Country, Platform, and so on,
that are referenced using the syntax pParams.Colname. The method also contains several
calls to methods in object classes within the library handling the download requests. After
registering the customer, the method sends the customer an email and redirects their
browser to the appropriate download page.

244
Using Task Methods to Process Requests

; $construct() for processing download requests


If len(pParams.Code)
Do iObj.$getMagazine(pParams.Code,lMagazineRow) Returns
lCodeFound
; get magazine data (esp. name and serial number)
Else
Calculate lCodeFound as kTrue
; default to true for straight downloads
End If
If not(lCodeFound) ;; invalid magazine code
Do inherited
If not(len(pParams.Folder)>0)
Do method createFolderName Returns lFolder
; identify the folder name for this user
Else
Calculate lFolder as pParams.Folder
End If
Do iHTMLObj.$setFolder(lFolder)
; set the folder name for this instance of the html page
Do iHTMLObj.$setUrl(iUrl)
Do iHTMLObj.$createRegisterError(pParams,lFolder)
Else
Do iObj.$getDownloadCustID(pParams.Email,lCustID)
; see if this is an existing download customer
Do lAdminObj.$getDistID(pParams.Country) Returns lDistID
If not(lCustID)
Do iSequence.$getNext('ECS_DownloadCustomers') Returns lNextSeq
; get the next sequence number
Do iObj.$createDownloadCustRecord(lNextSeq,pParams,lDistID)
Calculate lCustID as lNextSeq
Else
Do iObj.$getDownloadCustData(lCustID,lCustRow)
; get their data
Calculate lCustRow.DistID as lDistID
; if the user has changed country their DistID may
; also have changed, so update it anyway
Do iObj.$updateDownloadCustData(pParams,lCustRow)
; update their account data
End If
Do iObj.$getPlatformID(pParams.Platform,lPlatformID)
; get the platform
Do iSequence.$getNext('ECS_Downloads') Returns lNextSeq
; get the next sequence number

245
Chapter 5—Ultra-thin Omnis

Do iObj.$createDownloadRecord(
lNextSeq,lCustID,lPlatformID,,,,pParams.Code,
pParams.ProductID,pParams.HowDidYouHear)
If len(pParams.Code)
; if they have entered a magazine code, they need an
; email with a serial number
; send user email with the appropriate serial number
Do iEmailObj.$sendEmail(
2,lCustID,lMagazineRow.SerialNumber,,kTrue)
; 4th parm is blank; 5th parm for using downloadcustomer table
Calculate lUrl as 'http://www.omnis.net'
Else
Do iEmailObj.$sendEmail(1,lCustID,,,kTrue)
; 3rd & 4th parm are blank; 5th parm is for using
; downloadcustomer table
Switch pParams.Platform
Case 'Win95'
Calculate lUrl as iWin95download
Break to end of switch
Case 'WinNT'
Calculate lUrl as iWinNTdownload
Break to end of switch
Case 'Ppc'
Calculate lUrl as iPpcdownload
Break to end of switch
Case 'Linux'
Calculate lUrl as iLinuxdownload
Break to end of switch
Case 'OSX'
Calculate lUrl as iMacosxdownload
Break to end of switch
Default
Calculate lUrl as iWin95download
Break to end of switch
End Switch
End If
End If
If not(lCodeFound)
Do $itasks.DOWNLOAD.$getUnsecuredUrl(lServerUrl)
; get the server path
Calculate lUrl as con(
lServerUrl,sys(9),'downloadhtml',sys(9),
lFolder,sys(9),iUrl,'.htm')
End If

246
Returning Content to the Client

Quit method lUrl ;; return the path to the approp download


The final command in the $construct() method is the Quit method <url> which returns an
URL to the client’s browser. See the next section for further details.

Returning Content to the Client


After completing its processing, $construct() returns its results as the return value of the
method, using the Quit method command. There are three possible types of return from such
a remote task instance: <url>, <data>, and <error>.

Quit method <url>


$construct() can generate a file (typically HTML), and any files it references, and then
return the URL of that file. For example, it can use the HTML report destination, and print a
report to HTML.
You return the <url> in one of two forms.
 If you prefix it with http:// or https://, the user’s browser will be redirected to the
specified URL. For example,
Quit method “http://www.myhost.com/myfile.html”

 If you do not prefix the URL as above, the user’s browser will be redirected to the
URL http://<web server address><url>. For example, if your web server is
www.myhost.com
Quit method “/omnishtml/00000001/myfile.html”
will result in the browser being redirected to
http://www.myhost.com/omnishtml/00000001/myfile.html
If you do generate dynamic HTML files, perhaps by printing reports to HTML, you can use
the oDirClean object to periodically check for expired files, and delete them. The HTML
report task wizard contains an example of how to do this. You should also note that if you
are generating new output for each request, you need to use a different file name or folder
for each request. The oDirClean object provides a mechanism which allows this.

Quit method <data>


$construct() can generate content directly in memory, and return that content to the user.
The content can be of any content type supported by a browser, typically HTML, or perhaps
a JPEG image. You build the content in either an Omnis character or binary variable. The
content must start with the text “content-type:” to differentiates the data from a <url> or
<error> (the other possible returns from $construct). The syntax of the data in the variable
is:
 HTTP headers starting with “content-type:” and separated by carriage return-
linefeed pairs. There must also be a content-length header.

247
Chapter 5—Ultra-thin Omnis

 An empty line terminated by a carriage return-linefeed pair.


 The content, for example HTML or JPEG data, the length of which must match
that specified by the content-length header.
For example:
Begin text block
Text: Content-type: text/html (Carriage return,Linefeed)
Text: Content-length: 12 (Carriage return,Linefeed)
Text: (Carriage return,Linefeed)
Text: Some content
End text block
Get text block iReturn
Quit method iReturn
returns the 12 character string “Some content” to the browser.
If you want to return binary content, you can build up the HTTP headers in a character
variable, and then use the bytecon() function to combine the character variable and the
binary content, storing the result in a binary variable. You can return the result as the return
value of Quit method.
In addition to the content type and length headers, you can specify other HTTP headers if
you wish. However, note that Omnis will automatically generate Expires: and Pragma: no-
cache headers, so you should not generate these.
The following extract of code is an HTML based storefront that presents with many
different HTML forms for logging in, choosing products, and so on, and heavily uses
remote tasks to process user requests and compose HTML on-the-fly to display in the
client’s browser.
; $create_rtOrder1 method for composing the store login screen
; do some preparation...
Begin text block
Text: <html> (Platform newline)
Text: (Platform newline)
Text: <head> (Platform newline)
Text: <title>Omnis Store - Login</title> (Platform newline)
Do method getCSSHeader
Do method getJSHelpHeader
Do method getHeader (kTrue) ;; kTrue - wide table
Text: <td width="262" ><span class="titletext">Login to the Omnis
Store</span></td> (Platform newline)
Text: <td width="220"></td> (Platform newline)
Text: </tr> (Platform newline)
Text: <tr> (Platform newline)

248
Returning Content to the Client

Text: <td width="500" colspan="3"><span class="bodytext"> (Platform


newline)
Text: The Omnis Store lets you purchase the Omnis Studio rapid
application (Platform newline)
Text: development environment. Ordering is easy, just follow the
step by step process.</span></td> (Platform newline)
Text: </tr> (Platform newline)
Text: <tr> (Platform newline)
Text: <td width="500" colspan="3">&nbsp;&nbsp; </td> (Platform
newline)
Text: </tr> (Platform newline)
Text: <tr> (Platform newline)
Text: <td width="500" colspan="3"><table border="0" width="100%"
cellspacing="0" cellpadding="0"> (Platform newline)
Text: <tr> (Platform newline)

Text: <td width="500" colspan="3"><form method="Get"


action="[iOmnisDll]"> (Platform newline)
Text: <input type="hidden" name="OmnisLibrary" value="[iLibName]">
(Platform newline)
Text: <input type="hidden" name="OmnisClass" value="rtNewCustomer">
(Platform newline)
Text: <input type="hidden" name="OmnisServer" value="[iServerPort]">
(Platform newline)
Text: <input type="hidden" name="IEBrowser"
value="[pParams.IEBrowser]"> (Platform newline)
;; store browser type
Text: <input type="hidden" name="Folder" value="[pParams.Folder]">
(Platform newline)
Text: <input type="hidden" name="BasketID"
value="[pParams.BasketID]"> (Platform newline)
;; store basket id if there is one
Text: <input type="hidden" name="AcctsCountry"
value="[pParams.AcctsCountry]"> (Platform newline)
;; so we know the accounts country
Text: <input type="hidden" name="InitialCountry"
value="[pParams.InitialCountry]"> (Platform newline)
;; so we know the initla country
Text: <input type="hidden" name="SessionID"
value="[pParams.SessionID]"> (Platform newline)
;; so we know the session
Text: <table border="0" width="100%" cellspacing="0" cellpadding="0"
bordercolor="#FFFFFF"> (Platform newline)
Text: <tr><td width="50%"> (Platform newline) ;; ### was <td>
Text: <span class="subtitle">New Customers</span><br> (Platform
newline)

249
Chapter 5—Ultra-thin Omnis

Text: <span class="bodytext">Click here to create a new


account:</span><br> (Platform newline)
Text: <input type=image
src="../../images/buttons/newaccount/new1.gif" width="135"
border="0" height="39" name="NewAccount" (Platform newline)
Text: onmouseout="MM_swapImgRestore()"
onmouseover="MM_swapImage('NewAccount','','../../images/buttons/n
ewaccount/new2.gif',1)"> (Platform newline)
Text: </td></tr></table> (Platform newline)
Text: </form> (Platform newline)
; etc etc etc...
The above code gives you some idea of how you can use the Text: command to build up
complete HTML files and pass them back to the client. Note you can use Omnis variables
enclosed in square brackets to fill in parameter values for form objects, such as:
<input type="hidden" name="OmnisServer" value="[iServerPort]">

Quit method <error>


$construct() can return an error to the browser. To do this, you use Quit method ‘nnn The
Error message’, where nnn is a three digit error code followed by a single space before the
error text.

Turning off the pragma:nocache header


The "x-omnis-ctrl:" control header can be returned at the start of the content to allow you to
turn off the pragma:nocache header.
When returning content, it can either start with "content-type:" or "x-omnis-ctrl:". If x-
omnis-ctrl: is present, it must be at the start of the content, to have any effect. To prevent the
Omnis web server plug-in from generating the pragma:nocache header, start the content
with:
x-omnis-ctrl:nopragma<cr><lf>
The letters can be in any case, but there must be no white space.

Cookie and Referer Headers


When a request arrives at the web server from an HTML form, there are some HTTP
headers sent from the client that may be of interest to the remote task instance. These
include “Cookie:” and “Referer”. (Note that a discussion of how the various HTTP headers
work is beyond the scope of this document; there are many good sources of information on
the Web). You can gain access to these parameters using the following mechanism.
In your HTML form, include an empty parameter with the name HTTP_<header name>, for
example, HTTP_COOKIE. This is an instruction to the Omnis web server plug-in, telling it
to insert the value of the corresponding HTTP header into the form parameter. This means

250
Persistent Remote Tasks

that when $construct() runs, there is a column HTTP_<header name> in the row variable
parameter, and its value is the value of the HTTP header. Note that the header value can be
empty if it is either not present, or not available to the Omnis web server plug-in.

Persistent Remote Tasks


Normally, the remote task instance created to process an HTML form destructs, as soon as
Omnis has called $construct(), and received the result to return to the user. It is possible that
you may want to keep the remote task instance available, so that it can receive further
requests. This mechanism is explained here. You should note:
1. This mechanism does not work in conjunction with Load Sharing (Load Sharing is
described in a later chapter).
2. This mechanism does not detect use of the ‘back’ button on the browser, meaning
that remote task instances can build up; these only go away when they time-out.
Each time Omnis receives a request from an HTML form, its default behavior is to destruct
the remote task instance after returning the result. You can prevent this behavior, by
implementing the $canclose method for the remote task instance, and returning kFalse if the
task is to stay open. The remote task instance has a property $connectionid, which identifies
the particular Omnis web client connection. The data you return to the user must contain
$connectionid, so that the next request to the Omnis App Server addresses the remote task
instance. Typically, you return a new HTML form to the user. This must contain a
parameter “ConnectionID” which contains the value of $connectionid.

evPost events
When an HTML form request arrives at the Omnis App Server, Omnis looks for the
ConnectionID parameter. If there is none, processing proceeds in the usual manner, calling
$construct() for a new remote task instance. If there is a ConnectionID parameter, Omnis
tries to locate the existing remote task instance. If it is no longer present, Omnis returns an
error to the user. Otherwise, Omnis sends an evPost event to the $event() method of the
remote task instance.
evPost works in exactly the same way as $construct(). In other words, there is a parameter
which is a row variable containing the HTML form parameters, HTTP header processing
occurs for the parameters, and the result is one of the three alternatives allowed for the
result of $construct(). The only difference is that the parameters and return value are
handled using event parameters. Event parameter pPostData is a row variable containing the
form parameters from the client, and you use the field reference event parameter
pPostResult to return the result to the client.
After each call to evPost, Omnis calls $canclose, to see if the remote task instance can now
be closed.

251
Chapter 5—Ultra-thin Omnis

Multipart Form Data


You can pass data and upload files from HTML forms to the Omnis App Server, using the
Multipart form data type. The content type “multipart/form-data” can be used for submitting
forms that contain files, non-ASCII data, and binary data files.
To use multipart form data, add the following attribute to the form tag:
enctype=”multipart/form-data”
and use the file=“type” attribute to identify files to be uploaded. For example:
<FORM method="POST"
action="/omnis_apache"
enctype="multipart/form-data"
accept-charset="utf-8">
<input type="hidden" name="OmnisServer" value="3012">
<input type="hidden" name="OmnisLibrary" value="LIB">
<input type="hidden" name="OmnisClass" value="rt">
<input type="text" name="test">
<input type="file" filename="myfilename" name="fileparam">
<input type="submit" value="Send">
</FORM>
Note that the “get” method restricts form data set values to ASCII characters. Only the
“post” method (with enctype="multipart/form-data") will cover the entire character set.
The form parameters are passed to the remote task using a row variable. Parameters without
the filename attribute behave as in previous versions, that is, their contents is passed to the
row variable. Parameters with the filename attribute are passed to the remote task via a
column in the row variable, called MultiPartFileList. This column is a list, with a row for
each filename parameter. The list has seven columns:
Column Description
ParamName the name of the filename parameter
ReceivedFileName the pathname of the file as it was specified on the client machine
DataLength the length of the file data in bytes
IsText if the length of the file is less than or equal to 16384 bytes, the data is
in one of the following two cols, depending on the value of IsText
CharData if IsText is kTrue, this contains the character data read from the file.
BinData if IsText is kFalse, this contains the binary data read from the file.
TempFilePath if the length of the file is greater than 16384 bytes, TempFilePath
contains the pathname of a temporary file containing the file data; the
temporary file is deleted after the remote task has returned from its
$construct()

252
Direct Client Connections

Direct Client Connections


In addition to the technique of connecting web based clients to an Omnis App Server via a
standalone Web Server, you can connect directly to Omnis, without the need to install a
Web Server (Omnis has its own built-in Tomcat web server). Using the built-in http server
may be a convenient way to test an Omnis Ultra-thin application, where the only difference
is the format of the http call itself to Omnis: in all other respects your application, including
the code in your remote tasks, is the same.
To enable direct connections to the Omnis App Server you need to make some
modifications to the html file.
 The WebServer script attribute needs to be set to /webclient
 The WebServer url attribute needs to be set to http://<ipaddress>:port
In this case, the OmnisServer address attribute is not relevant when connecting directly to
Omnis in this way.
The direct http call to Omnis is structured like this:
http://<Server>:<Serverport>/Ultra
<Server> is the domain name or the IP address of the computer on which Omnis Studio is
running. This is often 127.0.0.1 for your own local machine, but will be configured using a
different address or server name on a remote server.
<Serverport> is the port number which has been set in $serverport of Omnis Studio; this
is 5912 by default, but you can change it to anything you wish, in the range 1-32767. The
$serverport property is an Omnis preference ($root.$prefs).
To try this out, create a library called "DirectHTTP" and add a remote task called
"rtDirectHTTP". Then insert the following code into the $construct() method of the remote
task:
; $construct() method
; create the following variables
; Parameter var: pParams (Row)
; Local vars: fullhtml (Char 100000000) & html (Char 100000000)
Begin text block
Text: <html> (Carriage return,Linefeed)
Text: <body bgcolor="FFFFFF"> (Carriage return,Linefeed)
Text: <title>Hello [pParams.User] </title> (Carriage
return,Linefeed)
Text: <H1>Hello [pParams.User] </H1> (Carriage return,Linefeed)
Text: <a href="javascript:history.go(-1);">Go back</a> (Carriage
return,Linefeed)
Text: </BODY> (Carriage return,Linefeed)

253
Chapter 5—Ultra-thin Omnis

Text: </html> (Carriage return,Linefeed)


End text block
Get text block html
Calculate fullhtml as con('content-type:
text/html',chr(13,10),'content-length:
',len(html),chr(13,10,13,10),html)
Quit method fullhtml
The Remote task can be called within an HTML form with the following source text:
<html>
<form action="http://127.0.0.1:5912/ultra" method="Get">
What is your name? <input type="Text" name="User" size="30"
maxlength="50"></br></br>
<input type="Submit" name="Send" value="Send">
<input type="hidden" name="OmnisLibrary" value="DirectHTTP">
<input type="hidden" name="OmnisClass" value="rtDirectHTTP">
</form>
</html>
You must change the IP address and the port according to your configuration, although the
IP address and port number given above are the default values.
Then open the HTML form in a browser, enter a name in the field, and click Send.
This will call the $construct method in the remote task "rtDirectHTTP", passing a parameter
called "User" to it, which will contain the text you entered in the form. The full http call is
like this:
http://127.0.0.1:5912/ultra?User=Username&Send=Send&
OmnisLibrary=DirectHTTP&OmnisClass=rtDirectHTTP
The remote task processes the form values (and performs whatever other functions you
like), and returns standard HTML text that is displayed in the browser.

254
Localization for the JavaScript Client

Chapter 6—Localization
If you are developing applications for an international market, you may want to translate the
text and labels in your web and mobile apps into another language or support multiple
languages. You can use the String Table Editor to create an external file to store alternative
strings for the labels and text in your app to support multiple languages in your JavaScript
remote forms. The external file is stored in Tab Separated Value (TSV) format.
Note that the old way of storing string tables internally (.stb format) and handling them via
$stringtabledata and $stringtabledesignform still works with Omnis Studio 6.0 for
compatibility. This technique is described in the Omnis Programming manual.

Localization for the JavaScript Client


String Table Format
The String Table external component in Studio 6.0 supports two disk formats for storing
string tables. These are the existing .stb format and a new tab separated value (TSV) format,
which has the following features:
 Data is stored in a UTF-8 encoded text file, as a series of rows of fields.
 Fields in the data are separated by tabs.
 Each field is enclosed in double quotes.
 Double quotes in field values are escaped as a pair of double quotes.
 Field can contain newline characters.
 Each row is separated by a newline outside the contents of a field.
 The fields in row 1 are the column names for the string table.
The external component selects the TSV format automatically if the string table file has the
extension “.tsv”. The current String Table editor supports the new TSV format. The string
table file should be stored in the same folder as the library file.
If you open the Catalog (press F9) while editing a remote form or remote task that has a
string table associated with it (via $stringtable), then the Catalog automatically loads the
$stringtable if it is not already loaded, or reloads it if it has changed on disk.

255
Chapter 6—Localization

Localizing Remote Forms


Remote tasks have a property, $stringtable which is the name of the string table for the
current library and shared by all JavaScript Client remote form instances in the remote task.
When a client connects and the remote task is using the $stringtable property, Omnis loads
the appropriate string table.
When you test a remote form that has an associated string table, Omnis generates a
JavaScript file automatically if the file does not exist or if the string table file (.tsv) is more
up to date than the script file. In addition, Omnis inserts a script tag for the string table into
the HTML file generated automatically by the Test Form option. The path of the string table
JavaScript file is of the form:
html/strings/libname/file.js
where ‘strings’ is a folder in the html folder, ‘libname’ is a folder for the library, and file.js
is the JavaScript file for the remote task strings, named using the name of the task string
table file.
For deployment, you need to place the file.js in the equivalent folder in the web server tree
where the other Omnis HTML pages, scripts, etc are located. Alternatively, you can use an
option in the String Table Editor to export the string table JavaScript file, rather than using
the exported file from your development tree. This option can be used to output the entire
table as a JavaScript file, or you can output one or more files for selected locales, where
each file contains a single selected locale column and is named file.locale.js.
String tables are converted to separate JavaScript files and transferred to the client as
needed and depending on its locale. The script file is cached in the client browser and only
reloaded when the string table has changed.

Optimizing string tables


Single-locale JavaScript string tables can be used to further improve loading performance
for string tables. There is a new file, jsStringTableSwitch.htm in the html folder in the main
Omnis development tree. This file can be used as the initial remote form for an application,
and has markers where it can be customized - this allows you to specify the string table file
to use for each locale, and a default for unknown locales. In addition,
jsStringTableTempl.htm needs to be customized to set up the initial remote form etc, and
the string table path. When a page based on jsStringTableSwitch.htm loads, the page:
 Runs a script which selects the string table file to use, based on the locale.
 Loads the template based on jsStringTableTempl.htm using AJAX.
 Sets the string table to use in the template
 Replaces the document content with the modified template
This results in an HTML page for the remote form that only loads the strings for the current
locale, and which still has the original URL you have chosen for your application.

256
Localization for the JavaScript Client

Standalone Client
If you run your application in the Standalone client you have to set the library preference
$serverlessclientstringtable to specify which string table to use for the remote form
instances in the SCAF for the library. This takes the name of a string table (tab-separated
value .tsv file in library folder).
String table functions
The client accesses the current string table for the stgettext() function, and properties
assigned with the $st prefix. In addition, server methods can also use stgettext() to look up
strings for the client locale (either the locale received from the client, or the locale set using
$stringtablelocale). If the locale is not present in the string table, stgettext() will return
values from column 2 of the string table.

Localizing Error Strings


There are a number of strings that can appear in error message and other dialogs on the
JavaScript Client. These are built into the client and are all in English by default, but for
Studio 6.0, you can provide your own translations for some or all of these strings. Note that
some of the error messages are very unlikely to appear in the final deployed version of your
app, especially if you have thoroughly tested your app and eliminated all the errors, so it not
entirely necessary to translate all of these error strings.
To override any of the default strings, you can add your own translated string to the HTML
page containing the JavaScript Client. Each of the strings in the JavaScript Client has an
object name so you can reference by name, adding your own text for the sting separated by
a colon. For example, the following would override the default message string for the
Omnis App Server timeout (which occurs as specified in the $timeout property):
<script type="text/javascript">
jOmnisStrings.en = { "comms_timeout":"A timeout has occurred" };
</script>

257
Chapter 6—Localization

The following strings are present in the JavaScript Client, where \x01 is a place-holder
which is replaced by parameters added to the string when it is called by the client; you
should retain \x01 in your translated text.

Error string object Error string text (English default)


comms_error An error has occurred when communicating with the server.
Press OK to retry the request
comms_timeout The server has not responded. Press OK to continue waiting
ctl_tree_invmode Invalid data mode for tree
error Error
omn_form_ctrlinst Failed to install the control \x01. Possible missing class
script
omn_inst_badformlist \x01: Invalid formlist
omn_inst_badparent \x01: Invalid parent for subform set
omn_inst_badpn \x01: Paged pane does not have page \x01
omn_inst_badpp \x01: Cannot find the paged pane with name \\x01\
omn_inst_badservmethcall Cannot make server method call when waiting for a response
from the server
omn_inst_badsfsname \x01: Invalid or empty name for subform set
omn_inst_cliexcep Exception occurred when executing client method://
omn_inst_dupsfsname \x01: A subform set with this name already exists
omn_inst_dupuid Subform set already contains unique id \x01
omn_inst_excep Exception occurred when processing server response://
omn_inst_excepfile File \\x01\ Line \x01//
omn_inst_formnum Invalid form number. Parameter error \x01
omn_inst_objnum Invalid object number. Parameter error \x01
omn_inst_respbad Unknown response received from server
omn_inst_sfsnotthere \x01: A subform set with name \\x01\ does not exist
omn_inst_xmlhttp Failed to initialize XMLHttpRequest
omnis_badhtmlesc Invalid HTML escape
omnis_badstyleesc Invalid style escape sequence
omnis_convbad Error setting \x01: variable type \x01 not supported by
JavaScript Client
omnis_convbool Error setting \x01: data cannot be converted to Boolean
omnis_convchar Error setting \x01: data cannot be converted to Character

258
Localization for the JavaScript Client

Error string object Error string text (English default)


omnis_convdate Error setting \x01: data cannot be converted to Date
omnis_convint Error setting \x01: data cannot be converted to Integer
omnis_convlist Error setting \x01: data cannot be converted to List
omnis_convlistrow Error setting \x01: cannot convert List to Row
omnis_convnum Error setting \x01: data cannot be converted to Number
omnis_convrow Error setting \x01: data cannot be converted to Row
omnis_escnotsupp Text escape not supported by JavaScript Client

259
Chapter 7—Deploying your Web & Mobile Apps

Chapter 7—Deploying
your Web & Mobile Apps
To deploy your Omnis web or mobile application you need to host it on the Omnis App
Server which is the main engine at the heart of your Omnis app deployment. You will also
need a Web Server to host the HTML page containing your remote form(s) and any other
web pages or content. When the end user runs your application, the app connects to the
Omnis App Server, via the web server, and the JavaScript remote forms you have designed
are loaded in the end user’s desktop browser or the browser on their mobile device. You can
deploy your JavaScript Client based application to the web or mobile devices in two ways:
 Web and mobile app deployment
you can deploy your application to the web and provide your end users with a URL to
the location of the app, which they can navigate to on their desktop, tablet or mobile
device; the initial remote form is embedded into an HTML file which is created for you
during development which you will need to edit for deployment
 Standalone mobile app deployment
alternatively you can compile your app into one of the Application Wrappers to provide
a single standalone app for deployment to mobile devices; in effect the wrapper points
to the HTML page containing the initial remote form for your app. A standalone app
can operate “online” with a permanent connection to the internet and the Omnis App
Server; it can also work “offline” and then reconnect to the Omnis App Server to
synchronize data and content; or a standalone app can operate entirely in “serverless”
mode without any connection to the Omnis App Server
In addition to hosting your HTML page, you need to install the Omnis Web Server plug-in
into your web server which handles all communication between the Omnis App Server and
any connected web and mobile clients.

260
Omnis Web Architecture

Omnis Web Architecture


The server side of your web or mobile app comprises the Omnis App Server that runs your
Omnis library, a standard Web Server, and your database server(s). All these parts would
either run on the same machine, or more typically would be on the same LAN or subnet,
communicating via TCP/IP. The web server and the Omnis App Server can be hosted on a
Windows, OS X, or Linux computer server.
The web server would store your entire web, including any HTML pages containing your
JavaScript remote forms and any other web pages as required.
The Omnis library contains the GUI and data class definitions, business rules, and
application logic, while the database server would be an industry-standard database server,
such as Oracle, MySQL, PostgreSQL, Sybase, DB2, or any JDBC or ODBC compliant
database such as MS SQL Server.
The Omnis App Server is the main engine that runs your web and mobile applications. It is
a multi-threaded server that runs your Omnis application, executing all the business logic,
accessing your server database(s), and handling all the client interactions to-and-from your
web and mobile clients. Web and mobile client access to the Omnis App Server is restricted
to a specified number of users and is determined by the server license, which you must
purchase separately from your locale sales office.

Standalone Mobile Apps


As an alternative to deploying your applications to web browsers on web and mobile
devices, you can deploy a mobile app using one of the Application Wrappers available for
Android, iOS, and BlackBerry. See the Creating Standalone Apps section for more
information.

Editing Your HTML Pages


Omnis creates an HTML page when you test your JavaScript remote form (when you press
Ctrl-T) that contains details of the JavaScript Client object, your remote form class, the
location of your web server (or your computer when testing), and so on. You can use this
HTML file for deploying your web application, but you will need to edit it, or copy the
relevant lines of code containing the JavaScript Client object to your own HTML pages.
The test HTML file has the same name as your remote form plus the .htm extension, and is
located in the html folder under the main Omnis folder. For example, under Windows 7/8
the HTML template is located in your AppData\Local folder, such as:
C:\Users\<user-name>\AppData\Local\TigerLogic\OS<version>\html
You can edit the test HTML in a standard web page design tool or a text editor, such as
Notepad under Windows.

261
Chapter 7—Deploying your Web & Mobile Apps

The JavaScript Client Object


In the template HTML file, there is a <div> that contains the JavaScript Client called
‘omnisobject1’. It contains various parameters that provide details about your application
that are sent to the Omnis App Server when the client connects. The parameter names are in
lowercase and prefixed with ‘data-‘, to comply with HTML5.
The code for omnisobject1 from the ‘jsctempl.htm’ file is as follows (for existing users, the
equivalent old parameter names are included in parenthesis):
<div id="omnisobject1" style="position:absolute;top:0px;left:0px"
data-webserverurl="" (was WebServerURL)
data-omnisserverandport="" (was OmnisServerAndPort)
data-omnislibrary="" (was OmnisLibrary)
data-omnisclass="" (was OmnisClass)
data-param1="" data-param2="" (was param1, param2,..)
data-commstimeout="0"> (new parameter)
For example, the HTML page containing the Omnis quiz has the following <div> tag
containing the JavaScript Client object and its parameters:
<div id="omnisobject1" style="position:absolute;top:0px;left:0px"
data-webserverurl="http://194.131.70.208/cgi-bin/js/omnisapi.dll"
data-omnisserverandport="5775" data-omnislibrary="STUDIOQUIZ"
data-omnisclass="jsQuiz" data-param1="" data-param2=""></div>
You can add another Omnis object to the same HTML page, but it must have a unique id,
such as “omnisobject2”, and you can set its own server, library, and form parameters.

JavaScript Client Object Parameters


data-webserverurl
The data-webserverurl property identifies the HTTP URL of either the local IP address of
your computer during development or the address of the Web Server and location of the
web server plug-in.
When testing with the development version of Omnis, the data-webserverurl is set to
“_PS_” which will be replaced with the address of the computer from which the HTML
page is being served, that is, your development computer. For example, if the test HTML
page is at http://127.0.0.1:5000/jschtml/test.htm, then _PS_ will be replaced with
http://127.0.0.1:5000. For testing, data-omnisserverandport will be empty.
For deployment, when using a Web Server, the data-webserverurl parameter should be set
to the location of the Omnis web server plug-in, such as
http://www.myhost.com/scripts/omnisapi.dll, .which handles all the communication between
the server and the client.
data-omnisserverandport
For development and testing data-omnisserverandport can be empty. For deployment, data-
omnisserverandport tells the Omnis web server plug-in how to connect to the Omnis App

262
Editing Your HTML Pages

Server. If the Omnis App Server is on the same machine as the web server, then data-
omnisserverandport can be the port number of the Omnis App Server, e.g. it could be
"5000" if the Omnis App Server is at port 5000 on the same machine as the web server. If
the Omnis App Server is on a different server from the web server, then the data-
omnisserverandport parameter must be “IP-Address:Port-number” of the Omnis App
Server, e.g. it could be "111.222.000.111:5000" if the Omnis App Server is at port 5000 on
a machine with IP address 111.222.000.111.
data-omnislibrary and data-omnisclass
The data-omnislibrary parameter identifies the library containing your remote form, and
data-omnisclass is the remote form class displayed by the omnisform object.
data-commstimeout
The data-commstimeout parameter allows you to give the end user the option to timeout a
request or carry on waiting. The default value of zero means that no timeout is applied, and
the client will continue to wait for a response. To apply a timeout, you need to enter an
integer representing the timeout in seconds. When the client sends a message to the server it
must respond within this timeout period, otherwise the user will be prompted to either
continue waiting for a response, or abort the request.

Managing Wifi Connections


The client should handle a wifi connection going away while processing a request at the
server, so when the connection comes back, the client should respond properly. Otherwise,
you have the option to provide a timeout, as above.

Additional and Custom Parameters


You can specify up to nine additional parameters (named data-param1, data-param2, ..)
which can be passed into the row variable parameter pParams of the $construct() method of
the remote task assigned to the remote form.
In addition to the pre-defined parameters, you can include your own custom parameters if
you wish to pass extra values to the task or form $construct method. Custom parameter
names should be prefixed with “data-“ and should be lowercase. The parameter will be
added to the construct row variable which you can interrogate in your task or form
$construct method.
Positioning the Omnis object
The position or alignment of the “omnisobject1” itself within your HTML page is where the
Omnis JavaScript Client remote form will be displayed in a web browser. For mobile clients
you have less control since the remote form will usually fill the entire mobile screen. By
default, the JavaScript Client is displayed in the top left corner of the client browser (set
using style="position:absolute;top:0px;left:0px"), but for web clients you can reposition the
JavaScript Client object to appear anywhere in your HTML page using alternative style or
positioning parameters.

263
Chapter 7—Deploying your Web & Mobile Apps

Centering the omnisobject


By replacing the default style parameter in the div tag on the JavaScript Client object with
style=”width:900px; margin:auto” will center the remote form in the browser, assuming
your remote form is 900 pixels wide. Note that you cannot use the align property on the
omnisobject to reposition it, therefore align="center" will not center the omnisobject.
The above technique for centering the omnisobject will be fine for web-based applications
but it may not work for all mobile devices, therefore you can use the following method to
center the omnisobject for all devices. You have to place two extra divs around the div
containing the omnisobject and change the style parameter inside the omnisobject div, as
follows:
<div id="grandparent" style="float:left; width:100%;
overflow:hidden; position:relative;">
<div id="parent" style="clear:left; float:left;
position:relative; left:50%;">
<div id="omnisobject1" style="display:block; float:left;
position:relative; right:50%;" data-webserverurl="_PS_"
data-omnisserverandport="" data-omnislibrary="JSLIBRARYNAME"
data-omnisclass="JSREMOTEFORMNAME" data-param1="" data-
param2="">
</div>
</div>
</div>

CSS styles and JavaScript folders


Note that the Omnis html folder contains a number of other folders, including CSS, scripts,
and images, which contain CSS style sheets, JavaScript files, and images (icons) which are
required to run the Omnis JavaScript Client: these folders and their contents must be copied
to the equivalent location in your web server relative to the HTML page containing your
remote form(s). The html folder also contains the icons folder containing all the icons
generated during testing, some of which may be required for your application: see the
Component Icons section for more details.

Fav icon
The icon used for the test HTML page (displayed in the top-left of the browser tab) is the
image file called 'favicon.ico' located in the html/images folder. The image file in the
development version of Omnis is the Omnis logo, but for deployment you can replace this
image with your own icon file.

Customizing the JavaScript Working Message


You can change the appearance and positioning of the working message displayed in the
JavaScript Client when some processing is occurring. The working message is an animated

264
Setting up the Omnis App Server

GIF which is in a DIV laid over the main JavaScript Client area. You can restyle the
working message overlay DIV by adding your own class in the ‘user.css’. The default style
for the working message is in the omnis.css style sheet:
#omnis_overlay {
background:url('images/xajax-loader.gif') 20px 20px no-repeat;
}
But you can override this in user.css, for example:
#omnis_overlay {
background-position:center;
}
Which will center the working image, and/or you could also add your own animated GIF.

Setting up the Omnis App Server


In order to deploy your Omnis web or mobile application, you need to download and install
the Omnis App Server which will run your Omnis application (library) file. The Omnis App
Server is available for Windows, OS X, or Linux computer servers. There is a Tech note
also on the Omnis website called:
 TNJS0003: “Setting Up The Omnis App Server”
And when running on Windows, you can set the Omnis App Server up to run as a service
which is described in this Tech note:
 TNWI0002: "Running the Omnis Application Server as a Windows Service"
You should read these tech notes for the latest information about setting up the Omnis App
Server, including information about the latest version of IIS and Apache appropriate to
deploying Omnis web and mobile apps.
The server does not need to be located on the same machine as your web server. For testing
and debugging you can use the Omnis development version, but for deployment you must
use the Omnis App Server.
You need to place any libraries containing your application in the ‘Startup’ folder within the
Omnis App Server tree, so that Omnis automatically opens them when it starts up.

Server Licensing
You can download the Omnis App Server installer from the Omnis website at:
www.tigerlogic.com/omnis. Having installed the Omnis App Server you will need to
serialize it according to the number and type of clients you expect to serve. There are a
number of different server deployment licenses for running web and mobile apps in the
JavaScript Client. Please refer to www.tigerlogic.com/omnis, or contact your local sales

265
Chapter 7—Deploying your Web & Mobile Apps

office for details about these Omnis App Server deployment licenses. In addition, you will
need to purchase a different development license and deployment server license to create
and deploy standalone mobile apps running in serverless client mode.
Server Activation
When you serialize the Omnis App Server, it will attempt to automatically activate, which
requires the server to be connected to the Internet for activation to occur. If activation is
successful following this process your server will be licensed and ready for use. Without
activation, the Omnis App Server will not run.
To allow you to switch your Omnis App Server activated license to another system, you can
deactivate your server using the Deactivate option in the Tools menu. Having deactivated
your server, you can install and serialize the server on a new system. Contact your local
sales office for further information about activation, or see the Activation FAQ on the
Omnis website.

Setting the Omnis App Server Port Number


Having installed the Omnis App Server, you need to set its port number or service name.
The port number must be an available TCP/IP port number on the Omnis App Server. The
number can be between 1 and 32767, but you must not use 80 or any other number used for
e-mail, FTP, or other services.
During development, you can leave the $serverport preference set to zero and Omnis will
choose a free port automatically. However, since you’ll be running your web or mobile app
using the Omnis App Server, you have to set its server port number. You should use a high
number for the $serverport setting, preferably a four or five digit number, for example,
5912: choosing a port number in the range 5000-6000 should be fine.
In the development version of Omnis, you can set the port number in the $serverport Omnis
preference. In the Omnis App Server you can set the port number in the Server
Configuration dialog, available under the File>>Server Configuration menu option (note
this option is only available in the Omnis App Server when it is serialized with the correct
serial number).
The Server Configuration dialog lets you enter the server port number. The Server stacks
($serverstacks) parameter lets you specify the number of method stacks (and therefore
threads) on the Omnis App Server, which will be created when you execute the Start server
command. The Timeslice ($timeslice) parameter lets you specify the duration (in 1/60th
second units) of the execution time slice for a server thread.
When you click OK in the Server Configuration dialog and if the Omnis App Server is
already listening, you are prompted to restart Omnis, otherwise the Omnis App Server starts
to listen on the specified port using the new parameters.
You can set the Omnis App Server port using the command Calculate $prefs.$serverport as
5912.

266
Setting up the Omnis App Server

The Omnis App Server port number is stored in the Omnis.cfg file in the ‘Studio’ folder
under the main Omnis folder.

Server Multi-threading
The Omnis App Server allows multiple requests to be processed concurrently, allowing
smoother allocation of available processor time and avoiding any lengthy delays on the
client. To handle these multiple requests, the Omnis App Server is multi-threaded. By
default, the Omnis App Server is a standard single-threaded server handling client requests
in a strictly first-come, first-serve basis; client requests are queued, with each request being
handled only when the previous request has completed. You can however handle multiple
client requests concurrently using the Omnis Multi-threaded Server, which you can enable
by executing the Start server command on the Omnis App Server: see below.
The Multi-threaded Server maintains a pool of method stacks that can process web and
mobile client requests simultaneously. The pooling mechanism allows a balance to be struck
between performance and server resources - the number of method stacks in the pool is
configurable with the $root.$prefs.$serverstacks property, and also available in the Omnis
App Server Configuration dialog.
Multiple Method Stacks
The standard single-threaded Omnis App Server has only a single method stack to process
methods. Broadly speaking, once a method call has been pushed onto the method stack no
other method call can begin to execute until the first call has completed. For the majority of
web and mobile client applications this is fine for processing events, particularly if some
processing is performed on the client and your web server receives relatively few hits or
requests for data. By contrast, the Omnis Multi-threaded Server contains a pool of method
stacks which are available to process multiple client requests, and this is appropriate for
more data intensive web applications where lengthy calls to a server database are required,
or for web sites that receive higher volumes of traffic. When a request to execute a method
is received from a web or mobile client, that method call is pushed onto any unused stack
or, if there are no unused stacks, the message is queued until one becomes available. Each
method stack runs in its own thread, which means that if a method stack is stalled (for
example, it is waiting for the database server) the other stacks will continue to execute.
Potentially, the Multi-threaded Server may have to cope with a very large number of
simultaneous clients, each with their own remote form and remote task instances. Typically
though, a small proportion of clients will require the use of the server at any one time. In
fact, multi-threading does not increase the server processor time available, it just allows the
available processor time to be allocated in a smoother way. The method stack pool
mechanism allows a balance to be struck between performance and server resources - the
number of method stacks in the pool is configurable with the $root.$prefs.$serverstacks
property, which is set to 5 by default.
As method stacks are allocated dynamically, it is very likely that a remote client will not get
the same method stack every time it executes a method on the server. Each method stack

267
Chapter 7—Deploying your Web & Mobile Apps

contains its own state which, apart from during an individual method call, does not belong
to any particular client. This state includes the Current Record Buffers (CRBs) for all files
and variables (apart from class variables) and such modes as the current list. A client cannot
rely on any properties or values of this state being preserved across different method calls.
The only things belonging to the client are its instance and task variables. So a client must
do such things as setting the main file and current list each time one of its methods is
executed, and should not rely on such things as the values of memory-only fields being
maintained across method calls. As a special case, the class variables for the remote task
and remote form classes are shared amongst all clients so can be used to hold shared data
(see below for the warnings about the care needed when using shared variables).

Using the Multi-threaded Server


When the Multi-threaded Server starts up, it opens the libraries, data files and SQL session
pools required by the clients (see below for the description of a SQL session pool). You
need to issue the Start server command to cause the method stacks and associated threads to
be created. The Start server command can specify an optional stack initialization method;
when specified, this method is pushed onto every client method stack and allowed to
execute (so if $serverstacks is 5 it will execute five times), so it can be used to initialize the
state of the method stacks. The Start server command generates a fatal error if, due to lack
of resources or some other reason, it is unable to complete successfully.
When you want to stop the server, you should issue the Stop server command, but quitting
the Studio program achieves the same result.
When the server is active, Omnis continues to be responsive to events on the server and
could, for example, display a window with 'Start server' and 'Stop server' buttons. It is not
recommended that the server program performs any substantial tasks while it is deployed
and in use listening for client requests.
Any runtime errors generated by client methods are reported in the trace log (using a similar
mechanism as errors during library conversion), but you can override this default behavior
by making sure each client method stack has an error handler. You can use the stack
initialization method call for the Start server command to define an error handler for each
method stack.
Note that you cannot debug methods running in a remote form or task instance, after you
have called the Start server command in a development version of Omnis.

Database Access
If you are accessing a server database in your web application, and using the Multi-threaded
Server, you must use the Object DAMs (introduced in Omnis Studio 3.0) which are capable
of multi-threading. Using the Object DAMs, you can connect directly to Oracle, MySQL,
PostgreSQL, DB2, and Sybase, as well as most ODBC- and JDBC-compliant databases
such as MS SQL Server.

268
Setting up the Omnis App Server

The Object DAMs are implemented as external components and use object variables based
on the Object DAMs, and interact with a DAM using the methods of the object. Using this
approach, you create object variables of a particular DAM class. There is a group of
common methods that apply to all DAM objects and a set of DAM specific methods based
on the type of object. Various chapters in the Omnis Programming manual provide more
information about accessing your data using the DAMs.

Omnis Server Commands


There are some Omnis commands that you can use to control the Multi-threaded Server
which are contained in the Threads… command group in the Omnis method editor.

Start server
The Start server command is used to create the client method stacks and associated threads.
It takes an optional stack initialization method as a parameter. The command clears the flag
if it is used in a copy of Omnis which is not capable of supporting multi-threading or your
serial number does not allow clients to connect. A fatal error is generated if for some other
reason it is not possible to create the stacks and threads.
Stop server
The Stop server command stops the server from responding to client requests. Once the
server has been started you should stop it before quitting Omnis, before using Omnis for
anything apart from serving client requests (e.g. running a standard LAN-based Omnis
application), or before opening or closing any Omnis data files or libraries.
The Stop server command disposes of all remote task and form instances. The resources
used by the client stacks and threads are not released, but they will be reused by the next
Start server command.
Begin and End critical block
These commands are used to denote a section of code which needs to execute in single
threaded mode without allowing other client methods to execute. For example:
Set current list cList
Begin critical block
Build list from file
End critical block
Here cList is a class variable which is shared amongst the clients and the critical block is
used to prevent other clients from accessing the list whilst it is being built. Generally class
variables should only be used when the shared functionality is essential and only with care:
Calculate cString as 'abc' ;; OK
Calculate cString as $cinst.$xyz()
; only OK inside a critical block

269
Chapter 7—Deploying your Web & Mobile Apps

Simple atomic operations such as the first line of the above example are safe, but when a
method call is involved it may be interrupted by other threads and cause problems. Class
variables should not be used as bind variables or as the return list for SQL operations.
Yield to other threads
The Yield to other threads command is a hint that the executing thread is waiting for other
threads and is prepared to yield its processor time. It can be used when waiting for
semaphores (since with the Multi-threaded Server another client stack could be holding the
semaphore), as follows:
Do not wait for semaphores
Repeat
Prepare for edit
If flag true
Break to end of loop
End If
Yield to other threads
Until break

Commands which are not available to a client


The following commands are not available for methods running on the Multi-threaded
Server. They usually generate a 'Command not available when executing a client method'
fatal error but some (such as the Debugger… group) simply do nothing:
The Libraries… group
The Classes… group
Pre V30 SQL commands…
The Data management… group
The Message boxes… group
The Debugger… group
Quit Omnis
Enter data
Prompted find
And all the Omnis data file and lookup commands
Any other command which would cause a dialog to be displayed on the server is not
available for methods running on the Multi-threaded Server. In addition, there is a lot of
notation, such as the notation for opening and closing libraries and data files, that will not
work in a method running on the Multi-threaded Server.

SQL Session Pools


Suppose the Multi-threaded Server has N method stacks, and therefore N threads capable of
processing methods on behalf of clients. This means that at any one time, there can be at
most N SQL sessions in use. However, the Multi-threaded server may have many more than

270
Setting up the Omnis App Server

N current users. If you are using SQL, you need a potentially large number of sessions to
the database server. There is nothing wrong with this in itself, and there are occasions when
you might want to use database access permissions, to control the tables and columns
accessible to different users. If this is the case, you require a separate session for each user.
However, if all users have the same access permissions, you really only need N SQL
sessions. This can significantly reduce the resource usage of the server. SQL Session Pools
provide a way to do this.
A SQL Session Pool is a set of multi-threaded DAM sessions, which can be shared by
clients. Typically, you would create a session pool with one session for each method stack.
Details of how to use SQL Session Pools can be found in the Methods chapter of the
manual Omnis Studio Reference.

Server Load Sharing


Load sharing allows a pool of Omnis App Server processes, running on one or more
machines, to serve clients. Once a client connects to an Omnis App Server process, all
subsequent requests for that client need to be handled by the same Omnis App Server
process, since the process contains the instance data for the client. Therefore, load sharing
provides a mechanism that assigns a new client connection to an Omnis App Server process.
The data-omnisserverandport parameter in an HTML page normally has the syntax:
[(IP address|domain name):](service name|port number)
To use load sharing, you prefix this property with a name for the pool of Omnis App Server
processes and a comma, for example “Omnis,6000”, or “Omnis,194.131.70.197:6000”. In
this case, the address information in the property no longer addresses an Omnis App Server.
Instead, it addresses a new module, a load sharing process.
When a new connection arrives at the Omnis web server plug-in, the plug-in inspects the
syntax of the data-omnisserverandport parameter. If it is prefixed by a pool name, the plug-
in connects to the load sharing process, and sends it a message that asks for the address of a
server process in the pool. The load sharing process typically returns the address and port
number of the least busy process in the pool. The plug-in then connects to this process, and
sends the web or mobile client connection to it. When the plug-in responds to the client, it
includes the address of the Omnis App Server process in the response.
When the client sends subsequent messages to the web server for this web or mobile client
connection, it sends the address passed in the connect response instead of the data-
omnisserverandport parameter. Thus the only additional overhead imposed by load sharing
occurs during connection setup.
So how does Omnis know (1.) which Omnis App Server processes exist, and (2.) which
Omnis App Server process is the least busy? The load sharing process (LSP) has a .ini file,
which contains the pool names for the pools for which it is responsible, and for each pool,
the addresses of the Omnis App Server processes in the pool. Periodically, the load sharing
process polls each Omnis App Server process, and asks it for the percentage of web or

271
Chapter 7—Deploying your Web & Mobile Apps

mobile client connections currently in use (using the serial number as the maximum), and
information about how much time the server has spent processing requests. The load sharing
process combines this information to determine which process is the least busy.
You can configure the time interval between polls of each Omnis App Server process via
the .ini file. Once every 10 or 20 seconds is usually frequent enough.
Enabling Load Sharing
To enable the load sharing process you need place the LSP program on your web server, or
a machine connected to your web server. It is a single executable called Omnislsp.exe
(Windows) or omnislsp (Linux and Mac OS X). A configuration file (omnislsp.ini) must be
made to accompany the Omnislsp program, and this takes the following format:
[Setup]
Port=6001
QuietMode=0
BucketSize=100
LogLineThreshold=16
Pool1=Omnis
[Omnis]
PollTimer=10
Server1=123.145.71.123:7001
Server2=123.145.71.124:7002
The commands for the lsp are: omnislsp -start
omnislsp -stop
(with the omnislsp.ini in the same directory as the program)
The Port entry in the .ini file identifies the TCP/IP port number on which the LSP listens for
requests from the Omnis web server plug-in.
The QuietMode entry in the .ini file indicates if the LSP generates OK messages, or
messages to the console, to report its status. When set to zero, it will generate messages.
When set to one, it will not.
The LogLineThreshold entry in the .ini file indicates when the text log generated by the LSP
will be reduced in size. If the LSP writes a line to the log, and the file contains
LogLineThreshold lines, it will reduce the file size to LogLineThreshold/2 lines,
maintaining the most recently written lines, before writing the line to the log. The log is in
the same directory as the omnislsp program.
The BucketSize entry specifies how the LSP breaks up the server processes into groups,
based on how busy they are. It is a value in milliseconds. The LSP divides the processes
into 10 buckets, based on the average time to process a request obtained from the
information it gathers by polling the server processes periodically. The buckets are
numbered 1-10, where 1 contains the least busy servers, and 10 the most busy servers. A

272
Setting up the Omnis App Server

server is in the smallest numbered bucket, for which its average time to process a request is
less than or equal to (bucket number)*BucketSize. If a server is so busy that this calculation
does not allocate it to a bucket, it belongs to bucket 10. You may need to experiment with
possible settings for BucketSize, in order to determine the optimum setting for your
application.
Each pool has its own section in the .ini file. The PollTimer entry indicates the frequency in
seconds at which the LSP polls the server processes in the pool for information. The
ServerN entries identify the TCP/IP address and port of each server process in the pool.
You also need to edit the 'data-omnisserverandport' parameter in your HTML file
containing the JavaScript Client plug-in, for example:
data-omnisserverandport="Omnis,6001" or
data-omnisserverandport="Omnis,123.456.789.010:6001"
where Omnis is the name of a pool of Omnis App Server processes and 6001 is the port
number of the LSP.
On the LSP servers
The Omnis App Servers may be stopped and restarted without the need to stop the LSP.
Load Sharing Mechanism
The load sharing process periodically polls the processes in a pool of Omnis App Server
processes. Each server returns the current number of connections to the server, the
maximum number of concurrent connections allowed to the server (specified by the serial
number), the number of requests since the last poll, and the total elapsed time in
milliseconds taken to process the requests. The load sharing process organizes the servers
into buckets, based on the results of the information returned from polling the servers.
When a connection request arrives at the load sharing process, it allocates a server to the
request as follows. It traverses the buckets, starting with that for the least busy servers,
looking for a server that has some free connections. Within a bucket, it looks for the server
with the smallest percentage of connections in use, using the results of the last poll. If there
is more than one server with the same smallest percentage of connections in use, the process
allocates the connection to the server to which it least recently allocated a connection. At
this point, the load sharing process also updates the connection statistics from the last poll,
to reflect the new connection. The traversal stops when a free process has been found. If all
servers are fully utilized, the LSP allocates the connection to a server at random; in this
case, it is likely that the server will reject the request, and return a suitable error to the
client.

Installing as a Service (Windows only)


The omnislsp process can be installed as a service which starts-up automatically when
Windows loads. For this purpose, two additional parameters are supported:
omnislsp –install Creates and starts the “Omnis Load Sharing Process” service.
omnislsp –uninstall Stops and removes the service.

273
Chapter 7—Deploying your Web & Mobile Apps

The startup-type for the new service is set to “Automatic” and the service uses the omnislsp
executable and .ini file at their current locations. When omnislsp runs as a service, dialog
boxes are disabled and messages are written to the application event log instead.

Socket Binding
For the development version, Omnis will retry the bind 5 times, once a second, and then
report an error via the trace log; this behavior is the same as previous versions. The Omnis
App Server will retry indefinitely once a second.
When running as a Service, after a few bind attempts, Omnis outputs a message to the
system event log (if the event log is being used for Studio), “Failed to bind web client
socket - will retry indefinitely”. If the bind is eventually successful, Omnis outputs a second
message, “Successful bind of web client socket”.
Note that you can stop the service while the indefinite retries are occurring, but you cannot
use the tray to bring Omnis to the front (or do anything else with the Studio service) as the
web client bind occurs quite early in the initialization of Studio.
The Omnis App Server displays a working message while the retries are occurring; this
allows the end-user to cancel the retry loop.

Setting Up Your Web Server


In addition to the Omnis App Server, you need to install and configure a standard web
server, such as Microsoft IIS, Apache, or Tomcat. You should download a suitable web
server from the appropriate vendor. You need to install the appropriate Omnis Web Server
plug-in in the correct location on your web server, for example, in the /cgi-bin, /scripts, or
/webapps folder. A different plug-in is available for each of the most common web servers.

Installing the Web Server Plug-in


Typically a web server will have a place to store all executable code accessible via HTTP
over the Internet. This is often the /cgi-bin or /scripts folder, but it can be any folder
configured to allow execution. You need to place the Omnis Web Server plug-in, such as
the omnisapi.dll (IIS) or mod_omnis.so (Apache), in this folder and ensure that the web
server is set up correctly to enable it to be executed. The location of the plug-in should be
specified in the data-webserverurl parameter of your HTML files containing your remote
forms.

Apache Server Plug-in


The Apache module for Linux is called mod_omnis.so and is located in the
clientserver\server folder in the main Omnis tree. The Apache module works with Red Hat
and other Linux distributions. This module is faster than the nph-omniscgi server extension.

274
Setting Up Your Web Server

Two versions of the Apache web server plug-in are provided in the clientserver\server
folder, under the main Omnis folder, to support Version 2 and Version 2.2 Apache web
servers.
To install the Apache module
 Copy mod_omnis.so to the Apache modules directory, e.g. on RedHat 9.x this is
/etc/httpd/modules

 Add the following lines at the end of access.conf:


<Location /omnis_apache>
SetHandler omnis-apache
</Location>

 Add the following lines to httpd.conf, at the end of each block of similar directives:
LoadModule omnis_module modules/mod_omnis.so
AddModule mod_omnis.cpp
You need to restart httpd (restarting the system is the simplest way to do this). After
installing the Apache module, you can address it using /omnis_apache in the data-
webserverurl parameter in the JavaScript Client object.
Installing the Java Servlet
Omnis Studio includes a Java Servlet web server plug-in that allows you to run your Omnis
web applications with any web server that supports version 2.3 of the Servlet API. Web
servers that comply with Java Servlet API 2.3 include the Apache TomCat and Jetty web
servers, but there are several others. For more information about Java Servlets, see:
http://www.oracle.com/technetwork/java
The Java Servlet allows Omnis remote forms to connect to an Omnis App Server via a Java
web server. In this respect, the Servlet is the Java equivalent of the ISAPI, CGI or the
regular Apache plug-in available in Omnis Studio.
The Java Servlet is called RdtaServlet and can be found in the Omnis Studio installed tree
in the clientserver\server\omnisservlet folder. Inside the Servlet folder, the servlet files are
in the following folder structure:

275
Chapter 7—Deploying your Web & Mobile Apps

servlet
|
- WEB-INF
|
- rdtaserv.dll (Platform dependant)
|
- web.xml
|
- classes
|
- com
|
- rdta
|
- RdtaServ.class
To install the servlet on your web server, such as the Apache Tomcat server, you should
place the whole servlet folder in the Webapps folder within the Tomcat installation. If you
wish, you can rename the servlet folder.
You will need to restart the webserver in order for the servlet to be loaded.
Web server parameters for the Java Servlet
The data-webserverurl parameter in your HTML containing your remote form must have the
correct format to access a web server with the Java Servlet.
 data-webserverurl
this must be the URL to the tomcat webserver appended with the name and path of the
servlet, such as "http://www.mydomain.com/servlet/%servletname%"
Note if you have renamed the servlet folder you should use the new name in the data-
webserverurl parameter instead of ‘servlet’;
The default value for %servletname% is 'rdtaservlet'. You can modify this or add others by
modifying the web.xml file. The following xml can be added to the <web-app> element in
the document to add a new servlet alias name. For example
<servlet-mapping>
<servlet-name>RdtaServ</servlet-name>
<url-pattern>/%servletname%</url-pattern>
</servlet-mapping>

ISP Web Hosting


If your web site is hosted by a third-party, such as an ISP, they will need to place the Omnis
web server plug-in in their cgi-bin folder, and furthermore they need to provide you with a

276
Setting Up Your Web Server

direct connection to the Internet. Your ISP may want to test the web server plug-in, usually
the case for any files you place in their cgi-bin folder.
If your Omnis web application uses a web site hosted by an ISP you will need to adjust your
port settings in the Omnis App Server and HTML files. In this case you can use
DomainName:Port or IPAddress:Port in your port setting.
Secure Sockets
You can use secure sockets (HTTPS) if you have installed an SSL certificate on your web
server. The JavaScript Client will use a secure connection to connect the client to the web
server if you prefix the URL or IP_address in the data-webserverurl parameter with
“https://”, for example:
https://remainderOfFullURL
In addition, remote tasks have the $issecure property that lets you turn secure mode on and
off dynamically, by assigning to the property at runtime in your application.
Secure socket connections do not support the "address:port" format for the data-
webserverurl parameter of a JavaScript Client object.

Web Server Plug-in Custom Configuration


You can configure the Web Server plug-in via a separate configuration file, allowing greater
security and control over user access to your Omnis web or mobile application. It is not
necessary to configure the web server plug-in in most circumstances, but this functionality
provides added flexibility and security. The parameters specified in your configuration file
can provide default connections for clients, simplifying the post command required to
connect to the Omnis App Server. The configuration file should be placed in the same
directory as your Web Server plug-in.
 Access and Security
Using the web server plug-in configuration file you can restrict access to an Omnis App
Server
 Configure Server parameters
The configuration file allows you to override parameters for the Omnis App Server, or
in effect, provide default parameters if the oserver parameter is blank in your cgi
parameters in your html; in this case the value would be taken from the configuration
file.
 Post content to Remote tasks
the configuration file allows you to pass HTTP Post content to the Omnis remote task.

Server plug-in activation


The new functionality in the Omnis Web Server plug-in is built into the plug-ins supplied
with the Omnis App Server installation, but you have to rename plug-in itself to activate the
new functionality.

277
Chapter 7—Deploying your Web & Mobile Apps

mod_omnis.so
If you are using mod_omnis.so under Linux or Windows, you need to change the value of
the location in your http.conf or equivalent apache configuration script to /omnis_apacheini,
for example:
<location /omnis_apacheini>
SetHandler omnis-apache
</location>

nph-omniscgi
Rename the nph-omniscgi.exe to nph-omniscgiini.exe for Windows, or rename nph-
omniscgi to nph-omniscgiini for Linux.
omnisapi.dll
For Windows IIS based servers, rename omnisapi.dll to omnisapiini.dll.
rdtaserv.dll
If you are using the Web Services enabled Web Server plug-in, rename rdtaserver.dll to
rdtaserverini.dll.
Creating a Configuration file
The configuration file should be named omnissrv.ini and be placed in the same directory as
your Web Server plug-in, for both Windows and Linux.
The format of the configuration file mirrors that of a Windows .ini file and is defined as
follows:
 Section names are contained in square brackets e.g. [SectionName].
 A section ends when another section begins or at End Of File (EOF).
 Comments are lines beginning with a semicolon (‘;’).
 All text following a comment is ignored until the line is terminated.
 Keys are of the form keyname=value where keyname is a unique identifier within the
section and value is the value of the specified key.
 Section names, key names and key values must not contain white space.
 Section names and key names are case sensitive.
The new functionality in the Web Server plug-in is controlled using specific named sections
in the configuration file. The omnissrv.ini file can contain the AllowConnectionsTo section
which controls access to the Omnis App Server. The .ini file can also include either a
DefaultConnection or OverrideConnection section (but not both), which either provide
default parameters for the Omnis App Server or override parameters posted to the Omnis
App Server from the http web server.

278
Setting Up Your Web Server

Controlling Server Access


You can control access to your Omnis App Server by including the [AllowConnectionsTo]
section in the configuration file. This section contains a list of key names of the form
address<n> where n is a sequentially numbered character starting at 1. When this section is
present, connections to Omnis App Servers are limited to those defined in the specified key
values. In the event that the oserver parameter is defined as a port number, only the port
number is required.
For example, in the following AllowConnectionsTo section connections are limited to
Omnis App Servers running on the local machine on port 5920 and the remote machine
192.168.0.2 on port 5920.
[AllowConnectionsTo]
address1=5920
address2=192.168.0.2:5920
Note that the local IP address in the configuration file cannot be resolved. Imagine the
server plug-in and the Omnis App Server are on the same machine, with an IP address of
192.168.0.3. If the incoming request was of the form data- OmnisServer=5920, the
configuration file has to match this form. So if you want to allow only connections to port
5920, you would have to add this line to the [AllowConnectionsTo] section:
address1=5920. If you use the expanded form of the address, i.e.
address=192.168.0.3:5920, the server plug-in would deny the request. In the event of a
denial of service the plug-in returns a HTTP 403 error with the following message ‘Access
to the resource has been denied’.
Default Connections
You can provide default connection parameters in the [DefaultConnection] section of the
configuration file. This section provides a means of adding missing values into an HTTP
post, or in effect, providing a complete set of default parameters if none are provided in the
HTTP post. When they are present in the HTTP request, the values in DefaultConnection
are ignored and the values are taken from the original request. The DefaultConnection
section can contain the following keys:
 OmnisServer
 OmnisClass
 OmnisLibrary
 PostDataParamName
 Any number of additional parameter pairs in the form Parameter Name=value
The OmnisServer, OmnisClass and OmnisLibrary mirror the operation of the identically
named remote form parameters. The value of the PostDataParamName key specifies a
variable name for all the content of the HTTP post. All other keys are assumed to be
parameters. They are passed to the Omnis remote task and appear as columns in the row
variable. The column name is the key name and the value matches the value of the key. One

279
Chapter 7—Deploying your Web & Mobile Apps

thing to note, if the parameter is present in the original request and the configuration file
also contains a definition for the parameter, the value is always taken from the request even
if the parameter has no associated value. For example:
[DefaultConnection]
OmnisServer=192.168.0.1:5920
OmnisClass=remoteTask
OmnisLibrary=TEST
param1=value1
param2=value2
PostDataParamName=PostData
In the context of the above DefaultConnection section, consider the following URL which
attempts to connect to Omnis:
/omnis_apacheini?OmnisClass=remoteTask&param1=1234
The OmnisClass and param1 values are taken from the URL while the other values are
taken from the DefaultConnection section. In this case, no OmnisServer and OmnisLibrary
parameters are provided in the query string, so those values are taken from the configuration
file. Therefore the plug-in will amend the query string to:
/omnis_apacheini?OmnisClass=remoteTask&OmnisServer=192.168.0.1:5920&
OmnisLibrary=TEST&param1=1234&param2=value2&PostData=
Note PostData is empty as the content-type is application/x-www-form-urlencoded, so in
this case the data is not passed to Omnis.
Overriding Connections
You can override the server parameters passed to the Omnis App Server by an HTTP post
by including a [OverrideConnection] section in your configuration file. In this case, all the
values in the request are ignored, and the Omnis App Server uses values from the
configuration file. The OverrideConnection section may contain the following keys with
associated values:
 OmnisServer
 OmnisClass
 OmnisLibrary
 PostDataParamName
 Any number of additional Parameter Name=value
These keys function exactly as described in the DefaultConnection section. An example
OverrideConnection section is as follows:

280
Setting Up Your Web Server

[OverrideConnection]
OmnisServer=192.168.0.1:5920
OmnisClass=rtTest
OmnisLibrary=TEST
param1=value1
param2=value2
PostDataParamName=PostData
In the context of the above OverrideConnection section, consider the following URL which
attempts to connect to Omnis:
/omnis_apacheini?OmnisClass=remoteTask&param1=1234
In this case, the values in OmnisClass and param1 submitted in the post are ignored, and all
the values for the post are taken from the DefaultConnection section in the configuration
file. Therefore the query string is amended to:
/omnis_apacheini?OmnisClass=rtTest&OmnisServer=192.168.0.1:5920&
OmnisLibrary=TEST&param1=value1&param2=value2&PostData=
Note PostData is empty as the content-type is application/x-www-form-urlencoded, so in
this case the data is not passed to Omnis.

281
Chapter 7—Deploying your Web & Mobile Apps

Creating Standalone Mobile Apps


In addition to using the JavaScript Client in the web browser on any computer or mobile
device, you can embed your JavaScript Client based remote forms into a Standalone app,
which you can deploy to end users as a self-contained app which they can install onto a
mobile device. To create a standalone app, we provide a Wrapper Application for each
supported mobile platform, which currently includes Android, iOS, and BlackBerry, but
more platforms will be added as they become available. The wrapper applications create a
thin layer around a simple Web Viewer which can load your JavaScript remote form.
The wrapper applications allow you to deploy mobile apps that end users can run either in
Offline or serverless mode, without any connection to the Omnis App Server, or in Online
mode which would allow end users to temporarily connect to the Omnis App Server to
synchronize their data and application content.

 Offline or Serverless mode


end users can run your app in standalone or “offline” mode without ever connecting to
the Omnis App Server or a database server. The Application Files (remote form
definitions, scripts, etc) are bundled with the wrapper app to create a single, clickable
application file; this allows complete “offline” operation, or a one-off connection can
be made to the Omnis App Server to install the applications files and from there on a
connection to the Omnis App Server would not be needed
 Optional connection
end users have the option to switch to “online” to synchronize the database and app

282
Creating Standalone Mobile Apps

content via the Omnis App Server; this mode would suit end users who have an
intermittent connection, but often need to synchronize their data with a central location

Wrapper Application Source Files


The projects and source code for the wrapper applications are available to download from
the Omnis website. The ZIP files contain template configuration files, together with the
project and source files so you can build your standalone app or customize the wrappers if
required.
There is a separate manual called ‘Building & Customizing Standalone Apps’ available on
the Omnis website about using and customizing the wrapper applications for mobile app
deployment: this manual contains all the latest information for each of the supported mobile
platforms and will be updated regularly to keep abreast of any changes in the build process.
To download the wrapper application source files and to read the manual, please go to:
www.tigerlogic.com/omnis/download

Configuring the Wrapper Application


The following section provides an overview of the configuration file that is used to
configure your standalone apps; you should refer to the ‘Building & Customizing
Standalone Apps’ online manual for information specific to your chosen mobile platform.
The wrapper applications can be configured to run a single JavaScript remote form as the
entry point to the app, which can be configured in a configuration file called config.xml.
Configuration file
The config.xml file contains the URL for the page containing your JavaScript remote form
and depending on the platform, may contain a number of other parameters specific to your
platform. The config.xml is standardized for all platforms, and is based on the following
structure:
<?xml version="1.0" encoding="utf-8" ?>
<settings>
<AppTitle>0</AppTitle>
<AppStandardMenu>1</AppStandardMenu>
<AppTimeout>300000</AppTimeout>

<MenuIncludeSettings>1</MenuIncludeSettings>
<MenuIncludeOffline>1</MenuIncludeOffline>
<MenuIncludeAbout>1</MenuIncludeAbout>

<SettingsFloatControls>0</SettingsFloatControls
<SettingsScaleForm>1</SettingsScaleForm
<SettingsAllowHScroll>0</SettingsAllowHScroll>

283
Chapter 7—Deploying your Web & Mobile Apps

<SettingsAllowVScroll>0</SettingsAllowVScroll>
<SettingsMaintainAspectRatio>0</SettingsMaintainAspectRatio>
<SettingsOnlineMode>1</SettingsOnlineMode>

<ServerOmnisWebUrl>http://172.19.250.25:5911</ServerOmnisWebUrl>
<ServerOnlineFormName>/jschtml/rfOnline</ServerOnlineFormName>
<ServerOmnisServer></ServerOmnisServer>
<ServerOmnisPlugin></ServerOmnisPlugin>
<ServerOfflineFormName>rfOffline</ServerOfflineFormName>
<ServerAppScafName>mylib</ServerAppScafName>

<TestModeEnabled>0</TestModeEnabled>
<TestModeServerAndPort>172.19.250.25:5911</TestModeServerAndPort>
</settings>

The config.xml contains the following properties (note that some may not be included on a
particular platform):
 AppTitle
whether or not the app displays a title bar at the top. Note that hiding the title on
Android 3 will hide the ActionBar which will remove access the testing menu
 AppStandardMenu
whether or not the standard menu is displayed at the top.
 AppTimeout
the time in milliseconds after which the app will close after being sent to the
background.
For all platforms:
 MenuIncludeSettings
whether the “Settings” menu option is available in the app.
 MenuIncludeOffline
whether the runtime menu option is available to switch to offline mode.
 MenuIncludeAbout
whether the “About” menu option is available in the app.
The following settings control the scaling of the app (remote form) on the device:
 SettingsFloatControls
This property is only significant when SettingsScaleForm is "0" (false). In this case, the
client uses the new $screensizefloat property of each JavaScript Client control on the
form. When applying the screen size, the client uses $screensizefloat to float the edges
of controls using the same rules as $edgefloat (note that the component values are not
supported, just the edge-related values). If the form is wider or taller than the screen,
floating only occurs if the relevant SettingsAllowHScroll or SettingsAllowVScroll

284
Creating Standalone Mobile Apps

parameter is false. The amount by which the controls float is the difference between the
actual screen width or height and the designed width or height of the form for the
closest matching $screensize. The value of $screensizefloat is stored for each setting of
$screensize in the remote form
 SettingsScaleForm
If you set this to "1" (true), the client scales the form to fit the available screen space.
The scaling factor is the screen width or height divided by the width or height of the
closest matching $screensize. For these purposes, the actual screen size excludes the
operating system areas such as the status bar
 SettingsAllowHScroll and SettingsAllowVScroll
set these to "1" if you want to allow horizontal or vertical scrolling of the form
respectively, or "0" if not
 SettingsMaintainAspectRatio
If you set this to "1", scaling maintains the aspect ratio of the form. When turned on,
and depending on SettingsAllowHScroll and SettingsAllowVScroll, it may reduce the
scaling factor in one direction, to make the form fit, and center the form vertically or
horizontally as required
 SettingsOnlineMode
whether the app starts in Online mode.
The following settings relate to the Omnis App Server:
 ServerOmnisWebUrl
URL to the Omnis or Web Server. If using the Omnis Server it should be
http://<ipaddress>:<omnis port>. If using a web server it should be a URL to the root
of your Web server. http://myserver.com
 ServerOnlineFormName
route to the form’s .htm file from ServerOmnisWebUrl. So if you’re using the built in
Omnis server, it will be of the form /jschtml/myform.htm. If you are using a web server,
it will be the remainder of the URL to get to the form, e.g. /omnisapps/myform. (Do not
add the .htm extension!)
Only ServerOmnisWebUrl & ServerOnlineFormName are needed for Online forms. The
other Server… properties are for Offline mode.
 ServerOmnisServer
The Omnis Server <IP Address>:<Port>.
 ServerOmnisPlugin
If you are using a web server plugin to talk to Omnis, the route to this from
ServerOmnisWebUrl. E.g. /cgi-bin/omnisapi.dll
 ServerOfflineFormName
Name of the offline form. (Do not add .htm extension!)

285
Chapter 7—Deploying your Web & Mobile Apps

 ServerAppScafName
Name of the App Scaf. This will be the same as your library name.
The remaining parameters refer to test mode.
 TestModeEnabled
whether the app will start in test mode (Ctrl-M on form from Studio to test on device)
 TestModeServerAndPort
the <ipaddress>:<port> of the Omnis Studio Dev version you wish to use test mode
with.
You can also change these parameters by pressing the menu button on the mobile device,
and using the menu options to change them. The app remembers the last setting made via
the menu, so the config.xml lets you set the initial values in the wrapper application.

Access Permission Requests


When you deploy your app and the end user downloads it, the app must request permissions
to access various areas of the device, for example, the app must request access to the device
Contacts, Camera, or Location (GPS) if this functionality is required in your app.
It is considered bad practice and potentially confusing for the end user to include
unnecessary permissions for your app, especially if you are distributing your app through
one of the online app stores. When downloading/installing your app, the user can see which
permissions your app has requested access to, so any unnecessary permission requests may
give the user the impression that your app is malicious and they may not download and use
your app.

Testing Remote Forms in a Wrapper App


During development, you can open a JavaScript remote form in a wrapper application using
the Test Form Mobile (Ctrl-M) option, assuming a wrapper application is setup and enabled
(otherwise you can still test your mobile forms in a desktop browser on your development
computer before you setup the wrapper app). This option appears beneath the ‘Test Form’
option in the remote form context menu. The Test Form Mobile option is only displayed in
the relevant menus when both:
1. A wrapper application is enabled for test form (see the menu of the Android app,
and the system settings for the iOS app)
2. A wrapper application is connected to the Omnis App Server, using the test form
parameters.
The $designshowmobiletitle property determines whether or not the title of a wrapper
application is visible when you use the Test Form Mobile (Ctrl-M) option. For deployment,
config.xml allows you to configure whether or not the title is displayed in the wrapper
application.

286
The JavaScript Serverless Client

The JavaScript Serverless Client


PLEASE NOTE: you will require a new alternative Development license to enable the
$serverlessclient property in a remote form: the property will remain grayed out without
this alternative license.
You can switch a remote form to operate in “Serverless Client” mode in which case your
mobile app can operate entirely without a connection to the Omnis App Server. In order for
a remote form to be available in Serverless or offline mode, you must set its
$serverlessclient property to kTrue.
Any mobile app containing remote forms in serverless client mode have the ability to switch
between “offline” and “online” modes at the user’s request. Separate forms can be used for
the same app in offline/online modes to provide different functionality.
The Serverless Client also includes Local Database support, utilising a SQLite database (or
Ultralite from Sybase), and even provides the ability for your offline form to synchronize an
end user’s local database with an online database. This means that a user could switch to
offline mode while in areas of no or patchy network coverage to continue working, and then
switch back to online mode when back in the office.

How does it work?


The Serverless Client has provision for a local client-side database. This can be used as a
local database for the standalone mode for your app, or it can be used to synchronize with
an online “Consolidated Database” (CDB). In the latter case, the local database is used for
storing tables held in the server-side database and for caching SQL transactions performed
whilst the Omnis App Server is not available.

JavaScript Serverless Client allows forms to work in ‘offline’ mode

The client-side database can be SQLite and the synchronization of the local database with a
“consolidated database” administered by the SQLite Synchronization Server provided by
TigerLogic. Alternatively, you can use an UltraLite database from Sybase on the client and
a MobiLink server to synchronize the data on the backend.

287
Chapter 7—Deploying your Web & Mobile Apps

You can download the ‘SQLite Synchronization Server’ manual from the Omnis website:
www.tigerlogic.com/omnis/download

Serverless Client Methods


All methods running in a Remote form in serverless client mode must be set to ‘Execute on
Client’ (right click the method name in the method editor and select ‘Execute on Client’).
Initialization and Termination Methods
The $construct() and $destruct() methods in a remote form cannot be executed as client
methods, therefore you can create methods with the names $init() and $term() which
perform a similar function that can be executed on the client. The $init() and $term()
methods can be used in standalone apps running inside the JavaScript Client wrapper
application in which all methods must be executed on the client.
The $init() method is called after the form and the client script files have been loaded. This
allows you to do any final initialization of the remote form. The $term() method is called
when a remote form instance destructs.
You can use $cinst.$screensize in client methods, including $init(), to get the current
screensize of the client.

Serverless Client Application Files


The Serverless Client Application File (SCAF) is a SQLite database that contains all of the
resources necessary for a mobile application to run locally in the wrapper in standalone
mode. These resources include JavaScript scripts, CSS files, image files and Omnis remote
forms. There are two SCAF files needed for each wrapper application:
 Omnis SCAF (omnis.db)
files needed to run the JavaScript Client
 Application SCAF (<library_name>.db)
contains all your application files
Omnis Studio will generate these SCAF files automatically in the ‘/html/sc’ folder under the
main Omnis folder. These files need to be placed on the Omnis App Server in the same
location for end users (mobile clients) to access if necessary (see below).
Whenever you save a remote form which has $serverlessclient set to kTrue, it will update
the application files in your Omnis folder. A message is displayed while Omnis exports all
the necessary files.
Deployment of SCAF Files
When the wrapper application is executed for the first time in offline mode it will check if
any SCAF files are bundled with the application (see the wrapper building section for info
on how to do this). If these files exist, they are copied into the application space on the

288
The JavaScript Serverless Client

device and used in the wrapper. Note that bundling SCAF files with the application will
increase the size of the application bundle.
If SCAF files are not distributed with the application the application will attempt to connect
to the Omnis App Server on startup and download the latest versions of the SCAF files.
For the application to know which application SCAF to use the option:
<APPSCAF>name</APPSCAF> (where name is the name of the Omnis library)
is used in the config.xml file within the wrapper application.

Updating SCAF Files


Once the app has been installed onto a device, it will add an entry to the ‘Settings’ app of
the device, with the same name as your app.

The wrapper configuration sub menu “Update Omnis Software Package” contains options
for updating the SCAF files. The available options are:
 Never
the SCAF will never be updated
 Always On Startup
will attempt to connect to the Omnis App Server and update the SCAF files every time
the application is run
 Next Startup Only
will attempt this update only on the next execution of the wrapper application
It is also possible for the end-user to update the SCAF from inside the app by swiping down
the screen to open the runtime menu and selecting the appropriate menu item.

289
Chapter 7—Deploying your Web & Mobile Apps

Database Support
The JavaScript wrapper application contains embedded support for SQLite (or UltraLite
from Sybase) and provides client-executed methods with access to a local private SQL
database. The database can currently only be used by Serverless Client applications in
offline mode, inside the wrapper application on Android, iOS, and BlackBerry.
All interactions between the JavaScript Client and the wrapper will be asynchronous, so the
database API also takes this into account.

Schema and Query Classes


The JavaScript Client-executed method code generator restricts the $definefromsqlclass()
method for use with either a query or a schema class name as the first argument although it
is still possible to pass a subset of column names required using parameter two onwards.
This will allow for example:
Do listOrRow.$definefromsqlclass(‘SchemaName’)
and the code generator will expand this into JavaScript to define the list or row with the
columns from the schema.

Data Types
When creating rows to be used for bind variables, it is important that the data types of the
columns in the row match those in the database.
Client methods only provide a ‘var’ data type when creating variables, which will generally
be interpreted as Character type. As such, it is safest to manually add columns to your row,
using the function:
Do lRow.$cols.$add(<name>,<data type>,<data subtype>,[<length>])
e.g.:
Do lRow.$cols.$add(‘Age’,kInteger,kShortint)

The SQL Object


A Serverless Client application gains access to the embedded database using a SQL Object,
which in this case is a property of the current remote form called $sqlobject:
$cinst.$sqlobject

For example:
Calculate oVar as $cinst.$sqlobject
All requests to the SQL object are asynchronous (except $getlasterrortext and
$getlasterrorcode), and call a client-executed completion method ($sqldone) in the current
remote form instance upon completion. Each request returns an identifier when called and
the same identifier is passed as a parameter to the completion method, allowing the request

290
The JavaScript Serverless Client

to be identified. Thus, multiple requests may be in progress “simultaneously”, although they


will only execute serially in the wrapper.
Note that you do not need to provide a $sqldone() method although if you do not, errors
may be ignored. On success, the returned unique identifier is positive. A negative value
indicates an error code.
In the following sections, oSQL is a Var containing the SQL object returned by
$cinst.$sqlobject.
$getlasterrortext()
Do oSQL.$getlasterrortext() Returns lErrText
Returns the error text of the last operation. “OK” implies success.
$getlasterrorcode()
Do oSQL.$getlasterrorcode() Returns lErrCode
Returns the error code of the last operation. 0 implies success.
$selectfetch()
Do oSQL.$selectfetch(cSQL, lBindVars, iFetchCap) Returns id
Executes a statement with a result set (typically select or select distinct) and fetches the
initial set of rows.
 cSQL
is the statement. This may be hand-coded, or the result of $select/$selectdistinct for a
schema or query class. cSQL can contain bind variable place-holders in the form
@[column_name], where column_name is the name of a column in lBindVars.
 lBindVars
is a row variable referenced by one or more bind variable markers in the SQL text.
 iFetchCap
is the number of rows to initially fetch (this can be kFetchAll to fetch all rows in the
result set).
For all object methods, note that lBindVars may contain columns not referenced by the SQL
text. Only those columns referred to by name in the bind place holders will be read.
On completion, $sqldone() is called with the following parameters:
 The request id (as returned by $selectfetch)
 A list containing zero or more rows from the initial result set.
At this point it is your responsibility to copy or populate the appropriate form controls to
display the data.

291
Chapter 7—Deploying your Web & Mobile Apps

Example1:
Do iList.$definefromsqlclass(‘myQuery’)
Do oSQL.$selectfetch($clib.$queries.myQuery.$select, iList, 100)
Returns id
Example2:
Do oSQL.$selectfetch(‘select * from Table1 where age=@[age]’,
lBindVars,100) Returns id

$fetch()
Do oSQL.$fetch(selectfetchid, iFetchCap) Returns id
Fetches more rows from the result set generated by a $selectfetch()
 selectfetchid is id returned by $selectfetch().
 iFetchCap is the number of rows to fetch.
In this case, the returned id will be the same. On completion, $sqldone() is called with the
following parameters:
 The request id (as returned by $selectfetch)
 A list containing zero or more further rows from the result set.
$insert()
Do oSQL.$insert(cSQL, listorrow) Returns id
Inserts one or more rows into a database table.
 cSQL is the insert statement. This may be hand-coded, or the result of $insert for a
schema class. cSQL can contain bind variable place-holders in the form
@[$column_name], where column_name is the name of a column in listorrow.
 listorrow is the list or row containing the data to insert.
On completion, $sqldone() is called with the following parameters:
 The request id (as returned from $insert()).
Example:
Do oSql.$insert("INSERT INTO Product (name, quantity) VALUES
(@[colName],@[colQuant])",lBindVars) Returns IDinsert

$delete()
Do oSQL.$delete(cSQL, row) Returns id
Deletes zero or more rows from a database table.
 cSQL is the delete statement. This may be hand-coded, or the result of $delete() for a
schema class. cSQL can contain bind variable place-holders in the form
@[column_name], where column_name is the name of a column in row.

292
The JavaScript Serverless Client

 row contains the values referenced by the bind variable place-holders.


On completion, $sqldone() is called with the following parameters:
 The request id (as returned from $delete()).
$update()
Do oSQL.$update(cSQL, newRow, oldRow) Returns id
Updates zero or more rows of a database table.
 cSQL is the update statement. This may be hand-coded, or the result of $update for a
schema class. cSQL can contain bind variable place-holders in the form
@[$column_name], where column_name is the name of a column in newRow or
oldRow. If the bind variable is used in the SET clause, it will come from the newRow
variable, if it is used in the WHERE clause, it will come from the oldRow variable.
 newRow is the row containing the values referenced by the bind variable place-holders
of the new values, i.e. those specified in the SET clause.
 oldRow is the row containing the values referenced by the bind variable place-holders
of the old values, i.e. those specified in the WHERE clause.
On completion, $sqldone() is called with the following parameters:
 The request id (as returned from $update()).
$execute()
Do oSQL.$execute(cSQL) Returns id
Executes a SQL statement that does not return a result set, intended for use with DDL
administrative commands such as CREATE, DROP and ALTER.
 cSQL is the SQL statement to be executed. Note that bind variable place holders are
not supported.
On completion, $sqldone() is called with the following parameters:
 The request id (as returned from $execute()).
The following methods may be used to obtain database meta-data:
$selecttables()
Do oSQL.$selecttables() Returns id
Retrieves table names defined in the local database.
On completion, $sqldone() is called with the following parameters:
 The request id (as returned from $selecttables()).
 Single-column list containing the TableName of each table in the local database.

293
Chapter 7—Deploying your Web & Mobile Apps

$selectcolumns()
Do oSQL.$selectcolumns(tableName) Returns id
Retrieves column names and type information for the specified table.
On completion, $sqldone() is called with the following parameters:
 The request id (as returned from $selectcolumns ()).
 A list describing the table column definitions, defined with the following columns:
ColumnName - name of the table column.
SqlType - name corresponding to the column’s SQL data type.
ColumnSize - the size of a variable-length data type, e.g. for CHAR and BINARY.
Precision - the numeric precision for a NUMERIC column. Zero for others.
Scale - the numeric scale for a NUMERIC column. Zero for others.
Default - the default value that was assigned to the column when the table was created.
$selectindexes()
Do oSQL.$selectindexes(tableName) Returns id
Retrieves column index information for the specified table.
On completion, $sqldone() is called with the following parameters:
 The request id (as returned from $selectindexes ()).
 A list describing the table column definitions, defined with the following columns:
IndexName - name of the index.
ColumnNames - comma-separated list of column names used by the index.
PrimaryKey - kTrue if the index was created with the PRIMARY KEY clause.
Unique - kTrue if the index was created with the UNIQUE clause.

Database Synchronization
The SQL object provides two further methods that facilitate dynamic synchronization with a
third-party synchronization server. The embedded UltraLite database requires connection to
a Sybase Mobilink server. This is installed as part of SQLAnywhere 12.01
Please refer to the Mobilink User Guide
(http://download.sybase.com/pdfdocs/awg0901e/dbmlen9.pdf) for guidance on:
 Setting-up the MobiLink Synchronization server.
 Configuring MobiLink users, tables and scripts.
 Creating a Consolidated Database and Installing Mobilink system tables.
The user guide also provides a useful first-steps tutorial that should prove useful. As a
quick-start guide, following lessons 1-5 in the following tutorial should get you to a point at
which you can test synchronization with the wrapper:
http://dcx.sybase.com/1201/en/mlstart/ml-sc-tutorial.html

294
The JavaScript Serverless Client

$syncinit()
Do oSQL.$syncinit(syncParams) Returns id
Initializes synchronization with the (MobiLink) synchronization server. Synchronization
parameters are implementation-specific and supplied via a row variable. If synchronization
initialization is successful, an initial ‘sync’ is also performed. See $sync() for details.
The UltraLite module currently recognizes the following parameters:
Username – MobiLink synchronization user name.
Password – MobiLink synchronization user password, if required.
NewPassword – Allows the MobiLink user to change password to NewPassword, if
supplied.
Version – Determines which script version to use for various synchronization actions.
Stream – Determines the network protocol to be used, e.g. tcpip
StreamParams – Allows protocol-specific connection parameters to be supplied, e.g. host
Publications – Lists the MobiLink publications to which the user is subscribed.
AdditionalParams – A string of name=value; pairs specifying any additional parameters.
Ping – If present, confirms communication with the Mobilink Server only. No
synchronization occurs.
UploadOnly – If present, no changes are downloaded from the CDB, only uploads are
processed.
DownloadOnly – If present, no changes are uploaded to the CDB, only downloads are
received.
ResumePartialDownload – If present, UltraLite resumes a failed download only. No
upload occurs.
On completion, $sqldone() is called with the following parameters:
 The request id (as returned from $syncinit ()).
Example:
Calculate config as row(Username,Version,Stream,StreamParams)
//define using local variables
Do
config.$assigncols(‘ml_sales2’,’default’,’tcpip’,’host=192.168.0.
10’)
Do oSQL.$syncinit(config) Returns id

$sync()
Do oSQL.$sync() Returns id
Once synchronization has been initialized using $syncinit(), $sync() performs ad-hoc
synchronization between the (UltraLite) database and the (MobiLink) synchronization
server. If it is required to modify the synchronization parameters, $syncinit() may be called
instead since this also performs synchronization on successful initialization.
On completion, $sqldone() is called with the following parameters:

295
Chapter 7—Deploying your Web & Mobile Apps

 The request id (as returned from $sync ()).


UltraLite Database Support
To use UltraLite offline storage and Mobilink device synchronization as described above,
the mobile device application is linked with the dbUltraLite library in addition to the
JavaScript wrapper application.

SQLite Database Support


The SQLite offline storage and synchronization process uses a SQLite database on the
remote client device in place of Sybase UltraLite. More specifically, SQLite
synchronization relies on SQLite databases on the server and on each client device to store
user tables as well as synchronization status info. The SQLite Synchronization Server uses
these tables to pass data to/from each synchronization client and to forward synchronization
requests on to the Consolidated Database (CDB). The SQLite Synchronization process is
described in the ‘SQLite Synchronization Server’ manual which you can download from the
Omnis website: www.tigerlogic.com/omnis/download
To use the SQLite database object in place of the UltraLite database object, the mobile
device application is linked with the dbSQLite library in place of the dbUltraLite library.
Other than this, operation and use of the SQL object remains essentially the same. The
SQLite initialization parameters differ slightly, as shown below.

$syncinit()
Do oSQL.$syncinit(syncParams) Returns id
The SQLite module currently recognizes the following parameters:
Username – The synchronization user name (defined at the synchronization server).
Password – The synchronization user password (defined at the synchronization server).
HostString – Omnis Web-thin Client URL to the SQLite Synchronization Server.
Timeout – The timeout in seconds for synchronization operations.
On completion, $sqldone() is called with the following parameters:
 The request id (as returned from $syncinit ()).
Example:
 Do config.$define(Username, Password, HostString, Timeout)
;;define using local variables
 Do config.$assigncols(
‘user1’,’xxxxxx’,’http://192.168.0.10:7001/ultra?
OmnisClass=rtSync&OmnisLibrary=SyncServer’, 5)
 Do oSQL.$syncinit(config) Returns id
Please refer to the ‘SQLite Synchronization Server’ manual for information on the design,
implementation and usage of the synchronization server. You can download this manual
from the Omnis website (www.tigerlogic.com/omnis).

296
The JavaScript Serverless Client

No Database Support
If the remote client application does not require database support, the application can
instead be linked with the dbNoSQL library. This library provides stub definitions for the
database API calls required by the wrapper application. Note that in this mode however, any
calls to the SQL object will fail.

JavaScript Client Wrapper Application


The wrapper encapsulates a WebView which hosts
the JavaScript Client application. The wrapper
initializes using the supplied config.xml file which
also informs the wrapper of the HTML page to load
for the application.
The wrapper can be configured to connect to the
Omnis IDE as a client for testing purposes. This is
achieved via the Test Mobile Form menu option in
the Studio IDE. The wrapper also provides device-
independent access to features such as GPS, the
camera and audio interface using the Device Control
(see the JavaScript Components chapter for details
about accessing device features).
To support Serverless operation, the WebView runs
local scripts that contain client executed methods.
Before you compile the app, you will need to customize the config.xml file.
When the client operates in online mode it uses the URL parameter from the config file to
load the remote form and the wrapper behaves like a standard JavaScript application. If the
client is to run offline however, the other config parameters are used to allow the wrapper to
(optionally) update its local copy of the application, or to run the forms locally.

iOS Wrapper Project


The iOS wrapper project has three targets, with differing local database support. These are:
 OmnisJSWrapper – No local database support.
 OmnisJSWrapper_SQLite – SQLite is used for local database support.
Synchronization with a back-end server is still under development, but is expected to be
available in the next release.
 OmnisJSWrapper_UltraLite – UltraLite is used for local database support. Uses
MobiLink for synchronization, as in Beta 1.

297
Chapter 7—Deploying your Web & Mobile Apps

UltraLite
Please note that, due to licensing restrictions, we are unable to ship the libulrt.a file, on
which the UltraLite target depends. As such, if you wish to build the UltraLite version of the
wrapper, you will first have to compile this file yourself.
In order to do this, you should install SQLAnywhere12. In the SQLAnywhere12
installation’s ultralite/iphone directory you will find the source code etc, and a readme file
which should guide you through the build process (Please note that we offer no support for
the compilation of this file).
Once you have built the libulrt.a (for device or simulator), you should drop it into the
appropriate folder (-iphoneos or –iphonesimulator) in the wrapper project’s dbInterface
directory. The project should now build successfully.

Accessing Mobile Device Features


The wrapper application allows your mobile apps to access hardware and software based
services on the end user’s mobile device, such as a smartphone or tablet. Access to these
mobile device features is available using the Device Control, available in the Component
Store when you design a JavaScript based remote form. See the JavaScript Components
chapter for more information about the Device control.

298
Index

Index
#ERRCODE, 83 $commandid, 86
#ERRTEXT, 83 $commitanimations, 67, 98
#F, 77 $communicationaddress, 138
#ICONS, 164 $communicationdata, 138
$action, 138 $connectbytessent, 60
File control, 148 $connectionid, 61, 251
$activitystyle, 120 $connectiontime, 61
$add $construct, 99, 154
Remote forms, 69 For complex grids, 128
$addcolorcss, 131 iOS forms, 190
$addcols(), 155 Parameters, 263
$alpha, 66 Row variable, 57
$alwaysenabledobject, 166 Subforms, 172
$animation, 121 Tasks, 57
$apikey, 158 Ultra-thin Omnis, 244
$attr, 121 $construct()
$autoscroll, 114 Remote tasks, 247
$backalpha, 66 $contact... properties, 143
$backcolor, 66 $container, 173
$backpattern, 66 $contenttip, 126, 147
$barcodeimage, 138 $contextmenu, 86
$barends, 122 $cssclassname, 115
$baseedgewidth, 175 $ctask
$beginanimations, 67, 98 Remote forms, 70
$borderradius, 114, 146 $ctrlname, 150
$buttonbackiconid, 124 $currentcolumn, 130
$cancelkeyobject, 66 $currentnodeident, 181
$canclose, 251 $currentpage, 163, 164
$changeform, 59 $currenttab, 174, 175
$chartdirection, 122 $customlink, 120
$classname, 171 $datamode, 177, 178
$client, 184 $dataname
$clientaddress, 61 Components, 110
$clientcommand, 67, 70, 104 Droplists, 145
Subform sets, 87 Edit control, 146
$colenabled, 165 File control, 148
$coltext, 165 For charts, 123
$columncount, 167 For check boxes, 125
$columndatacol, 130 For combo boxes, 126
$columnmode, 131, 132 For complex grids, 128
$columnnames, 130 For data grids, 130
$columnnumberformat, 132 Hyperlinks control, 153
$columnpicklist, 131 Lists, 154
$columnwidths, 130 Page pane, 164

299
Index

Picture control, 164 $iconset, 118


Rich text editor, 169 $init, 76, 81, 288
Subforms, 172 $initiallefticonid, 161
Tree lists, 177 $initiallefttext, 161
$datestyle, 135 $initialrighticonid, 161
$defaultline, 145 $initialrighttext, 161
$defaulttext, 126, 145 $initialtitle, 161
$designcols, 130 $iremoteforms, 70
$designshowmobiletitle, 64, 188 $ischecklist, 154
$designtaskname, 55 $ispassword, 146
$deviceimage, 138 $issecure, 62, 244, 277
$disabledefaultcontextmenu, 86 $issingleline, 146
$dragborder, 95 $jscustomformat, 111
$edgefloat, 94 $jsdisplayformat, 111
$effect, 147, 163 $jslocaltime, 100
$encrypt, 103 $keyeventdelay, 156
$enterable, 130 $lastresponse, 61
$evenrowcolor, 154 $latlong, 158
$event, 147, 157 $lefthidden, 161
JavaScript components, 115 $legendpos, 123
Slider, 170 $linkedobject, 147, 157, 163
$event() Navbar, 161
Tasks, 62 Page control, 163
$event() method, 75 Tab control, 174
$events, 74, 115, 148, 160 $listcolumn, 126, 145
iOS, 199 $listname, 126, 165
$extendable, 130 $mapmarkers, 159
$fixedtabsize, 174 $maptype, 158
$flowplayerline, 183 $max, 166, 170
$flowplayerurl, 183 $maxfixedtabsize, 174
$flyout, 123 $maximize, 67
$forecolor, 66 $maxtime, 61
$formatheader, 132 $maxusers, 62
$hasheader, 130 $maxvalue, 167
$headertext, 130 $mediatype, 164
$height, 188 $menuname, 165
$horizontal, 167 $menupos, 165
$horzscroll, 64, 114 $min, 170
$hot properties $minimize, 67
Trans button, 176 $minvalue, 167
$hottitleclicks, 165 $movetab, 174
$hotwhenmouseover, 165 $multipleclasses, 172
$hscroll, 133, 155 $name, 110
$html, 152 $negallowed, 147
$hyperlinkurl, 149 $nodeaction, 177, 180
$iconid, 116, 164, 165 $nodedata, 177, 180
For buttons, 124 $nodeiconlist, 180
$iconpages $numberformat, 113
iOS, 196 $okkeyobject, 66

300
Index

$openform, 59 $subinst, 172


$order, 65 $switchoff, 173
$pagecount, 163 $switchon, 173
$pancontrol, 159 $systemkeys, 156
$picturealign, 164 $tabborderradius, 174
$progresscolor, 166 $tabcount, 174
$push, 161 $tabenabled, 174
$redraw, 68 $tablayout, 174
$remotemenu, 67 $tabmenu, 175
$reportfile, 101 $tabsjst, 174
$reqcurbytesreceived, 61 $tabtext, 174
$reqcurbytessent, 61 $tabvisible, 174
$reqmaxbytesreceived, 60 $term, 288
$reqmaxbytessent, 61 $text, 124, 125
$reqtotbytesreceived, 60 $textbeforeicon, 124
$reqtotbytessent, 60 $timeout, 61
$requests, 60 $timervalue, 176
$resizemode, 93 $timeslice, 266
$righticonid, 161 $trackmenus, 175
$righttext, 161 $uppercase, 147
$running, 176 $usehtmlselect, 165
$scalecontrol, 159 $userdefined, 131
$screensize, 44, 64, 94 $useseconds, 176
iOS, 188 $val, 170
$screensizefloat, 110 $value, 166
$scrolltochangepage, 163 $vertscroll, 64, 114
$selectedlinecolor, 154 $visible, 149
$selectedlinesonly, 157 $vscroll, 133, 155
$selectedtab, 174 $webbrowser, 82
$sendcarryon, 166 $width, 188
$senddata, 68 $youtube, 182
$serverlessclient, 287 $zoom, 158
$serverlessclientstringtable, 257 $zoomcontrol, 159
$serverport, 82, 266 80, port setting, 266
$serverstacks, 266, 267 Activation, 266
$setcurfield, 67 Activity Control, 120
$setdocinfo, 103 Amend Startup Task option, 56
$settemp, 102 Animations, 98
$showcontrols, 169 Apache Server Extension, 274
$showmessage, 68, 69 Application SCAF, 288
$showurl, 68 Application wrappers, 260
$showvalue, 122 Apps Gallery, 109
$side, 174 assignpdf, 104
$soundname, 138 Background Control, 120
$sqlobject, 67, 290 Animation, 121
$startfield, 65 Bar Charts, 122
$streetviewcontrol, 159 Lists, 123
$stringtable, 256 Barcode Device Action, 141
$stringtablelocale, 112 Beep Device Action, 141

301
Index

Begin critical block command, 269 Context menus, 86


Borders CSS folder, 264
JavaScript components, 114 CSS styles, 115
br(), 98 Data Grid Control, 130
Button Control, 124 Data Grids
Calendar Pick List, 131
Date Picker, 135 Database
Call Device Action, 145 Session, 52
Cell formatting Database sessions
Data grids, 131 Opening a database session, 13
Checkbox Control, 125 data-commstimeout, 263
Circles, 120 data-omnisclass, 263
Class Wizard data-omnislibrary, 263
Remote form, 49 data-omnisserverandport, 262
classname, 172 data-param1..., 263
Client commands, 70 data-webserverurl, 262
javamessage, 71, 72 Date format, 72
lockui, 73 Date formatting, 111
noyesmessage, 71 Date functions, 112
okcancelmessage, 71 Date Picker Control, 135
savepreference, 72 Dates, 99
setcustomformat, 72 Debugging
yesnomessage, 71 Client methods, 77
Client connections, 61 Debugging remote forms, 83
Client messages, 69 Default list
Client methods, 76 Combo boxes, 126
Data types, 78 Default web browser, 82
Debugging, 77 Deployment, 260
Execute on Client, 76 Device App
JavaScript, 76 iOS, 236
Serverless mode, 288 Device control
Client objects, 80 Properties, 138
Client preferences, 72 Device Control, 137
Combo Box, 126 $action, 138
Command ID Wrapper app, 137
Remote menus, 86 Downloading files, 149
Complex Grid, 128 Droplist Control, 145
Component properties, 110 Dynamic tree lists, 178
Component resizing, 94 Ease transition effects
Component Store, 21, 53, 108 Background control, 122
iOS, 186 Edit Control, 146
Components Events, 147
JavaScript, 108 Edit fields, 146
config.xml, 283 End critical block command, 269
Construct row variable, 57 errcode(), 83
Contacts data structure errtext(), 83
Device Control, 143 evAfter, 116, 147
Contacts Device Action, 143 evAnimationsComplete, 73
Content Tips, 147 evBarClicked, 123

302
Index

evBarcodeFailed, 140 evSubFormToTop, 74


evBarcodeReturned, 140 evTabSelected, 175
evBefore, 116, 147 evTimer, 176
evBusy, 60, 62 evUserChangedPage, 163
evCarryOn, 166 Execute on Client, 75, 76
evClick, 115, 116 Fav icon, 264
evClickInitialLeftButton, 161 File Control, 148
evClickRightButton, 161 Firefox
evCollapseNode, 181 Testing forms, 84
evContactsFailed, 140 Flag, 77
evContactsReturned, 140 flag(), 77
evDateChange, 137 Flowplayer, 183
evDoubleClick, 116 Fonts
evEndSlider, 170 PDF printing, 101
Event handler, 96 Formatting
Event methods, 75 Date and Time, 111
Execute on Client, 75 Number, 113
Event parameters, 74 GET method, 241
Events GET requests, 241
$events, 74 Google map, 158
Enabling, 115 API key, 158
JavaScript components, 115 GPS Device Action, 142
Remote forms, 73 Gradients, 66
Remote tasks, 62 Grids
evExecuteContextMenu, 74, 86 Complex Grid, 128
evFormToTop, 73 Data grids, 130
evGpsReturned, 140 high definition
evIdle, 60, 62 Icons, 116
evImageFailed, 140 Host name, 11
evImageReturned, 140 Hosting
evKeyPress, 147, 156 ISP, 276
evLoadNode, 180 HTML file, 49
evMapClicked, 160 html folder, 261
evMapMoved, 160 HTML folder, 81
evMapZoomed, 160 HTML forms, 241
evMarkerClicked, 160 HTML Object, 150
evNewValue, 170 HTML Pages
evOpenContextMenu, 74, 86 JavaScript Client, 261
evPageChanged, 163 HTML test page, 81
evPhotoFailed, 140 HTTP headers, 250
evPhotoReturned, 140 HTTPS, 61, 244, 277
evPopFinished, 162 Hyperlink Control, 153
evPost, 251 iActivity Control, 200
evPushFinished, 162 iButton Control, 201
evRejected, 62 Icon sets, 118
evRenamed, 178 Icons
evScreenOrientationChanged, 74, 75, 198 JavaScript components, 116
evSegmentClicked, 123 Icons folder, 116
evStartSlider, 170 iDateTime Control, 201

303
Index

iImageView Control, 202 Serverless Client mode, 287


iLabel Control, 204 Standalone Apps, 282
Image Device Action, 142 JavaScript components, 108
images folder, 264 Events, 115
iMap Control, 204 Examples, 109
iMultiLineEdit Control, 212 Icons, 116
iNavigationbar Control, 213 Naming, 110
Inserting data, 26 JavaScript Components, 54
iOS JavaScript controls, 108
Client commands, 194 JavaScript files
Component Icons, 192 Client methods, 76
Components, 187 JavaScript messages, 71
Remote forms, 186 JavaScript objects, 80
Screen size, 188 JavaScript working message, 264
iOS Client, 184 JavaScript: command, 95
Configuration file, 240 jsctempl.htm, 262
Deploying iOS apps, 240 JStimezoneOffset, 99
Testing, 237 kClientiOS, 184
iOS Components, 200 kDevOmnisPDF, 101
iOS Developer Program, 185, 235 kEsc constants, 97
iOS Form, 186 Key presses, 156
iOS forms kFormatCustom, 111
Events, 198 kJSDataGridModeAuto, 132
Methods, 197 kJSDataGridModeCustomFormat, 131
Testing, 238 kJSDataGridModeDropList, 131
iOS Forms kJSDataGridModeFormatted, 132
Properties, 196 kJSDatePickerStyleCalendar, 135
iPage Control, 215 kJSDeviceActionBeep, 141
iProgress Control, 216 kJSDeviceActionGetBarcode, 141
iSearchBar Control, 217 kJSDeviceActionGetContacts, 143
iSegmented Control, 219 kJSDeviceActionGetGps, 142
iSingleLineEdit Control, 221 kJSDeviceActionGetImage, 142
iSlider Control, 223 kJSDeviceActionMakeCall, 145
ISP web hosting, 276 kJSDeviceActionSendSMS, 145
iSwitch Control, 223 kJSDeviceActionTakePhoto, 142
iTabbar Control, 224 kJSDeviceActionVibrate, 142
iTable Control, 228 kJSFileActionDownload, 148, 149
iToolbar Control, 231 kJSFileActionUpload, 148
iWebView Control, 233 kJSFormat... constants, 111
Java Servlet, 275 kJSformResizeModeAspect, 93
JavaScript, 48 kJSformResizeModeCenter, 93
Running in the client, 95 kJSformResizeModeFull, 94
JavaScript client kJSformResizeModeNone, 93
Database access, 268 kJSMapTypeHybrid, 158
JavaScript Client kJSMapTypeRoad, 158
HTML Pages, 261 kJSMapTypeSatellite, 158
Localization, 255 kJSMapTypeTerrain, 158
Object, 262 kJSMapZoomDefault, 159
Object parameters, 262 kJSMapZoomLarge, 159

304
Index

kJSMapZoomOff, 159 $event, 160


kJSMapZoomSmall, 159 Events, 160
kJSTreeActionAdd, 181 iOS, 204
kJSTreeActionCollapse, 180 Menus
kJSTreeActionDelete, 181 Remote form, 85
kJSTreeActionExpand, 180 Tab menus, 175
kJSTreeActionRename, 180 Method stacks, 267
kJSTreeDynamicLoad, 178, 180 Mobile
kJSTreeFlagDiscardOnCollapse, 179 Screen size, 44
kJSTreeFlagEnterable, 179 Testing forms, 83
kJSTreeFlagExpanded, 179 Testing your form on a mobile device, 44
kJSTreeFlagHasChildren, 179 Monitor task wizard, 56
kJSTreeFlatList, 178 Multipart form data, 252
kJSTreeFlatListOld, 178 Multi-threaded server, 267
kJSTreeFlatListOldWithTags, 178 Navbar, 161
kJSTreeFlatListWithTags, 178 Navigation Bar Control, 161
kSSZDesktop, 63 Negative numbers, 147
kSSZiOS320x480Landscape, 188 New page browser prompt, 81
kSSZiOS320x480Portrait, 188 NewiOSRemoteForm, 186
kSSZiOS768x1024Landscape, 188 No/Yes messages, 71
kSSZiOS768x1024Portrait, 188 Number formatting, 113
kSSZjs320x480Landscape, 63 Number validation
kSSZjs320x480Portrait, 63 Data grids, 130
kSSZjs768x1024Landscape, 64 Numeric data entry, 147
kSSZjs768x1024Portrait, 64 Ok/Cancel messages, 71
Labels, 153 Omnis
Licensing, 265 Starting Omnis, 8
Lines, 120 Omnis App Server, 261
Linked Lists, 155 Setting up, 265
Linux, 261 Omnis SCAF, 288
List Control, 154 Omnis server
List scrolling, 155 Load sharing, 271
Lists, 154 Omnis Server
Adding columns, 155 Commands, 269
Linked lists, 155 Multi-threaded, 267
Load sharing, 271 Port number, 266
Load Sharing OmnisClass parameter
Enabling, 272 for direct access, 242
Load sharing mechanism, 273 OmnisLibrary parameter
Local time, 100 for direct access, 242
Localization, 255 omnisobject, 262
Localizing Error Strings, 257 Positioning, 263
Locking the UI, 73 OmnisServer parameter
loctoutc(), 99 for direct access, 242
Map Control, 158 Load sharing, 271
Map location, 158 ordervar
Map markers, 159 Subform sets, 91
Map type, 158 Orientation
Maps, 158 Remote forms, 74

305
Index

Screen, 63 Quit method <error>, 250


Page Control, 163 Quit method <url>, 247
Page Pane Radio buttons, 167
iOS, 215 RadioGroup Control, 167
Paged Pane, 163 RdtaServlet, 275
Tabs, 174 Rectangles, 120
pBar, 123 Remote form classes, 48
pCommandID, 86 Remote form instances, 70
pContextMenu, 86 Remote forms
PDF printing, 100 $add, 69
assignpdf, 104 $event() method, 75
Fonts, 101 Changing forms, 59
showpdf, 104 Debugging, 83
Persistent remote tasks, 251 Events, 73
Photo Device Action, 142 Height, 64
PICSESS, 12 HTML page, 81
Picture Control, 164 Instances, 67
Pictures iOS Client, 186
Inserting, 26 JavaScript, 48
Pie Charts, 122 Localization, 256
Lists, 123 Methods, 67
pKeyList, 156 Multiple forms, 59
Plain Remote Task, 55 Naming, 49
Plain task wizard, 56 Orientation, 74
pLinenumber, 165 Properties, 63
pLineNumber, 126, 145, 154 Redraw, 68
pNewVal, 125 Resizing, 93
pNodeIdent, 178 Test on Mobile, 83
pNodeTag, 178 Testing, 81
Popup Menu Control, 165 Troubleshooting, 84
Popup menus, 165 Width, 64
Port number, Omnis Server, 266 Wizards, 49
POST method, 243, 244 Remote Forms
pParams, 263 Testing in a Wrapper, 286
pPieSegment, 123 Remote menu class, 85
pPostData, 251 Remote menu classes, 85
pPostResult, 251 Remote menus, 85, 175
pragma:nocache, 250 Remote task instances, 56
Preferences, 72 Remote task wizards, 55
Printing Monitor, 56
PDF, 100 Plain, 56
Progress Bar Control, 166 Remote tasks, 48, 50, 55
Property Manager, 21, 53, 63, 110 $construct(), 247
pSliderValue, 170 Client access, 60
pTabNumber, 175 Construct row variable, 57
Pushbuttons, 124 Events, 62
Python HTML forms, 241
PDF printing, 100 Messages, 69
Quit method <data>, 247 Persistant, 251

306
Index

Plain Remote Task, 55 Styles


Troubleshooting, 84 for text, 97
Wizard, 55 Subform Control, 171
Resizable forms, 93 Subform sets, 87
Resizing components, 94 Subforms, 171
Rich Text Editor Control, 169 $construct, 172
SCAF, 288 $container, 173
Schema classes, 16, 51 $multipleclasses, 172
Screen sizes, 63 Caching, 172
screensize property, 44 Notation, 173
scripts folder, 264 Subform sets, 87
Scrolling subformset_add, 88
Autoscrolling, 114 subformset_formadd, 89
Data grids, 133 subformset_formremove, 90
Secure sockets, 61, 244, 277 subformset_formtofront, 90
Security, 61 subformset_remove, 89
Send to trace log command, 83 Switch Control, 173
Server Configuration, 266 Tab Control, 174
Server stacks, 266 Tab icons, 174
Serverless Client, 287 Tab menus, 175
Application Files, 288 Tabbing order, 65
Database Support, 290 Tables
Database Synchronization, 294 iOS, 228
Methods, 288 tabmenu… properties, 175
SQL Object, 290 Tabs, 174
Session pools, 270 Task properties, 60
Sessions, 52 Test Form Mobile, 286
showpdf, 104 Testing remote forms, 81
Simulator App Text editor, 169
iOS, 236 Text styles, 97
Slider Control, 170 Time formatting, 111
Smart lists, 155 Time zones, 99
SMS Device Action, 145 Time Zones, 137
Socket binding, 274 Timeouts, 61
Sounds Timer Control, 176
Playing sounds, 72 Timeslice, 266
SQL JavaScript Form wizard, 50 Toolbars
SQL Object iOS, 231
Serverless Client, 290 Trace log, 83
SQL sessions, 270 tracelog() function, 83
Standalone apps Trans Button Control, 176
config.xml, 283 Transparency, 66
Standalone Apps, 282 Tree Control, 177
Start server command, 268, 269 Tree lists, 177
stgettext(), 257 $datamode, 178
Stop server command, 268, 269 $dataname, 177
String Tables, 255 Data format, 178
style(), 97 Dynamic, 178
styledtohtml(), 131 Events, 178

307
Index

Node actions, 180 Installation, 274


TSV format, 255 Web Server Plug-in
tzcurrent(), 100 Custom Configuration, 277
tzstandard(), 100 Wifi connections, 263
UDID, 191 Window editor, 21
Ultra-thin Omnis, 241 Wizards
Uploading files, 148 Remote task, 55
Uppercase, 147 SQL JavaScript Form, 50
user.css, 115 Wrapper
utctoloc(), 99 Device Control, 137
Var data type, 78 Wrapper Applications, 283
Vibrate Device Action, 142 config.xml, 283
Video Xcode, 185, 236
HTML5, 182 Yes/No messages, 71
Video Control, 182 Yield to other threads command, 270
Web browser YouTube
Default, 82 Video control, 182
Web Server, 261 Zoom level, 158
Web server plug-in

308

You might also like