Skip to main content

Overview of Zen Mojo

This chapter provides an overview of Zen Mojo and its central concepts. It discusses the following topics:

If you are familiar with Zen, you will find some of these concepts familiar. You can, however, create Zen Mojo applications without having any familiarity with Zen.

Important:

If you were a member of the Zen Mojo beta program, see the appendix “Upgrade Steps for Beta Program Customers.”

Introduction to Zen Mojo

Zen Mojo is a set of classes that enable you to create web pages, suitable for either mobile devices or desktops. Zen Mojo presents the following key features:

  • The architecture is designed to minimize how often pages must be loaded, so that you can avoid this expensive operation. You can radically alter a single page without reloading it.

  • All communication between the client and the server is packaged as JSON, which is an extremely lightweight format that consumes little bandwidth.

  • Zen Mojo pages automatically generate HTML 5.0, which is supported by browsers on all modern mobile devices.

    You can include custom HTML if needed, but in general it is not necessary to write HTML.

  • Via its plugin technology, Zen Mojo provides easy access to common, familiar third-party JavaScript libraries. Rather than needing to write complex JavaScript code that renders layout objects, you can create much simpler JavaScript objects that simply describe the desired layout.

    You can also extend Zen Mojo by creating your own plugins to use additional third-party libraries.

  • Zen Mojo provides a rich set of tools that you can use to modify the page in response to user actions.

In a Zen Mojo application, your classes define both client methods and server methods, and the client methods are much more common. A client method is written in JavaScript and runs in the browser. A server method is written in one of the Caché server-side languages, typically Caché ObjectScript.

Useful Background Knowledge

To create web pages with Zen Mojo, it is necessary to know JavaScript, CSS, and some Caché ObjectScript.

It is assumed that you are reasonably familiar with one or more of the JavaScript libraries used by the Zen Mojo plugins.

If you are creating a hybrid application (see the next section), it is necessary to be acquainted with PhoneGap, a third-party tool not described in this book.

It is also helpful if you can read extremely simple and short XML documents, and if you know the XML terms element, attribute, and namespace. If you have not been exposed to XML, however, just carefully mimic the format of the XML documents presented in this book and in the Zen Mojo samples. It is not necessary to have a detailed understanding of XML, and this book will provide tips where needed.

Acquaintance with Zen can be helpful, but is not necessary.

Kinds of Zen Mojo Applications

Zen Mojo is designed for client-server interaction, and you can use it to create applications whose web clients are on either mobile devices or on desktops. The server is a Caché server. There are several kinds of applications you can create with Zen Mojo:

  • Web applications designed for desktops.

    This type of application is the most familiar to existing Caché users, who have previously built web applications in Zen and CSP. Note that in contrast to Zen and CSP, a Zen Mojo web application consists of a single page.

  • Web applications designed for mobile devices. As with the previous item, this application consists of a single page. In this case, the page is either specifically tailored for a mobile environment or uses responsive design and automatically adapts to various mobile devices. In general, web applications only have limited access to a mobile device’s native capabilities. They may also need some fine-tuning to run smoothly on different mobile devices.

    To create this kind of application, you would generally use different plugins than for desktop web applications. Some plugins are better suited to mobile environments, and others are better suited for desktops.

  • Hybrid applications for mobile devices. A hybrid application consists of a native application running a web application in an embedded (and therefore invisible) browser. The native container provides access to the device’s capabilities. The application can also use push notifications.

The following subsections describes the parts of the web application for Zen Mojo, and additional considerations for mobile and hybrid applications.

Web Applications

Formally, a Zen Mojo web application consists of the following parts:

a page class

A Zen Mojo page class is a class derived from %ZEN.Mojo.basePageOpens in a new tab. Zen Mojo is designed so that your application can use a single, fairly simple page class.

template classes

A Zen Mojo template class is a class derived from %ZEN.Mojo.Component.contentTemplateOpens in a new tab. A template class provides all the logic for your application, including data and layout information.

You can have multiple template classes to expand your application.

If you are familiar with Zen, note that Zen Mojo templates are unrelated to Zen templates.

an application class

An optional class derived from %ZEN.Mojo.baseApplicationOpens in a new tab that provides application-wide behavior such as the style sheet. The style sheet is specified as an XData block in the class, and this block contains CSS style instructions. You can also place a style sheet within the page class, but you may find it convenient to keep style information in the application class.

supporting classes

Zen Mojo provides a set of supporting classes, including plugin classes. In your implementation, you specify indirectly how the supporting classes are used. You do not generally subclass them.

JavaScript include files

Many of the plugin classes require a external, third-party JavaScript include files.

CSS style sheets

The plugin classes typically use one or more CSS style sheets, which help define the appearance of the layout objects provided by the plugin. You can use the third-party style sheets that accompany the plugins or you could develop your own style sheets.

web application definition

A web application definition is a configuration that resides in the CACHESYS database. You create application definitions in the Management Portal, in the same part of the portal where you define users and roles.

This configuration specifies information such as how the application can be accessed, the default timeout period, default error pages, and other details.

When you create a namespace, the Management Portal provides the option of creating an associated web application at the same time. You could use this default application or define another. In either case, you should review the application definition and make sure that it is appropriate for your needs.

For specific guidance, see “Zen Application Configuration” in Developing Zen Applications; this section is relevant because Zen Mojo is based on Zen. For more generic information on web applications, see “Web Applications” in the Caché Security Administration Guide.

Your classes (and the underlying Zen Mojo classes) define both client methods and server methods. A client method is written in JavaScript and runs in the browser. A server method is written in one of the Caché server-side languages, typically Caché ObjectScript. As noted previously, most of the methods in a typical Zen Mojo application are client methods.

Mobile Applications

To use Zen Mojo to create an application for a mobile environment, you create a Zen Mojo page and then generate a static HTML version of the page (this is the offline version of the page), collect the needed JavaScript libraries and CSS files, package these items together as a unit, and distribute the unit as a web application via the same channels used for other mobile applications.

To package the items as a unit, you use a third-party tool such as PhoneGap, not described in this book.

This application contacts the server when appropriate and also provides minimal functionality when the server is not available. The details depend upon the application. It is important to consider the following points:

  • Choose plugins that use libraries that are designed for use on mobile devices. For example, the JQuery Mobile and Chocolate-Chip UI libraries are meant for use on mobile devices, but the Dojo libraries are meant for use on larger screens.

  • The web page should be small, simple enough to display and use on smaller screens, and should be responsive to screen rotation.

  • You should ensure that the page provides at least minimal functionality without needing access to the server.

    For example, when the user initially accesses the application, if the server is inaccessible, the page could use data that was previously cached.

Hybrid Applications

For a hybrid application, you also must create a native container specific to the device. To create the native container, use using SWIFT or Objective-C (for iOS devices), Java (for devices running Android, or a language from the .NET family (for Windows phones). Caché provides all the options needed to connect your native interface with your data and application logic. Caché provides support for JSON and REST, so you can use JSON over REST services. Caché also supports web services (still frequently used for this purpose). You can also create custom HTTP requests if needed. For any approach, Caché provides a session context, and it is easy to switch to a secured connection using SSL3.

In a hybrid application, the client methods of your web page can access hardware features of the mobile device.

Your application can also use push notifications. For details on push notifications, see Configuring and Using Ensemble Push Notifications.

To package the native container with the offline page and other components, use PhoneGap, not described in this book.

Basic Definition of a Zen Mojo Page

To define a Zen Mojo page, you define a page class that includes an XData block like the following simple example:

XData pageContents [ XMLNamespace = "http://www.intersystems.com/zen" ]
{
<pane xmlns="http://www.intersystems.com/zen"
xmlns:mojo="http://www.intersystems.com/zen/mojo"
layout="none">

<mojo:documentView id="mainView"
ongetlayout = "return zenPage.getContent('layout',key,criteria);"
ongetdata = "return zenPage.getContent('data',key,criteria);">
<mojo:mojoDefaultPageManager>
   <mojo:HTML5Helper/>
</mojo:mojoDefaultPageManager>
</mojo:documentView>

</pane>
}

The next chapters provide details on the page class. For now, let us just examine this XData block.

The text within the curly braces is an XML document that Zen Mojo uses to generate the page. This example definition consists of one <mojo:documentView> element (or more simply, documentView). This element is the general-purpose container provided by Zen Mojo. This simple example demonstrates a typical page, and the following notes use this example to provide an overview:

  • The ongetdata callback specifies how to retrieve data for use in this documentView. When this documentView retrieves data, Zen Mojo invokes the method specified by ongetdata, passing several arguments to that method. (As we will see later, this callback returns a JSON object.)

  • The ongetlayout callback specifies how to build the layout of this documentView. When this documentView builds its visual appearance, Zen Mojo invokes the method specified by ongetlayout, again passing several arguments to that method.

    The ongetlayout callback returns a JSON object that is a Zen Mojo layout graph. A layout graph is a combination of layout objects. Layout objects, in general, include items such as paragraphs, tables, charts, groups, menus, check boxes, buttons, and other web page elements.

    Where suitable, the layout objects refer to data returned by the ongetdata callback. For example, a dropdown list can display a list of values returned by the ongetdata callback.

  • This documentView contains one child element, <mojo:mojoDefaultPageManager>, which is a page manager plugin or page manager provided by Zen Mojo. Each documentView must contain exactly one page manager, which automatically manages the page rendering.

    Zen Mojo provides multiple page managers, some of which can be used only with specific helper plugins. See the next bullet item.

  • The page manager contains one child element, <mojo:HTML5Helper/>. This child element is a helper plugin provided by Zen Mojo and it defines a set of layout objects. The ongetlayout callback returns a layout graph that consists of layout objects defined by this helper plugin.

    A page manager can contain multiple helper plugins, not just one as in this example. Often it is useful to use multiple helper plugins.

    Tip:

    The <mojo:HTML5Helper/> element is empty. Notice that the example contains only a single empty tag for this element rather than a matching opening and closing tag. An opening tag has the form <element> and a closing tag has the form </element>, as you can see in the example above. An empty tag has the form <element/>

The next section introduces helper plugins and layout objects in more detail.

Zen Mojo Helper Plugins and Layout Graphs

Zen Mojo uses helper plugins and layout graphs to determine the appearance of your web page. A helper plugin is a class that defines a set of layout objects, each which represents a graphical element. The plugin class defines methods that specify how to render those elements, typically using third-party JavaScript libraries.

You can include multiple helper plugins in a documentView. Currently, Zen Mojo provides the helper plugins that provide access to the ChocolateChip-UI framework, the Dojo library, the Google Maps API, the jQueryMobile library, and HTML5 standard. Also, a default helper provides special utility objects for use in layout graphs. You can create your own helper plugins, as well.

A layout graph is a JavaScript object that describes the layout in terms of layout objects. It is not necessary for you to write complex JavaScript or HTML rendering code, because Zen Mojo generates this code for you, based on your layout graphs. The following shows an example layout graph:

content = {
      children:[
         {type:'$header',caption:'=[sectionHeader]'},
         {type:'$listview',value:'=[personList]',filter:true,children:[
             {type:'$listviewitem',key:'drill-person',value:'=[id]',
                   label:'=[name]',content:'=[ssn]',clickable:true}
                ]}
         ]
};

In this example, $header, $listview, and $listviewitem are types of layout objects and are provided by a plugin (specifically the jQuery Mobile helpers). Other information in this layout graph specifies data to display in these layout objects and describes the behavior of these elements.

Zen Mojo Templates

The purpose of a Zen Mojo template is to define the appearance and behavior of a Zen Mojo page. It is important, therefore, to understand how a Zen Mojo page uses a template. This section discusses the following topics:

For simplicity, caching is discussed later in this chapter.

Content Objects

For any documentView, at any given time, Zen Mojo uses two JSON objects to determine the contents of that documentView. Generically, these JSON objects are known as content objects. The following figure shows an example (with a page that consists of a single documentView):

generated description: json objects

The two content objects are called the data object and the layout graph.

The current data object contains data that is currently available for use in the documentView. Often, but not necessarily always, this is obtained from the server.

The current layout graph determines the current appearance of the documentView. In its basic form, this object consists of a combination of the following:

  • Zen Mojo layout objects that are defined in the relevant plugins

  • References to the values provided by the data object

  • Constant values and other JavaScript expressions

The page retrieves both content objects from the template class and then uses them to generate the documentView.

In the next chapter, Tutorial 1 and Tutorial 2 provide a demo of these objects.

Keys

Zen Mojo uses a system of keys to support user interaction. This system works as follows:

  • Within a layout graph, you associate keys with items that can be selected, such as menu items, buttons, and so on.

  • Within page callbacks, the current key is available as the JavaScript key variable. For example, if a user clicks an item in a dropdown list, Zen Mojo invokes the onselect() callback. In this callback, the key variable contains the key of the selected list item.

  • Zen Mojo provides methods to set the current keys for the data object and layout graph, respectively. It also provides a method to update the layout.

    In a common scenario, a user selects an option, which invokes the onselect() callback. This callback then updates the data and layout keys and then updates the layout, changing the appearance of the page.

Note that additional variables are available within the callbacks, so your logic does not have to depend entirely on the keys.

Content Objects and Keys

The content objects are key-specific. That is, when a documentView retrieves a data object or a layout graph, it uses a specific key.

generated description: component object versions

Depending on the plugins you use, a page can have multiple documentView components, and the preceding consideration applies to each of them.

generated description: page and object versions

The Template System

A Zen Mojo template is responsible for all application logic, which means that it is responsible for returning all the data and layout graphs needed on a page. Ultimately, a Zen Mojo page uses two methods that you implement in your template class: onGetContent() and %OnGetJSONContent().

Similarly, a Zen Mojo template is responsible for submitting data to the server. In this case, a Zen Mojo page uses the %OnSubmitData() method that you implement in the template class.

This section describes how the page and template work together and explains how and when these methods are used.

Getting Content Objects

The page uses a single, central method (getContent()) to obtain content objects from the template. This is an existing method provided by Zen Mojo. So that you can specify the object to return, getContent() has arguments that enable you to specify:

  • The content object to retrieve — this is the providerName argument

  • The key to use when retrieving that content object — this is the key argument

There are other arguments as well, but they are not critical to this discussion.

The method getContent() invokes the onGetContent() and %OnGetJSONContent() methods in the template class and passes these parameters to them.

The following steps outline the overall flow of logic. For simplicity, these steps do not discuss the Zen Mojo cache mechanism, which is discussed later in this chapter.

  1. A user performs some action in response to which your page is designed to get new data from the server, modify the display, or both. This action might be to press a button.

  2. That action invokes the getContent() method of the page class.

    This is a client method provided by Zen Mojo. Recall that all client methods are written in JavaScript and run in the browser.

  3. The getContent() method invokes another Zen Mojo method, an internal method not meant for direct use.

  4. That internal method does some processing and then invokes the onGetContent() method in the associated template class.

    onGetContent() is an application-specific client method.

  5. The onGetContent() method is intended to be a dispatcher. It examines the providerName argument and then either:

    • Invokes another client method, which returns the requested object.

      onGetContent() passes the key value and other arguments to that method, so that the returned object is appropriate for the given key.

    • Returns null. In this case, see the next step.

  6. If onGetContent() returns null, the template invokes the %OnGetJSONContent() method in the template class.

    The %OnGetJSONContent() method is an application-specific server method. Recall that server methods are written in Caché ObjectScript and run on the server.

  7. The %OnGetJSONContent() method first examines the pProviderName argument, to determine the documentView for which the object is needed.

    Then an inner branch examines the pKey argument to determine which version of the object to return.

    The method then constructs and returns the object to the page, and the page then uses it.

The following figure summarizes these steps:

generated description: getcontent

Commonly, onGetContent() returns layout graphs (because these should not require communicating with the server), and %OnGetJSONContent() returns data objects.

Submitting Data

When the page sends data to the server, the template provides the needed logic. The overall flow of logic is as follows:

  1. A user clicks a Save or Submit button or performs some other action on the page.

    Your implementation of this button invokes the submitData() page method.

    The submitData() page method takes three arguments:

    • key — The key to use when sending data to the server.

    • data — A JSON object that carries the data to be sent to the server.

    • notify — Either null or a function. If this argument is a function, the page sends the data asynchronously to the server (rather than synchronously). Then , when the data has been sent, the page executes the function named by this argument.

  2. The submitData() method invokes the %OnSubmitData() method in the associated template class.

    %OnSubmitData() is an application-specific method that you have implemented.

  3. The %OnSubmitData() method receives the key and submit object as input.

    This method first examines the key to determine which branch of code to use. Then it examines and uses the submit object, as needed by your application. Finally, it creates a response object and returns it as output. Zen Mojo then makes the response object (another JSON object) available on the page.

generated description: submitdata

The Zen Mojo Content Cache

To avoid unnecessary calls to the server (and to avoid other unnecessary calls to the current template), Zen Mojo caches content in a local array and uses that cache when possible.

Specifically, the page method getContent() uses the cache if it is available. If there is no cached content for the given key and criteria arguments, getContent() then invokes onGetContent() of the current template, as described earlier in this chapter.

generated description: cache details

When you need to force Zen Mojo to call %OnGetJSONContent() for a given documentView, you can invalidate the cache for that documentView. You would do this if you needed to force the page to retrieve new data from the server.

Event Handling

When an event occurs on the page, Zen Mojo automatically invokes an event handler in the associated template class. The Zen Mojo event handlers are the onselect(), onchange(), and onevent() methods, which have no behavior by default.

  • If a user selects a layout object, Zen Mojo invokes the onselect() method.

  • If a user changes the value of a layout object, Zen Mojo invokes the onchange() method.

  • If an event of another type occurs, Zen Mojo invokes the onevent() method.

To make your page interactive, define any or all of these methods in your template class. For each method, Zen Mojo automatically passes information about the context in which the event occurred. This information indicates the documentView, the item key, and the item value. (Notice that the layout graph should associate keys with any items that can be selected, such as menu items, buttons, and so on. ) For onevent(), Zen Mojo also passes the event type.

For example, a user might select a menu item whose key is key1. Zen Mojo then invokes the onselect() callback, passing key1 as the value for the key argument. This callback could then set the data and layout keys equal to key1 and then update the layout, thus changing the appearance of the page.

Within your methods, you have access to tools that you can use for tasks like these:

  • Setting the current keys for the data object and layout graph.

  • Updating the layout.

  • Submitting data to the server.

  • Pushing new layouts onto a document stack (or popping them off the stack).

Zen Mojo provides methods to set the current keys for the data object and layout graph, respectively. It also provides a method to update the layout. Additional methods enable you to interact with the page and submit data to the server. Later chapters in this book describe these tools.

Note that additional variables are available within the callbacks, so your logic does not have to depend entirely on the keys.

How Zen Mojo Works

Zen Mojo works much in the same way that Zen does, except that Zen Mojo is much more lightweight.

When the client sends a page request, Zen Mojo generates the page and all of its components, creating an object tree. The object tree generates all the CSS (style sheet), JavaScript (client logic) and HTML (layout instructions) needed to display the page within the client browser.

On the client browser, the system automatically recreates the object tree as a set of JavaScript objects. Properties of the object tree are thus available to the client. The client can also, of course, use the client methods.

This object tree is much smaller for Zen Mojo than it is for Zen. In particular, a typical Zen page includes a large number of component objects. In contrast, a typical Zen Mojo page includes one documentView object.

generated description: object trees

As the user interacts with a page, events are fired that invoke the various methods of the client object tree. Zen Mojo automatically manages communication with the server and also handles session context (if any), security, and synchronizing changes between the client and the server.

With Zen Mojo, it is possible for an application to run without a session, which means that the application can run without a connection to the server. In contrast, Zen does not support this scenario.

The Zen Mojo Page Object

It can be useful to know a few things about the object tree (and the corresponding Caché classes) that Zen Mojo uses to represent a page. This object tree includes the following:

  • An instance of your page class. The page class inherits from %ZEN.Mojo.basePageOpens in a new tab. This class provides methods and properties that enable you to work with the page instance.

  • An instance of each documentView that you have added to pageContents. Typically pageContents contains one or two <mojo:documentView> components. For some of the plugins, only a single <mojo:documentView> is supported; in general, if a page manager plugin is intended for use on mobile devices, that plugin uses the entire page and does not support multiple documentViews.

    Each <mojo:documentView> is an instance of the class %ZEN.Mojo.Component.documentViewOpens in a new tab. This class provides methods that enable you to work with this instance and its related objects (such as its plugins).

  • Each documentView instance includes child objects, which are instances of the plugins specified by that documentView.

    Each page manager plugin is a subclass of %ZEN.Mojo.Plugin.basePageManagerOpens in a new tab, and each helper plugin is a subclass of %ZEN.Mojo.Plugin.baseHelperPluginOpens in a new tab

  • A content provider component, which is included automatically on every Zen Mojo page. This component enables the page to access and use the associated templates. The content provider is an instance of %ZEN.Mojo.Component.contentProviderOpens in a new tab.

    The following objects are attached to the content provider:

    • An instance of each template class that is associated with the page class.

    • One or more JSON providers. A JSON provider is an instance of %ZEN.Auxiliary.jsonProviderOpens in a new tab. The content provider has a JSON provider for each data object that the template returns. It does not have JSON providers for the layout graphs, because those do not usually require the server.

    The content provider is responsible for some of the internal processing discussed earlier in this chapter.

    It is not necessary to work with the content provider directly, except when invalidating caches.

Zen Mojo provides methods to access parts of this object tree as needed. That is, it is not necessary for you to know the detailed structure of this object tree.

Zen Mojo Version Numbers

There are separate version numbers for the Zen Mojo core, for each plugin, and for the plugin reference documentation. To see these version numbers, use the %PrintVersion() method of %ZEN.Mojo.UtilsOpens in a new tab:

do ##class(%ZEN.Mojo.Utils).%PrintVersion()

For example:

do ##class(%ZEN.Mojo.Utils).%PrintVersion()
 
Zen Mojo version 1.0.10
 
Page Managers
 
"0.5.3" : %ZEN.Mojo.Plugin.chui352PageManager
"0.5.2" : %ZEN.Mojo.Plugin.chuiPageManager
"1.0.2" : %ZEN.Mojo.Plugin.dojo191PageManager
"1.0.1" : %ZEN.Mojo.Plugin.dojoPageManager
"1.0.4" : %ZEN.Mojo.Plugin.jQM132PageManager
"1.0.0" : %ZEN.Mojo.Plugin.jQM143PageManager
"1.0.3" : %ZEN.Mojo.Plugin.jQMPageManager
"1.0.2" : %ZEN.Mojo.Plugin.mojoDefaultPageManager
 
Helper Plugins
 
"1.0.11" : %ZEN.Mojo.Plugin.HTML5Helper
"1.0.1" : %ZEN.Mojo.Plugin.charts101Helper
"0.5.5" : %ZEN.Mojo.Plugin.chui352Helper
"0.5.3" : %ZEN.Mojo.Plugin.chuiHelper
"1.0.5" : %ZEN.Mojo.Plugin.dojo1912DChartHelper
"1.0.5" : %ZEN.Mojo.Plugin.dojo191DijitHelper
"1.0.3" : %ZEN.Mojo.Plugin.dojo2DChartHelper
"1.0.4" : %ZEN.Mojo.Plugin.dojoDijitHelper
"1.0.4" : %ZEN.Mojo.Plugin.dojoGridX130Helper
"1.0.3" : %ZEN.Mojo.Plugin.dojoGridXHelper
"1.0.6" : %ZEN.Mojo.Plugin.googleMaps3Helper
"1.0.5" : %ZEN.Mojo.Plugin.googleMapsHelper
"1.0.1" : %ZEN.Mojo.Plugin.highCharts401Helper
"1.0.17" : %ZEN.Mojo.Plugin.jQM132Helper
"1.0.2" : %ZEN.Mojo.Plugin.jQM143Helper
"1.0.15" : %ZEN.Mojo.Plugin.jQMHelper
"1.0.7" : %ZEN.Mojo.Plugin.mojoDefaultHelper
 
Plugin Documentation installed: 0.8.6

For information on installing and accessing the Zen Mojo plugin reference documentation, see Using Zen Mojo Plugins.

FeedbackOpens in a new tab