Oracle�� JavaScript Extension Toolkit (JET)

Developing Applications with Oracle JET

1.1.2.0

E65296-02

October 2015

Documentation for software developers that describes how to develop client-side applications using Oracle JavaScript Extension Toolkit (JET)

Oracle JavaScript Extension Toolkit (JET) Developing Applications with Oracle JET, 1.1.2.0

E65296-02

Copyright �� 2014, 2015, Oracle and/or its affiliates. All rights reserved.

Primary Author: Michele Whittaker

Contributors: ���

This software and related documentation are provided under a license agreement containing restrictions on use and disclosure and are protected by intellectual property laws. Except as expressly permitted in your license agreement or allowed by law, you may not use, copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform, publish, or display any part, in any form, or by any means. Reverse engineering, disassembly, or decompilation of this software, unless required by law for interoperability, is prohibited.

The information contained herein is subject to change without notice and is not warranted to be error-free. If you find any errors, please report them to us in writing.

If this is software or related documentation that is delivered to the U.S. Government or anyone licensing it on behalf of the U.S. Government, then the following notice is applicable:

U.S. GOVERNMENT END USERS: Oracle programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, delivered to U.S. Government end users are "commercial computer software" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations. As such, use, duplication, disclosure, modification, and adaptation of the programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, shall be subject to license terms and license restrictions applicable to the programs. No other rights are granted to the U.S. Government.

This software or hardware is developed for general use in a variety of information management applications. It is not developed or intended for use in any inherently dangerous applications, including applications that may create a risk of personal injury. If you use this software or hardware in dangerous applications, then you shall be responsible to take all appropriate fail-safe, backup, redundancy, and other measures to ensure its safe use. Oracle Corporation and its affiliates disclaim any liability for any damages caused by use of this software or hardware in dangerous applications.

Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.

Intel and Intel Xeon are trademarks or registered trademarks of Intel Corporation. All SPARC trademarks are used under license and are trademarks or registered trademarks of SPARC International, Inc. AMD, Opteron, the AMD logo, and the AMD Opteron logo are trademarks or registered trademarks of Advanced Micro Devices. UNIX is a registered trademark of The Open Group.

This software or hardware and documentation may provide access to or information about content, products, and services from third parties. Oracle Corporation and its affiliates are not responsible for and expressly disclaim all warranties of any kind with respect to third-party content, products, and services unless otherwise set forth in an applicable agreement between you and Oracle. Oracle Corporation and its affiliates will not be responsible for any loss, costs, or damages incurred due to your access to or use of third-party content, products, or services, except as set forth in an applicable agreement between you and Oracle.

Contents

Preface

- Audience

- Related Resources

- Conventions

1 About Oracle JavaScript Extension Toolkit (JET)

- About Oracle JET

- Prerequisites for Using Oracle JET

- The Oracle JET Framework

- What's Included in Oracle JET

- Introduction to Oracle JET for Oracle ADF Developers

2 Getting Started with Oracle JET

- Typical Workflow for Getting Started with Oracle JET

- Choosing a Development Environment

- Downloading Oracle JET

- Downloading Oracle JET as a Zip File

- Downloading Oracle JET with a QuickStart Template

- Creating an Oracle JET Application Using the oraclejet.zip Download

- Creating an Oracle JET Application in the NetBeans IDE

- Creating an Oracle JET Application in JDeveloper

- Including References to CSS Files in Your Oracle JET Application

- Using RequireJS to Manage Library, Link, and Script References

- Specifying Library, Link, and Script References Without RequireJS

- Using the Oracle JET QuickStart Templates

- Loading the Oracle JET QuickStart Templates

- Working with the Oracle JET QuickStart Basic Template

- Adding Oracle JET to an Existing JavaScript Application

3 Designing Responsive Applications

- Typical Workflow for Designing Responsive Web Applications in Oracle JET

- Oracle JET and Responsive Web Design

- Oracle JET Grid, Form, and Responsive Helper Class Naming Convention

- Media Queries

- About the Maximum Display Width

- Using the Oracle JET Grid System in Responsive Design

- The Oracle JET Grid System

- The Grid Classes

- Adding an Oracle JET Grid System to Your Application

- Controlling the Size and Generation of the CSS

- Creating Responsive Form Layouts

- Using Responsive JavaScript

- The Responsive JavaScript Classes

- Changing a Component's Option Based on Screen Size

- Conditionally Loading Content Based on Screen Size

- Creating Responsive Images

- Using the Responsive Helper Classes

- Creating Responsive CSS Images

- Identifying the Responsive Design Patterns

- Changing Default Font Size

- Changing Default Font Size Across the Application

- Changing Default Font Size Based on Device Type

4 Using RequireJS for Modular Development

- Typical Workflow for Using RequireJS

- Oracle JET and RequireJS

- Oracle JET Module Organization

- Using RequireJS in an Oracle JET Application

- Troubleshooting RequireJS in an Oracle JET Application

- Using RequireJS for Lazy Loading Modules in an Oracle JET Application

- Using JavaScript Partitions and RequireJS in an Oracle JET Application

5 Creating Single-Page Applications

- Typical Workflow for Creating Single-Page Applications in Oracle JET

- Designing Single-Page Applications Using Oracle JET

- Understanding Oracle JET Framework Support for Single-Page Applications

- Creating a Single-Page Application in Oracle JET

- Using Knockout.js Templates and the ojModule Binding

6 Understanding Oracle JET User Interface Basics

- Typical Workflow for Working with the Oracle JET User Interface

- About the Oracle JET User Interface

- Oracle JET and jQuery UI

- Identifying Oracle JET UI Components, Patterns, and Utilities

- Common Functionality in Oracle JET Components

- Oracle JET Reserved Namespaces and Prefixes

- Adding an Oracle JET Component to Your Page

- Working with Forms

- Working with Form Layout Features

- Working with Form Controls

- Working with Form Validation and User Assistance

- Working with Labels

- Working with Sliders

- Working with Text Input Components

- Working with Selection Components

- Working with Buttons, Button Sets, and Toolbars

- Working with Buttons

- Working with Button Sets

- Working with Toolbars

- Working with Menus

- Working with ojMenu

- Working with Menu Buttons

- Working with Context Menus

- Working with Data Collections

- Choosing a Table or Data Grid

- Working with Tables

- Working with Data Grids

- Working with Trees

- Working with List Views

- Working with Row Expanders

- Working with Pagination

- Working with Data Visualizations

- Choosing a Data Visualization Component for Your Application

- Using Attribute Groups With Data Visualization Components

- Working with Layout and Navigation

- Working with Collapsibles

- Working with Accordions

- Working with Panels

- Working with Conveyor Belts

- Working with Film Strips

- Working with Masonry Layouts

- Working with Tabs

- Working with Trains

- Working with Dialogs

- Working with Popups

- Working with Progress Indicators

- Working with Nav Lists

- Working with offCanvasUtils

- Working with HTML Tags

- Adding jQuery UI Components or Effects to Your Oracle JET Application

7 Using the Common Model and Collection API

- Typical Workflow for Binding Data in Oracle JET

- About Oracle JET Data Binding

- Using the Oracle JET Common Model and Collection Framework

- About the Oracle JET Common Model and Collection API

- About Oracle JET Data Binding and Knockout

- Using the Oracle JET Common Model and Collection API

- Integrating REST Services

- About Oracle JET Framework Support for Integrating REST Services

- Passing Custom AJAX Options in Common Model CRUD API calls

- Supplying a customURL Callback Function

- Replacing oj.sync or oj.ajax Functions

- Creating a CRUD Application Using Oracle JET

- Defining the ViewModel

- Reading Records

- Creating Records

- Updating Records

- Deleting Records

8 Validating and Converting Input

- Typical Workflow for Validating and Converting Input

- About Oracle JET Validators and Converters

- About Validators

- About Converters

- Using Oracle JET Converters

- Using Oracle JET Converters with Oracle JET Components

- Understanding Oracle JET Converters Lenient Parsing

- Using Custom Converters in Oracle JET

- Using Oracle JET Converters Without Oracle JET Components

- Using Oracle JET Validators

- Using Oracle JET Validators with Oracle JET components

- Using Custom Validators in Oracle JET

- Using Oracle JET Validators Without an Oracle JET Component

9 Working with User Assistance

- Typical Workflow for Working with User Assistance

- Understanding Oracle JET's Messaging APIs on Editable Components

- Oracle JET Editable Component Messaging Options

- Oracle JET Component Messaging Methods

- Oracle JET Component Messaging Binding Attributes

- oj.InvalidComponentTracker

- Understanding How Validation and Messaging Works in Oracle JET Editable Components

- Understanding How an Oracle JET Editable Component Performs Normal Validation

- Understanding How an Oracle JET Editable Component Performs Deferred Validation

- Using Oracle JET Messaging

- Tracking Validity of a Group of Editable Components Using Knockout

- Notifying an Oracle JET Application of a Component's Messages and Validity

- Notifying an Oracle JET Editable Component of Business Validation Errors

- Configuring an Editable Component's Help Option

- Configuring an Editable Component's Title Option

- Controlling the Display of Hints, Title, and Messages

- Applying Form Validation Best Practices

10 Developing Accessible Applications

- Typical Workflow for Developing Accessible Oracle JET Applications

- Oracle JET and Accessibility

- Using the Accessibility Features of Oracle JET Components

- Creating Accessible Oracle JET Pages

- Configuring WAI-ARIA Landmarks

- Configuring High Contrast Mode

- Hiding Screen Reader Content

11 Internationalizing and Localizing Applications

- Typical Workflow for Internationalizing and Localizing Oracle JET Applications

- About Internationalizing and Localizing Oracle JET Applications

- Internationalizing and Localizing Oracle JET Applications

- Using the Oracle JET Framework's Internationalization and Localization Support

- Enabling Bidirectional (BiDi) Support in Oracle JET

- Setting the Locale Dynamically

- Working with Currency, Dates, Time, and Numbers

- Working with Oracle JET Translation Bundles

- About Oracle JET Translation Bundles

- Adding Translation Bundles to Oracle JET

12 Theming Applications

- Typical Workflow for Theming an Oracle JET Application

- About Oracle JET and Theming

- CSS Files Included With Oracle JET

- DOCTYPE Requirement

- SCSS and Oracle JET

- SCSS Tools

- Customizing Oracle JET Themes

- Customizing an Oracle JET Theme Using Sass

- Working with Framework Images in an Oracle JET Application

- Understanding Oracle JET Marker Styles

- Controlling Initial Visibility with CSS

- Understanding Right-to-Left Behavior

- Understanding Oracle JET and Browser Degradation

- Printing Oracle JET Pages

- Controlling CSS Content

- Using Variables to Control CSS Content

- Using Import Control to Define CSS Content

- Understanding Oracle JET Theming For Compatibility

- Using Tag Selectors or Classes

- Using REM

- Using Normalize

13 Securing Applications

- Typical Workflow for Securing Oracle JET Applications

- About Securing Oracle JET Applications

- Oracle JET Components and Security

- Oracle JET Framework Security Features

- Oracle JET Security and Developer Responsibilities

- Using oj.OAuth in Your Oracle JET Application

- Initializing oj.OAuth

- Verifying oj.OAuth Initialization

- Obtaining the OAuth Header

- Using oj.OAuth with Oracle JET Common Model

- Integrating oj.OAuth with Oracle Identity Management (iDM) Server

14 Optimizing Performance

- Typical Workflow for Optimizing Performance of Oracle JET Applications

- About Performance and Oracle JET Applications

- Adding Performance Optimization to an Oracle JET Application

15 Testing and Debugging

- Typical Workflow for Testing and Debugging an Oracle JET Application

- Testing Oracle JET Applications

- Using getNodeBySubId() in Testing

- Debugging Oracle JET Applications

A Troubleshooting

B Packaging and Deploying

C Oracle JET References

- Oracle Libraries and Tools

- Third-Party Libraries and Tools

Preface

Topics:

- Audience

- Related Resources

- Conventions

Developing Applications with Oracle JET describes how to build responsive web applications using Oracle JET..

Audience

Developing Applications with Oracle JET is intended for intermediate to advanced JavaScript developers who want to create pure client-side, responsive web applications based on JavaScript, HTML5, and CSS3.

Related Resources

For more information, see these Oracle resources:

- Oracle JET Web Site

- JavaScript API Reference for Oracle�� JavaScript Extension Toolkit (JET)

- Oracle�� JavaScript Extension Toolkit (JET) Keyboard and Touch Reference

Conventions

The following text conventions are used in this document:

Convention

Meaning

boldface

Boldface type indicates graphical user interface elements associated with an action, or terms defined in text or the glossary.

italic

Italic type indicates book titles, emphasis, or placeholder variables for which you supply particular values.

monospace

Monospace type indicates commands within a paragraph, URLs, code in examples, text that appears on the screen, or text that you enter.

1 About Oracle JavaScript Extension Toolkit (JET)

The Oracle JavaScript Extension Toolkit (Oracle JET) for UI developers uses Oracle and open source JavaScript libraries to build client-side HTML5 applications.

Use these topics for an overview of Oracle JET, prerequisites for using Oracle JET, and information for Oracle Application Development Framework (ADF) developers migrating to Oracle JET.

Topics:

- About Oracle JET

- Prerequisites for Using Oracle JET

- The Oracle JET Framework

- What's Included in Oracle JET

- Introduction to Oracle JET for Oracle ADF Developers

You can also view videos that provide an introduction to Oracle JET in the Oracle JET Videos collection.

About Oracle JET

Oracle JET is a collection of Oracle and open source JavaScript libraries engineered to make it as simple and efficient as possible to build client-side applications that consume and interact with Oracle products and services.

Oracle JET is designed to meet the following application needs:

- Adding interactivity to an existing page

- Adding tighter integration with Oracle services to an existing application

- Creating a new end-to-end client-side solution

Prerequisites for Using Oracle JET

Before you can successfully use Oracle JET, you should be familiar with the third party libraries and technologies that the JET framework uses.

Specifically, be sure that you are familiar with the following technologies:

- jQuery
jQuery is a JavaScript library designed for HTML document traversal and manipulation, event handling, animation, and Ajax. jQuery includes an API that works across most browsers. For additional information, see http://jquery.com.

- jQuery UI
jQuery UI is a JavaScript library built on top of the jQuery JavaScript library. All Oracle JET components are wrapped as jQuery UI widgets. For additional information about jQuery UI, see http://www.jqueryui.com.

- Knockout
Knockout is a JavaScript library that provides support for two-way data binding. For additional information, see http://www.knockoutjs.com.

- RequireJS
RequireJS is a JavaScript file and module loader used for managing library references and lazy loading of resources. RequireJS implements the Asynchronous Module Definition (AMD) API. For additional information about RequireJS, see http://www.requirejs.org. For information about the AMD API, see http://requirejs.org/docs/whyamd.html.

- JavaScript
For additional information, see https://developer.mozilla.org/en/About_JavaScript.

- CSS (Cascading Style Sheets)
For information, see http://www.w3.org/Style/CSS.

- HTML5 (Hypertext Markup Language 5)
For information, see http://www.w3.org/TR/html5.

- SASS (Syntactically Awesome Style Sheets)
SASS extends CSS3 and enables you to use variables, nested rules, mixins, and inline imports. Oracle JET uses the SCSS (Sassy CSS) syntax of SASS. For information, see http://www.sass-lang.com.

The Oracle JET Framework

Oracle JET supports the Model-View-ViewModel (MVVM) architectural design pattern.

In MVVM, the Model represents the application data, and the View is the presentation of the data. The ViewModel exposes data from the Model to the view and maintains the application's state.

To support the MVVM design, Oracle JET is built upon a modular framework that includes a collection of third-party libraries and Oracle-provided files, scripts, and libraries.

The Oracle JET Common Model and Collection Application Programming Interface (API) implements the model layer. The API includes the following JavaScript objects:

- oj.Model: Represents a single record data from a data service such as a RESTful web service

- oj.Collection: Represents a set of data records and is a list of oj.Model objects of the same type

- oj.Events: Provides methods for event handling

- oj.KnockoutUtils: Provides methods for mapping the attributes in an oj.Model or oj.Collection object to Knockout observables for use with component view models.

To implement the View layer, Oracle JET provides a collection of components wrapped as jQuery UI widgets, ranging from basic buttons to advanced data visualization components such as charts and Data Grids.

Knockout.js implements the ViewModel and provides two-way data binding between the view and model layers.

Additional Oracle JET framework features include:

- Messaging and event services for both Model and View layers

- Validation framework that provides UI element and component validation and data converters

- Caching services at the Model layer for performance optimization of pagination and virtual scrolling

- Filtering and sorting services provided at the Model layer

- Connection to data sources through Web services, such as Representational State Transfer (REST) or WebSocket

- Management of URL and browser history using Crossroads.js and Oracle JET oj.Router and ojModule components

- Integrated authorization through OAuth 2.0 for data models retrieved from REST Services

- Resource management provided by RequireJS

- API compatibility with Backbone.js Model, Collection, and Events classes, except for Backbone.js Underscore methods.

- JavaScript logging

- Popup UI handling

In addition, all Oracle JET visual components include the following features and standards compliance:

- Compliance with Oracle National Language Support (NLS) standards (i18n) for numeric, currency, and date/time formatting

- Built-in theming supporting the Oracle Alta UI style specifications

- Support for Oracle software localization standards, l10n, including:

- Lazy loading of localized resource strings at run time

- Oracle translation services formats

- Bidirectional locales (left-to-right, right-to-left)

- Web Content Accessibility Guidelines (WCAG) 2.0. In addition, components provide support for high contrast and keyboard-only input environments.

- Gesture functionality by touch, mouse, and pointer events where appropriate

- Support for Oracle test automation tooling

- Adaptive grid-based layout system

What's Included in Oracle JET

The Oracle JET distribution includes the Oracle JET framework and all third party libraries that the framework uses.

Specifically, Oracle JET includes the following files and libraries:

- CSS and SCSS files for the Alta theme

- Minified and debug versions of the Oracle JET libraries

- Data Visualization Tools (DVT) CSS and JavaScript

- Knockout and Knockout Mapping libraries

- jQuery libraries

- jQuery UI libraries (UI Core and only those modules needed by the Oracle JET framework)
For details about what's included in jQuery UI Core, see http://jqueryui.com/download. For information about downloading jQuery UI components or effects not included in the Oracle JET distribution, see Adding jQuery UI Components or Effects to Your Oracle JET Application.

- RequireJS and RequireJS text plugin

- Crossroads.js

- js-signals

- es6-promise polyfill

- Hammer.js
Oracle JET components use Hammer.js internally for gesture support. Do not add to Oracle JET components or their associated DOM nodes.

Introduction to Oracle JET for Oracle ADF Developers

If you are an Oracle Application Development Framework (ADF) developer getting started with JET, you should be aware of the key differences between Oracle JET and Oracle ADF. In some cases, Oracle ADF may be a better choice than Oracle JET.

The following table lists common application requirements and which product might be a better fit for your application.

Application Requirement

Oracle JET or ADF?

Feature

Extensible UI through in-place editing or some form of composer

Oracle ADF

Declarative programming model based on Metadata Services (MDS)

Upgrade safety for an enterprise application

Oracle ADF

Metadata and API upgradability for base code and extensions

Declarative navigation and/or reusable task flows

Oracle ADF

Task flows

Multiple Fusion Middleware (FMW) Suite products

Oracle ADF

Federated regions and task flows

Integrate with Fusion Applications (FA)

Oracle ADF

Services for complying with FA navigation, state sharing, and so on

Desktop integration with Microsoft Excel

Oracle ADF

Microsoft Excel front ends

Insulation from technology shifts

Oracle ADF

Guaranteed support for upgrades

Embed UI in a page built with third-party technology

Oracle JET

Fully client-side rendered component set and framework that doesn't assume page ownership

Single page application

Oracle JET

URL routing and browser history management for navigating within a single page

Standalone component set that can be integrated in a third-party framework

Oracle JET

Wrapped as independent client-side rendered jQuery UI components

To use Oracle JET, you should be comfortable working with JavaScript, CSS, and HTML5. You should also be familiar with the third-party technologies that Oracle JET uses. For a list of prerequisites for using Oracle JET, see Prerequisites for Using Oracle JET.

2 Getting Started with Oracle JET

Developing client-side applications with Oracle JET is designed to be simple and efficient using the development environment of your choice and QuickStart template applications to ease the development process.

Topics:

- Typical Workflow for Getting Started with Oracle JET

- Choosing a Development Environment

- Downloading Oracle JET

- Creating an Oracle JET Application Using the oraclejet.zip Download

- Using the Oracle JET QuickStart Templates

- Adding Oracle JET to an Existing JavaScript Application

Typical Workflow for Getting Started with Oracle JET

To get started using Oracle JET for application development, refer to the typical workflow described in the following table:

Task

Description

More Information

Choose a development environment

Determine what environment will house your Oracle JET files after download.

Choosing a Development Environment

Download Oracle JET

Download the Oracle JET zip file.

Downloading Oracle JET as a Zip File

Create a new Oracle JET application or load an Oracle JET QuickStart template

Create an Oracle JET application or load an Oracle JET QuickStart template in the NetBeans or JDeveloper IDE.

Creating an Oracle JET Application Using the oraclejet.zip Download or Using the Oracle JET QuickStart Templates.

Add Oracle JET to an existing JavaScript application.

Add the Oracle JET download to your existing JavaScript and add the necessary links to your application's main page.

Adding Oracle JET to an Existing JavaScript Application

Choosing a Development Environment

You can develop Oracle JET applications in virtually any integrated development environment (IDE) that supports JavaScript, HTML5, and CSS3. However, an IDE is not required for developing Oracle JET applications, and you can also use any text editor to develop your application.

NetBeans 7.3 and higher includes support for creating HTML5 projects, and you can create NetBeans projects using Oracle JET zip files as a site template. For additional information about creating an Oracle JET application in the NetBeans IDE, see Creating an Oracle JET Application in the NetBeans IDE.

Oracle JDeveloper 12.1.2.0 and higher also includes support for creating HTML5 projects, and you can also create your Oracle JET applications using the JDeveloper IDE. For additional information, see Creating an Oracle JET Application in JDeveloper.

Downloading Oracle JET

You can download Oracle JET from the Oracle Technology Network (OTN) as a single zip file. The zip file contains everything you will need to develop applications with Oracle JET. You can also download Oracle JET with a QuickStart template which includes an index.html file already configured to work with Oracle JET libraries and references.

The Oracle JET QuickStart template collection includes complete examples for working with Oracle JET for the first time, working with Oracle JET's responsive grid layout system, and more. If you are starting with a new HTML5 application and Oracle JET, the QuickStart Basic Template will be the fastest way to get started using Oracle JET.

Use the following table to determine where to find the details for downloading the Oracle JET bundle that meets your needs.

Task

Description

More Information

Download Oracle JET

Download Oracle JET as a zip file.

Downloading Oracle JET as a Zip File

Download Oracle JET with a QuickStart Template

Download Oracle JET with a QuickStart Template

Downloading Oracle JET with a QuickStart Template

Downloading Oracle JET as a Zip File

You can download Oracle JET from the Oracle Technology Network (OTN) as a single zip file. The zip file contain the libraries, scripts, styles, and files needed to develop applications using Oracle JET.

To download Oracle JET from the Oracle Technology Network (OTN):

1. Navigate to the Oracle JET download location at: Oracle JET Downloads.

2. Choose Accept License Agreement.

3. Download Oracle JavaScript Extension Toolkit: Base Distribution.

Downloading Oracle JET with a QuickStart Template

You can download any of the applications in the Oracle JET QuickStart template collection to get Oracle JET. The OracleJET_QuickStartBasic.zip file contains the Oracle JET bundle, an index.html file already configured for Oracle JET, and is a good choice for getting started with Oracle JET.

To download Oracle JET with the QuickStart Basic Template application:

1. Navigate to the Oracle JET download location at: Oracle JET Downloads.

2. Choose Accept License Agreement.

3. Download Quickstart: Basic Starter Template with Oracle JavaScript Extension Toolkit Pre-configured.

Creating an Oracle JET Application Using the oraclejet.zip Download

You can create a new Oracle JET application in NetBeans or JDeveloper using files extracted from oraclejet.zip. After you create your application, you can modify it to include references to Oracle JET CSS and libraries.

Topics

- Creating an Oracle JET Application in the NetBeans IDE

- Creating an Oracle JET Application in JDeveloper

- Including References to CSS Files in Your Oracle JET Application

- Using RequireJS to Manage Library, Link, and Script References

- Specifying Library, Link, and Script References Without RequireJS

Creating an Oracle JET Application in the NetBeans IDE

You can create a new Oracle JET application in the NetBeans IDE using files extracted from oraclejet.zip. Oracle JET supports NetBeans 7.3 or higher.

To create an Oracle JET application in the NetBeans IDE:

1. If needed, download and install NetBeans. Select a download bundle that includes support for HTML5. For additional detail, see https://netbeans.org/downloads/index.html

2. In the NetBeans IDE, click New Project.

3. In the New Project dialog, create a new HTML5 application.

a. In the Categories area, click HTML5.

b. In the Projects area, click HTML5 Application.

In this example, the HTML5 & PHP download bundle is used for the initial NetBeans download, and the categories are limited to HTML5 and PHP. If you downloaded a different NetBeans download bundle, the dialog will include additional categories.

c. Click Next.

4. In the New HTML5 Application dialog, configure the project name and project location.

a. In the Project Name field, enter a name for your project.

b. In the Project Location field, enter a location to store the project files.

In this example, the project is named OracleJETSample, and the project files will be stored in the C:\NetBeansProject directory.

c. Click Next.

5. In the New HTML5 Application dialog, specify the name of the site template.

a. Choose Select Template.

b. In the Template field, choose Browse and select the location containing the download bundle.

In this example, the completed HTML5 Application dialog specifies C:\Downloads as the location for the oraclejet.zip file.

c. Click Next.

6. Optionally, in the New HTML5 Application Dialog, add any additional libraries your application may need. By default, the Oracle JET libraries are already included.

7. Click Finish to create your application.
When you click Finish, NetBeans creates the project and adds an index.html file to your project. This figure shows the project files and index.html file that NetBeans generated for a project named OracleJETSample.

Creating an Oracle JET Application in JDeveloper

You can create a new Oracle JET application in the JDeveloper IDE using files extracted from oraclejet.zip. Oracle JET supports JDeveloper 12.1.2.0 or higher.

To create an Oracle JET application in the JDeveloper IDE:

1. If needed, download JDeveloper. For additional information, see http://www.oracle.com/technetwork/developer-tools/jdev/downloads/index.html.

2. In JDeveloper, click New Application.

3. In the New Gallery dialog, choose Custom Application and click OK.

4. In the Create Custom Application dialog, enter a name for your application and specify a directory to contain the application files.
In this example, the completed Create Custom Application dialog specifies an application named OJETSampleApplication. The application files will reside in the C:\OracleJETSamples\OJETSampleApplication directory.

5. Click Next to proceed to the next step.

6. In the Create Custom Application dialog, enter a name for your project.

7. In the list of available project features, scroll down to HTML and CSS and click Add to add HTML and CSS features to your project.
When you click Add, the JavaScript and XML project features also get added to the list of selected project features. In this example, the project is named OracleJETProject.

8. Click Finish to add the application to JDeveloper.

9. To create the folder that will store the Oracle JET files, do the following:

a. In the Applications window, in the Projects panel, right-click the project and choose New > From Gallery.

b. In the New Gallery, select the Folder item and click OK.

c. In the Create Folder dialog, in the Folder Name field, enter public_html and click OK.
The example shows the Applications window after the folder is created. JDeveloper displays the folder name as Web Content, but the underlying directory is still named public_html.

10. Navigate to the location on your local file system where you stored the download bundle and extract it into the public_html folder.
For the example application shown in the previous step, the public_html folder is stored in the C:\OracleJETSamples\OJETSampleApplication\OracleJETProject directory.

11. In the Projects panel, click Refresh and choose Refresh Application to display the updated project.
This example shows the Web Content folder in the Projects panel after extracting the oraclejet.zip file into the public_html folder.

12. In the Applications window, do the following to add an index.html page to your application.

a. In the Applications window, in the Projects panel, right-click the Web Content folder and choose New > HTML Page.

b. In the Create HTML File dialog, in the File Name field, enter index.html and click OK.

c. In the Visual Editor, click Source to view and edit your new page.
The example shows the default code that JDeveloper adds to a page when you create a new HTML page.

Including References to CSS Files in Your Oracle JET Application

Specify the references to the Oracle JET CSS files directly in your index.html file.

To include references to CSS files in your Oracle JET application:

1. Download Oracle JET as described in Downloading Oracle JET as a Zip File.

2. Edit the index.html file and add a link element pointing to the Oracle JET CSS theme that you will use.

For example, to use the Alta theme:

<!-- Oracle JET CSS files -->
<link rel="stylesheet" href="css/libs/oj/v1.1.2/alta/oj-alta-min.css" type="text/css"/>

For additional information about Oracle JET and the themes available for your use, see Theming Applications.

3. If you will be using the CSS included with Oracle JET, add the following line to the top of all HTML pages if needed.

<!DOCTYPE html>

This line is needed for the Oracle JET CSS to function as expected.

Using RequireJS to Manage Library, Link, and Script References

RequireJS is a JavaScript file and module loader that makes it easier to manage library references and is designed to improve the speed and quality of your code. Oracle JET uses RequireJS by default for the Oracle JET QuickStart Template and is required if you plan to use Oracle JET's internationalization, data visualization components, or the oj.OAuth plugin in your application.

To use RequireJS to manage references:

1. Download Oracle JET as described in Downloading Oracle JET as a Zip File.

2. Copy js/libs/oj/v1.1.2/main-template.js to the js folder.

3. Rename main-template.js to main.js.

4. Add the following script reference to your index.html file:

<script data-main="js/main" src="js/libs/require/require.js"></script>

5. Update main.js as needed to reference Oracle JET modules or your own scripts.

For a list of Oracle JET modules and additional details about using RequireJS in your Oracle JET application, see Using RequireJS for Modular Development.

For more information about RequireJS, see http://requirejs.org.

Specifying Library, Link, and Script References Without RequireJS

You can specify the Oracle JET script and link references directly in your index.html or main application file without using RequireJS. However, Oracle JET requires its use for major pieces of the Oracle JET framework, such as internationalization and data visualization components. If you know that your application will not need RequireJS, you can add script references specifying the library links.

To specify library, link, and script references without using RequireJS to manage references:

1. Download Oracle JET as described in Downloading Oracle JET as a Zip File.

2. Add the following references to your index.html file, if used:

<!-- 3rd Party JavaScript files -->
<script type="text/javascript" src="js/libs/jquery/jquery-2.1.3.min.js"></script>
<script type="text/javascript" src="js/libs/jquery/jquery-ui-1.11.4.custom.min.js"></script>
<script type="text/javascript" src="js/libs/knockout/knockout-3.3.0.js"></script>
<script type="text/javascript" src="js/libs/knockout/knockout.mapping-latest.js"></script>
<script type="text/javascript" src="js/libs/oj/v1.1.2/min/oj.js"></script>
<script type="text/javascript" src="js/libs/js-signals/signals.min.js"></script>
<script type="text/javascript" src="js/libs/crossroads/crossroads.min.js"></script>
<script type="text/javascript" src="js/libs/es6-promise/promise-1.0.0.min.js"</script>
<script type="text/javascript" src="js/libs/hammer/hammer-2.0.4.min.js"</script>

If you want to use the design time Oracle JET libraries for debugging, replace the min/oj.js reference with:

<script type="text/javascript" src="js/libs/oj/v1.1.2/debug/oj.js"></script>

Using the Oracle JET QuickStart Templates

You can load the Oracle JET QuickStart templates in NetBeans, JDeveloper, or your favorite development environment. After you load one of the templates, you can customize it for your application by modifying the template's index.html and main.js files.

Topics:

- Loading the Oracle JET QuickStart Templates

- Working with the Oracle JET QuickStart Basic Template

Loading the Oracle JET QuickStart Templates

The Oracle JET QuickStart templates includes all of the Oracle JET libraries and an index.html file already configured for your use. To load the Oracle JET QuickStart templates, extract the zip files and copy them as needed for your development environment.

You can also load the Oracle JET QuickStart templates in the NetBeans or JDeveloper IDE.

Topics:

- Loading the Oracle JET QuickStart Templates in NetBeans

- Loading the Oracle JET QuickStart Templates in JDeveloper

Loading the Oracle JET QuickStart Templates in NetBeans

To load the Oracle JET QuickStart templates in the NetBeans IDE:

1. Download the Oracle JET QuickStart template as described in Downloading Oracle JET with a QuickStart Template.

2. Create a new HTML5 application project and add the QuickStart template zip file (for example, OracleJET_QuickStartBasic.zip) as a site template as described in Creating an Oracle JET Application in the NetBeans IDE.

3. In the Projects panel, right-click the index.html file and choose Run File to display the page in your browser.

Note:

To take full advantage of the NetBeans integrated tools, the NetBeans team recommends that you install the NetBeans Connector extension for the Chrome browser. For additional info, see https://netbeans.org/kb/73/webclient/html5-gettingstarted.html.

The graphic below shows the Oracle JET QuickStart Basic Template displayed in the Chrome browser at run time. In this example, the NetBeans Connector is enabled.

Loading the Oracle JET QuickStart Templates in JDeveloper

To load the Oracle JET QuickStart templates in the JDeveloper IDE:

1. Download the desired Oracle JET QuickStart template as described in Downloading Oracle JET with a QuickStart Template.

2. Create a custom application and project and extract the QuickStart download bundle as described in Creating an Oracle JET Application in JDeveloper. You do not need to complete the last step to add the index.html file because it is already included with the Oracle JET QuickStart template.

3. In the Applications window, in the Projects panel, right-click the index.html file and choose Open.

4. In the Visual Editor, click Source to view and edit your new page.

5. In the Applications window, in the Projects panel, right-click the index.html file and choose Run to deploy the application and display the page in your default browser.

When you deploy the application for the first time, JDeveloper adds a default web.xml file to your project. The following example shows the default web.xml file for the OracleJETQuickStartBasic application.

<?xml version = '1.0' encoding = 'windows-1252'?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
</web-app>

Working with the Oracle JET QuickStart Basic Template

The Oracle JET QuickStart Basic Template provides everything you need to start working with code immediately. It is designed to work with the Oracle JET Cookbook examples, and you can use it to familiarize yourself with the Oracle JET components and basic structure of an Oracle JET application.

Topics:

- About the QuickStart Basic Template

- Modifying the QuickStart Basic Application Content

You can also view a video that shows how to work with the Oracle JET QuickStart Basic Template in the Oracle JET Videos collection.

About the QuickStart Basic Template

The QuickStart Basic Template is a single page application that is structured for modular development using RequireJS, Knockout templates, and the Oracle JET ojModule binding. Instead of storing all the application markup in the index.html file, the application uses Knockout's data-bind syntax and the ojModule binding to bind either a Knockout view template containing the HTML markup for the section or both the view template and JavaScript file that contains the ViewModel for any components defined in the section.

The following code shows a portion of index.html. Comments describe the purpose of each section, and you should review them for accessibility and usage tips.

Note:
Any CSS styling with the prefix "demo-" is for demonstration only and is not provided as part of the Oracle JET framework.

<html lang="en-us" class='demo-sticky-footer-layout'>
<head>
<title>Oracle JET QuickStart - Basic</title>
... contents omitted
<!-- RequireJS bootstrap file -->
<script data-main="js/main" src="js/libs/require/require.js"></script>
</head>
<body class="demo-appheader-offcanvas-pushwrapper">
<div id="globalBody" style="display: none">
<!-- off-canvas content -->
<div id="appDrawer"
class="oj-offcanvas-start oj-panel demo-appheader-offscreencontent"
style="height:100%;">
<div id='demoAppheaderOffCanvasInnerDiv'
data-bind="ojModule: {name: 'header', viewName: 'demoAppHeaderOffCanvasTemplate'}"
</div>
</div>
<!-- Header section contains the Global Branding, Global Navigation, and
Application Navigation code. Template is located in
/templates/header.tmpl.html -->
<header id="headerWrapper" role="banner"
data-bind="ojModule: { name: 'header'}"></header>

<!-- This is where your main page content will be loaded -->
<div id="mainContainer">
<div class="oj-row">
<div class="oj-xl-3 oj-lg-3 oj-md-12 oj-col"> <!-- demo-coldrop-A -->
<div role="navigation" class="demo-page-content-area">
<!--  This section is usually used for Navigation.
If its purpose is changed, the "role" attribute should be
changed as well to meet accessibility guidelines-->
<div id="navigationContent" data-bind="ojModule: { viewName: 'navContent'}">
</div>
</div>
</div>
<div class="oj-xl-6 oj-lg-9 oj-md-12 oj-col"> <!-- demo-coldrop-B -->
<div role="main" class="demo-page-content-area">
<!-- Unlike the Navigation and Complementary sections, this ojModule
binding is using "name" instead of "viewName". This tells the
binding to look for and load the JavaScript module of the same
name before loading the view template file. The value of the name
option is set to the current state of the ojRouter object which
is defined in the main.js file. This controls the modules that
will be loaded when the user clicks the App Nav buttons.
-->
<div id="mainContent" data-bind="ojModule: { name: router.stateId()}">
</div>
</div>
</div>
<div class="oj-xl-3 oj-lg-12 oj-md-12 oj-col"> <!-- demo-coldrop-C -->
<div role="complementary" class="demo-page-content-area">
<div id="complementaryContent" data-bind="ojModule: { viewName: 'compContent'}">
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

The ojModule binding���s viewName option tells Oracle JET that the section is only defining a view template, and the view will be bound to the existing ViewModel. Use the ojModule binding���s name option to load both a ViewModel module and view template.

The main container (div id="mainContainer") is defined as an Oracle JET responsive grid row, with sections for Navigation, Home Content Area, and Complementary. The following graphic shows the main container at run time, with arrows pointing to the names of the view template or ViewModel module defined in index.html.

The application uses oj.Router to manage navigation when the user clicks one of the application���s navigation buttons. If the user clicks People, for example, the Home Content Area changes to display the content in the people view template.

The site_root/templates folder contains the view templates (viewName) for the application. site_root/js/modules contains the ViewModel (name) scripts. The application defines the default paths and suffix for the view template in the main.js RequireJS bootstrap file. The image below shows the QuickStart Basic Template application file structure in the NetBeans IDE.

For additional information about working with single page applications, ojModule, oj.Router, and Knockout templates, see Creating Single-Page Applications.

Modifying the QuickStart Basic Application Content

You can add your own content to the main content area or anywhere on the page. To add content, modify the appropriate view template and ViewModel script (if it exists) for the section you want to update. Add any needed RequireJS modules to the ViewModel require() definition, along with functions to define your ViewModel.

If you add content to a section that changes its role, then be sure to change the role associated with that section. Oracle JET uses the role definitions for accessibility, specifically WAI-ARIA landmarks. For additional information about Oracle JET and accessibility, see Developing Accessible Applications.

To modify the Oracle JET QuickStart Basic application content:

1. Download the QuickStart Basic Template as described in Downloading Oracle JET with a QuickStart Template.

2. Load the QuickStart Basic Template as described in Using the Oracle JET QuickStart Templates.

3. In the index.html file, locate the ojModule binding for the section you want to modify and identify the template and optional ViewModel module.

For example, to update the Navigation content, locate the ojModule binding for the Navigation div in index.html and determine whether you need to modify a view template or both a view template and ViewModel module.

<div id="navigationContent" data-bind="ojModule: { viewName: 'navContent'}"></div>

The ojModule binding specifies navContent in the viewName option. Since the viewName option indicates that there is only a view template for this section, you will modify the navContent.tmpl.html file in the templates folder.

To update the header content which appears above the Navigation, locate the ojModule binding, locate the ojModule binding for the header div, shown below.

<header id="headerWrapper" role="banner" data-bind="ojModule: { name: 'header'}"></header>

The ojModule binding specifies header for the name option, which indicates that there is both a view template and ViewModel module for the header section. Therefore, you will edit header.tmpl.html in the templates folder and header.js in the js/modules folder.

The main content area content is a bit trickier to locate. The following code sample shows the mainContent div in the QuickStart Basic index.html file. In this example, the ojModule binding is using the name option to indicate that the binding should load the JavaScript module of the same name as the return value of router.stateId() before loading the view template file.

<div id="mainContent" data-bind="ojModule: { name: router.stateId()}"></div>

The return value of router.stateId() is set to the current state of the ojRouter object. The ojRouter object is defined with an initial value of home in the application's main.js RequireJS bootstrap, shown below.

var router = oj.Router.rootInstance;
router.configure({
'home': {label: 'Home', isDefault: true},
'people': {label: 'People'},
'library': {label: 'Library'},
'graphics': {label: 'Graphics'},
'performance': {label: 'Performance'}
});

Since the ojModule binding specified the name option, you will modify both the home.tmpl.html and home.js file.

4. To modify the view template, remove unneeded content, and add the new content to the template file.

For example, if you are working with an Oracle JET Cookbook sample, you can copy the markup into the template you identified in the previous step. Replace everything after the <h1>Home Content Area</h1> markup in the template with the markup from the sample.

For example, the following code shows the modified markup if you replace the existing content with the content from the Date and Time Pickers demo.

<h1>Home Content Area</h1>
<div id="div1">
<label for="dateTime">Default</label>
<input id="dateTime" data-bind="ojComponent: {component: 'ojInputDateTime', value: value}"/>
<br/><br/>
<span class="oj-label">Current component value is:</span>
<span data-bind="text: value"></span>
</div>

5. To modify the ViewModel, remove unneeded content, and add the new content as needed. Include any additional RequireJS modules that your new content may need.

The application's main.js file contains the list of Require modules currently included in the application. Compare the list of libraries with the list you need for your application, and add any missing modules to your define() function in the ViewModel script. For example, to use the ojInputDateTime components shown in the Date and Time Pickers, add ojs/ojdatetimepicker to the home.js ViewModel script since it's not already defined in main.js.

The sample below shows the modified home.js file, with the changes highlighted in bold.

define(['ojs/ojcore' ,'knockout', 'ojs/ojdatetimepicker'
], function(oj, ko) {
/**
* The view model for the main content view template
*/
function mainContentViewModel() {
var self = this;
self.value = ko.observable(oj.IntlConverterUtils.dateToLocalIso(new Date(2013, 0, 1)));
}

return mainContentViewModel;
});

If you're not using a Cookbook example and are not sure which Require module to include, see the table at Oracle JET Module Organization.

6. If you want to add, change, or delete modules or templates to the application, modify the main.js RequireJS bootstrap file as needed.
The file also contains the event handler that responds when a user clicks one of the navigation buttons. Depending upon your modifications, you may need to update this method as well.

7. Run the index.html file in your favorite browser and verify the change.

The following image shows the runtime view of the QuickStart Basic application with the new Home Content Area content showing the ojInputDateTime component with its current value.

The main container is defined using best practice for responsive design. You can resize the container to see its effect. For additional information about responsive design, see Designing Responsive Applications.

Adding Oracle JET to an Existing JavaScript Application

You can add Oracle JET to your existing JavaScript application by extracting the oraclejet.zip file into the site root of your application and including references to the Oracle JET libraries and CSS as needed.

To add Oracle JET to an existing JavaScript application:

1. Download oraclejet.zip as described in Downloading Oracle JET as a Zip File.

2. Extract oraclejet.zip into the site root of your application.

For example, if your application's site root is Site Root, extract oraclejet.zip into Site Root. After extraction, your site root folder will contain the following Oracle JET files and folders as shown in the NetBeans IDE.

The css folder contains the themes included with Oracle JET, and the scss folder contains the SASS source files for the Oracle JET themes. For additional information about Oracle JET theming, see Theming Applications.

The js folder contains the Oracle JET libraries and third party libraries, and the buildnum and revnum files identify the Oracle JET build number and version. For additional information about the libraries included in Oracle JET, see What's Included in Oracle JET.

3. If you want to use one of the themes included with Oracle JET, add the appropriate link to the CSS. For details, see Including References to CSS Files in Your Oracle JET Application.

4. If you want to use the Oracle JET libraries, you can either specify the links directly in your main application file or use RequireJS to manage the Oracle JET library, link, and script references.

- For information about specifying the links directly in your main application file, see: Specifying Library, Link, and Script References Without RequireJS.

- For information about configuring your application to use RequireJS, see Using RequireJS to Manage Library, Link, and Script References.

3 Designing Responsive Applications

The Oracle JET framework includes a 12-column responsive grid system, design patterns, responsive form layout and helper classes, and responsive JavaScript that you can use to design responsive web applications.

Topics:

- Typical Workflow for Designing Responsive Web Applications in Oracle JET

- Oracle JET and Responsive Web Design

- Media Queries

- Using the Oracle JET Grid System in Responsive Design

- Creating Responsive Form Layouts

- Using Responsive JavaScript

- Using the Responsive Helper Classes

- Identifying the Responsive Design Patterns

- Changing Default Font Size

Typical Workflow for Designing Responsive Web Applications in Oracle JET

To design responsive Web applications in Oracle JET, refer to the typical workflow described in the following table:

Task

Description

More Information

Understand Oracle JET's support for responsive design

Understand Oracle JET support for responsive design, including Oracle JET grid, form layout, and responsive classes naming conventions.

Oracle JET and Responsive Web Design

Use the Oracle JET grid system

Use the Oracle JET grid system to create page layouts that vary based on screen size.

Media Queries

Using the Oracle JET Grid System in Responsive Design

Create responsive forms

Use the Oracle JET responsive form classes to create forms that vary based on screen size.

Media Queries

Creating Responsive Form Layouts

Fine tune your responsive design

Use responsive design patterns, helper classes, and responsive JavaScript to complete the responsive design.

Using Responsive JavaScript

Using the Responsive Helper Classes

Identifying the Responsive Design Patterns

Change the default font size.

Change the default font size across your application or on a specified device type.

Changing Default Font Size

Oracle JET and Responsive Web Design

Responsive web design describes a design concept that uses fluid grids, scalable images, and media queries to present alternative layouts conditionally based on the media type. With responsive web design, you can configure your application to be visually appealing on a wide range of devices, ranging from small phones to widescreen desktops.

Oracle JET provides a 12-column grid system and form layout classes that include styles for small, medium, large, and extra large screens or devices. The grid system and form classes use media queries to set the style based on the size of the screen or device, and you can use them to customize your page layout based on your users' needs.

In addition, media queries form the basis for responsive helper classes that show or hide content, align text, or float content based on screen size. They are also the basis for responsive JavaScript that loads content conditionally or sets a component's option based on screen size.

Oracle JET Grid, Form, and Responsive Helper Class Naming Convention

The Oracle JET form, grid, and responsive style classes use the same naming convention that helps identify which style size, function, and number of columns the class represents:

oj-size-function-numberofcolumns

When you use the style classes in your responsive application, apply the classes for small screens first, and then customize for larger screens as needed. The following list shows some examples.

- oj-sm-6 applies to all screen sizes.

- oj-lg-3 applies to large and extra large screens. The style has no effect on medium or small screens.

- oj-sm-6 and oj-lg-3 placed on the same column will be 6 columns wide on small and medium screens and 3 columns wide on large and extra large screens.

Oracle JET also provides style classes that apply to only one screen size. These style classes use the naming convention: oj-size-only-function. For example, the oj-md-only-hide class hides content only at the medium screen size.

You can find a summary of the classes available to you for responsive design in Oracle JET in the Styling Doc.

Media Queries

CSS3 media queries use the @media at-rule, media type, and expressions that evaluate to true or false to define the cases for which the corresponding style rules will be applied.

<style>
@media media_types (expression){
/* media-specific rules */
}
</style>

The CSS3 specification defines several media types, but specific browsers may not implement all media types. The media type is optional and applies to all types if not specified. The following media query will display a sidebar only when the screen is wider than 767 pixels.

@media (max-width: 767px){
.facet_sidebar {
display: none;
}
}

Oracle JET defines CSS3 media queries for the screen sizes listed in the following table.

Size

Default Range in Pixels

Device Examples

small

0-767

phones

medium

768-1023

tablet portrait

large

1024-1279

tablet landscape, desktop

extra large

1280-1440

large desktop

Note:

For printing, Oracle JET uses the large screen layout for printing in landscape mode and the medium screen layout for printing in portrait mode.

Oracle JET's size defaults and media queries are defined in the Sass variables listed below and used in the grid, form, and responsive helper style classes.

For additional information about CSS3 media queries, see https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Media_queries and http://www.w3.org/TR/css3-mediaqueries.

About the Maximum Display Width

The Alta theme, included with Oracle JET, defaults the maximum display width to 1440px. If the device display width is greater than 1440px, empty margins render between the left and right content margins and the viewport figure as shown in the figure below.

The maximum display width is specified in the $appContentMaxWidth Sass variable. If your application has no maximum content width, you can set this variable to none.

$appContentMaxWidth: none;

For additional information about the theming in Oracle JET, see Theming Applications.

Using the Oracle JET Grid System in Responsive Design

You can use the Oracle JET grid classes to create grid layouts that vary the number and width of columns depending upon the width of the user's screen or type of device. After you complete your design, you can control the size and generation of the CSS to remove unused classes.

Topics:

- The Oracle JET Grid System

- Adding an Oracle JET Grid System to Your Application

- Controlling the Size and Generation of the CSS

The Responsive Grids section in the Oracle JET Cookbook provides several examples and recipes for using the Oracle JET grid system, and you are strongly encouraged to review them to get accustomed to the grid system.

The Oracle JET Grid System

Oracle JET provides a 12-column responsive mobile-first grid system that you can use for responsive design. The Oracle JET grid is very similar to other grid systems like those found in Twitter Bootstrap or Zurb Foundation. You start by coding for small screens, and larger devices will inherit those styles. Then you customize for larger screens as needed.

The Oracle JET grid structure includes the oj-row class to define a grid row, and the oj-col class to define a grid column. You can customize each column by adding one of the grid classes described in The Grid Classes or responsive helper classes described in Using the Responsive Helper Classes.

The following figure shows a simple example of a grid system defined to contain four rows. The width of the columns vary, depending upon the width of the browser or the size of the device.

The code to define Row 1 is shown in the following example. In the example, the row is defined to contain two columns, one with a width of 9 and one with a width of 3.

<div class="oj-row">
<div class="oj-sm-9 oj-col"></div>
<div class="oj-sm-3 oj-col"></div>
</div>

Since the oj-sm-* style is the only style defined for the row, the row will always contain two columns, no matter which device the row is rendered on or how wide the browser is stretched.

The code to define Row 2 is shown in the following example. In this example, Row 2 is also defined to contain two columns. However, in this example, there are two size styles specified on the same column.

<div class="oj-row">
<div class="oj-sm-6 oj-md-9 oj-col"></div>
<div class="oj-sm-6 oj-md-3 oj-col"></div>
</div>

On small screens, the oj-sm-6 style will be applied to both columns, and Row 2 will contain two columns, each with a width of 6. On medium screens and larger, the oj-md-9 and oj-md-3 styles will be applied, and Row 2 will contain two columns, the first with a width of 9 and the second with a width of 3.

Row 3 contains three columns. In this example, there are two size styles specified on the same column.

<div class="oj-row">
<div class="oj-sm-6 oj-lg-4 oj-col"></div>
<div class="oj-sm-4 oj-lg-4 oj-col"></div>
<div class="oj-sm-2 oj-lg-4 oj-col"></div>
</div>

On small and medium screens, the first column has a width of 6, the second column has a width of 4, and the third column has a width of 2. On large and extra large screens, each of the three columns has a width of 4.

Row 4 also contains three columns. This example defines styles for small, medium, large, and extra large screens.

<div class="oj-row ">
<div class="oj-sm-6 oj-md-6 oj-lg-4 oj-xl-5 oj-col"></div>
<div class="oj-sm-4 oj-md-3 oj-lg-4 oj-xl-3 oj-col"></div>
<div class="oj-sm-2 oj-md-3 oj-lg-4 oj-xl-4 oj-col"></div>
</div>

On small screens, the first column has a width of 6, the second column has a width of 4, and the third column has a width of 2. On medium screens, the first column also has a width of 6, but the second and third columns has a width of 3. On large screens, all columns have a width of 4. For extra large screens, the first column has a width of 5, the second column has a width of 3, and the third column has a width of 4.

The Oracle JET Cookbook contains the complete example and recipe for the basic grid used in this section. You can also find more advanced examples for grids, including nested grids, column customization, and workarounds for common issues you may encounter with your grid. For details, see Responsive Grids.

The Grid System and Printing

The Oracle JET grid system applies the large styles for printing in landscape mode and the medium style for printing in portrait mode if they are defined. You can use the defaults or customize printing using the print style classes.

In the basic grid example, Row 2 and 4 include the oj-md-* style classes. Row 3 and Row 4 include the oj-lg-4 style for all columns in the row.

<div class="demo-grid-sizes demo-grid-display">
<div class="oj-row">
<div class="oj-sm-9 oj-col"></div>
<div class="oj-sm-3 oj-col"></div>
</div>
<div class="oj-row">
<div class="oj-sm-6 oj-md-9 oj-col"></div>
<div class="oj-sm-6 oj-md-3 oj-col"></div>
</div>
<div class="oj-row">
<div class="oj-sm-6 oj-lg-4 oj-col"></div>
<div class="oj-sm-4 oj-lg-4 oj-col"></div>
<div class="oj-sm-2 oj-lg-4 oj-col"></div>
</div>
<div class="oj-row ">
<div class="oj-sm-8 oj-md-6 oj-lg-4 oj-xl-2 oj-col"></div>
<div class="oj-sm-2 oj-md-3 oj-lg-4 oj-xl-8 oj-col"></div>
<div class="oj-sm-2 oj-md-3 oj-lg-4 oj-xl-2 oj-col"></div>
</div>
</div>

As shown in the following print preview, when you print this grid in landscape mode, the oj-lg-4 style classes will be applied on Row 3 and Row 4. When you print the grid in portrait mode, the oj-md-* style classes apply on Row 2 and Row 4.

If you want to change the printing default, you can add the oj-print-numberofcolumns style class to the column definition. This has the effect of changing the column sizes for printing purposes only. In the following example, Row 1 includes the oj-print-6 class for each column in the row.

<div class="oj-row">
<div class="oj-sm-9 oj-print-6 oj-col"></div>
<div class="oj-sm-3 oj-print-6 oj-col"></div>
</div>

In normal mode, Row 1 contains two columns, one column with a size of 9 and one column with a size of 3, regardless of screen size. If you do a print preview, however, you'll see that Row 1 will print with two columns in portrait and landscape mode, both with a size of 6.

The Oracle JET Cookbook contains a complete example that shows printing behavior at Responsive Grid Printing. For additional information about the Oracle JET print styling classes, see Oracle JET Grid, Form, and Responsive Helper Class Naming Convention.

The Grid Classes

Oracle JET's grid system uses the responsive media query variables described in Media Queries. In addition, Oracle JET defines the following responsive media query variables for the Alta theme.

The following list describes the Oracle JET grid style classes that you can use in your grid.

- oj-row: Place on a row.

- oj-col: Place on each column.

- oj-cols-nopad: Place on a row or its parent to remove column padding. By default, columns have padding.

- oj-size-numberofcolumns: Set the column width.
For example, oj-sm-6 sets the column width to 6 on small screens and larger. oj-lg-4 will set the column width to 4 on large and extra large screens.

- oj-size-offset-numberofoffsetcolumns: Move columns over. Offset classes are not generated for small screens as there usually is not enough screen real estate to require these classes on small screens.
oj-md-offset-6 will move 6 columns over on medium screens and larger.

- oj-size-center: Center columns.

- oj-size-odd-cols-numberofcolumns: Use this in a 2-column layout. Instead of putting sizing classes on every column, you can put a single class on the row parent. The number of columns specifies how many of the 12 columns the odd-numbered columns can use. In a 2-column layout, the even-numbered columns will take up the remainder of the columns.
For example, setting oj-md-odd-cols-4 on the row parent will have the effect of setting the odd column (col1) width to 4 and the even column (col2) width to 8 for all rows in the grid.

The code sample below shows the grid configuration used to render the figure, with oj-md-odd-cols-4 placed on the row parent.

<div class="oj-md-odd-cols-4">
<div class="oj-row">
<div class="oj-col">col 1</div>
<div class="oj-col">col 2</div>
</div>
<div class="oj-row">
<div class="oj-col">col 1</div>
<div class="oj-col">col 2</div>
</div>
<div class="oj-row">
<div class="oj-col">col 1</div>
<div class="oj-col">col 2</div>
</div>
</div>

You could achieve the same effect by defining oj-md-4 for the first column's width in each row and oj-md-8 for the second column's width in each row.

<div class="oj-row">
<div class="oj-md-4 oj-col">col 1</div>
<div class="oj-md-8 oj-col">col 2</div>
</div>
<div class="oj-row">
<div class="oj-md-4 oj-col">col 1</div>
<div class="oj-md-8 oj-col">col 2</div>
</div>
<div class="oj-row">
<div class="oj-md-4 oj-col">col 1</div>
<div class="oj-md-8 oj-col">col 2</div>
</div>

- oj-size-even-cols-numberofcolumns: Use in a 4-column layout. In this layout, you must use both the odd-cols class to control the width of odd-numbered columns and the even-cols class to control the width of the even columns.
For example, setting oj-md-odd-cols-2 and oj-md-even-cols-4 on the row parent has the effect of setting the first and third column widths to 2, and the second and fourth column widths to 4.

The code sample below shows the grid configuration using to render the figure, with oj-md-odd-cols-2 and oj-md-even-cols-4 placed on the row parent.

<div class="oj-md-odd-cols-2 oj-md-even-cols-4">
<div class="oj-row">
<div class="oj-col">col 1</div>
<div class="oj-col">col 2</div>
<div class="oj-col">col 3</div>
<div class="oj-col">col 4</div>
</div>
<div class="oj-row">
<div class="oj-col">col 1</div>
<div class="oj-col">col 2</div>
<div class="oj-col">col 3</div>
<div class="oj-col">col 4</div>
</div>
</div>

If you don't use the convenience classes, you must define the size classes on every column in every row as shown below.

<div class="oj-row">
<div class="oj-md-2 oj-col">col 1</div>
<div class="oj-md-4 oj-col">col 2</div>
<div class="oj-md-2 oj-col">col 3</div>
<div class="oj-md-4 oj-col">col 4</div>
</div>
<div class="oj-row">
<div class="oj-md-2 oj-col">col 1</div>
<div class="oj-md-4 oj-col">col 2</div>
<div class="oj-md-2 oj-col">col 3</div>
<div class="oj-md-4 oj-col">col 4</div>
</div>

Adding an Oracle JET Grid System to Your Application

The basic process to add the grid system is to design for the smallest device first and then customize as needed for larger devices.

To add an Oracle JET grid system to your application:

1. Design the basic grid system.

Ask yourself the following questions:

- How many rows will you need?

- How many columns will you need?

- Do you need to adjust the column widths or add columns when the screen size increases?

- Are you adding a form to the grid?

- Are the print style defaults appropriate for your application?

- Do you want to use a responsive pattern, such as column drop, layout shift, or off-canvas partitions?

2. For each row in your grid, create a div with a class of oj-row.

<div class="oj-row">
</div>

3. For each column in your grid, add a div with a class of oj-col within the row.

<div class="oj-row">
<div class="oj-col"></div>
<div class="oj-col"></div>
...
</div>

4. For each column, specify the widths of each column with the sizing classes for small, medium, large, or extra large screens as needed.

Add the small style classes first, and only add the larger sizes as needed.

5. Customize your grid as needed.

For example, you can consult the Responsive Grids section in the Oracle JET Cookbook to see examples to:

- Offset or center columns.

- Specify a maximum width.

- Remove padding.

- Wrap columns.

- Specify a print style.

- Use the convenience classes to design two and four column grids.

6. To use one of the responsive helper classes, add the class to your grid. For additional information, see Using the Responsive Helper Classes.

Controlling the Size and Generation of the CSS

When you use the Oracle JET grid system, the framework generates a large number of responsive classes. Here are some steps you can take to control the size and generation of the CSS.

- Use compression.
The responsive classes are often repetitive and compress well. For details about compressing your CSS, see Optimizing Performance.

- Remove unused classes.
By default, Oracle JET generates responsive classes for printing, and small, medium, large, and xlarge screens. If you know that your application will not use some of these classes, you can set the associated $responsiveQuery* variables to none.

// If you don't want xlarge classes, you could set:
$screenXlargeRange:         none;
$responsiveQueryLargeOnly:  none;
$responsiveQueryXlargeUp:   none;
$appContentMaxWidth:        nth($screenLargeRange, 2);

- Exclude unused classes from the grid, form layout, and responsive helper groups.
You can use the $includeGridClasses, $includeFormLayoutClasses, and $includeResponsiveHelperClasses variables to exclude classes from these groups altogether. For additional information about using the $include* variables, see Using Variables to Control CSS Content.

- Stop generation of a particular type of grid or responsive helper class.
For finer-grained control, there are additional variables that you can set to false to stop generation of a particular type of class.

Variable

Description

Grid:

$gridGenerateBasics

Generate basic grid classes such like .oj-sm-1, .oj-sm-2, and so on.

$gridGenerateOffsets

Generate offset grid classes like .oj-md-offset-1, .oj-md-offset-2, and so on. Offset classes are not generated for small screens even when the variable is true.

$gridGenerateCentering

Generate centering grid classes like .oj-sm-center.

$gridGenerateOddEven

Generate odd and even grid classes like .oj-md-odd-cols-1, .oj-md-odd-cols-2, and so on.

Responsive Helper:

$responsiveGenerateHide

Generate hide classes like .oj-md-hide.

$responsiveGenerateTextAlignEnd

Generate text-align end classes like .oj-md-text-align-end.

$responsiveGenerateFloatStart

Generate float start classes like .oj-md-float-start.

$responsiveGenerateFloatEnd

Generate float end classes like .oj-md-float-end.

Creating Responsive Form Layouts

Oracle JET provides form-specific style class that you can use with the Oracle JET grid system for form layout. The form layout style classes also use the Oracle JET responsive media query variables.

- oj-form: Place on the parent of the rows to remove the normal padding found in the grid.

- oj-form-cols and oj-form-cols-labels-inline: Display a single column on small screens, and create additional columns when there is enough space. Place on the parent of the rows, the same element where you would place oj-form.
Use these classes for forms where you expect the user to enter input down a column. For larger screens, the form will display two or more columns, and the user will enter the input down the first column and then down the remaining columns. Use oj-form-cols to display labels in their default location above the field. Use oj-form-cols-labels-inline to display labels inline for medium or larger screens, as shown in the following image.

When you specify oj-form-cols, Oracle JET calculates the width of the field to determine if another column will fit in the display. When you specify oj-form-cols-labels-inline, Oracle JET totals the field and inline label width to determine if another column will fit in the display.

The oj-form-cols and oj-form-cols-labels-inline classes use the CSS multi-column layout technique. With this method, you can display two or more columns whenever there's enough room on the page, not just at the responsive break points. You don't have to calculate programmatically where to break the fields into columns because the CSS automatically determines how to break the content into columns. Even if the individual elements have varying heights, the CSS breaks the elements into columns of fairly even heights. For additional information about the multi-column layout technique, see http://dev.w3.org/csswg/css-multicol.

Note:

The CSS multi-column layout technique is not supported by all browsers. If the browser doesn't support the technique, the display will default to single column for all screen sizes.

- oj-form-cols-max2: Use with oj-form-cols or oj-form-cols-label-inline to restrict the display to two columns. Place on the same element that you place oj-form-cols or oj-form-cols-labels-inline.
If this class is absent, the number of columns increases to fill the size of the screen.

- oj-size-label-inline: Show the label inline, which is on the left side of the field in left-to-right languages and the right side of the field in right-to-left languages. By default, Oracle JET is designed to be mobile first and places labels above the field.

- oj-size-labels-inline: Use to show all labels inline. Place on the parent of the rows, the same element where you would place oj-form.

- oj-size-label-nowrap: Use to set nowrap on a label. The label text will be truncated if it's too wide.

- oj-size-labels-nowrap: Use to set nowrap on all labels. Place on the parent of the rows, the same element where you would place oj-form.

- oj-form-control-group: In a stacked form, place around a group of form controls. The style class ensures that the correct amount of space is maintained from the last form control in the group to the next form control in the stacked layout, even if the form controls have wrapped within their container.

To see examples of the classes in use, consult the Oracle JET Cookbook at Form Layout for:

- Stacking and nesting forms

- Inline responsive forms

- Grouping forms

- Column spanning

Using Responsive JavaScript

The Oracle JET framework includes the ResponsiveUtils and ResponsiveKnockoutUtils utility classes that leverage media queries to change a component's value option or load content and images based on the user's screen size or device type.

Topics:

- The Responsive JavaScript Classes

- Changing a Component's Option Based on Screen Size

- Conditionally Loading Content Based on Screen Size

- Creating Responsive Images

The Responsive JavaScript Classes

The ResponsiveUtils and ResponsiveKnockoutUtils responsive JavaScript classes provide methods that you can use in your application's JavaScript to obtain the current screen size and use the results to perform actions based on that screen size. In addition, the ResponsiveUtils provides a method that you can use to compare two screen sizes, useful for performing actions when the screen size changes.

JavaScript Class

Methods

Description

responsiveUtils

compare(size1, size2)

Compares two screen size constants. Returns a negative integer if the first argument is less than the second, a zero if the two are equal, and a positive integer if the first argument is more than the second.

The screen size constants identify the screen size range media queries. For example, the oj.ResponsiveUtils.SCREEN_RANGE.SM constant corresponds to the Sass $screenSmallRange variable and applies to screen sizes smaller than 768 pixels in width.

getFrameworkQuery(frameworkQueryKey)

Returns the media query to use for the framework query key parameter.

The framework query key constant corresponds to a Sass responsive query variable. For example, the oj.ResponsiveUtils.FRAMEWORK_QUERY_KEY.SM_UP constant corresponds to the $responsiveQuerySmallUp responsive query which returns a match when the screen size is small and up.

responsiveKnockoutUtils

createMediaQueryObservable(queryString)

Creates a Knockout observable that returns true or false based on a media query string. For example, the following code will return true if the screen size is 400 pixels wide or larger.

var customQuery =
oj.ResponsiveKnockoutUtils.createMediaQueryObservable(
'(min-width: 400px)');

createScreenRangeObservable()

Creates a computed Knockout observable, the value of which is one of the oj.ResponsiveUtils.SCREEN_RANGE constants.

For example, on a small screen (0 - 767 pixels), the following code will create a Knockout observable that returns oj.ResponsiveUtils.SCREEN_RANGE.SM.

self.screenRange =
oj.ResponsiveKnockoutUtils.createScreenRangeObservable();

For additional detail about responsiveUtils, see the oj.ResponsiveUtils API documentation. For more information about responsiveKnockoutUtils, see oj.ResponsiveKnockoutUtils.

Changing a Component's Option Based on Screen Size

You can set the value for a component's option based on screen size using the responsive JavaScript classes. For example, you may want to add text to an ojButton label when the screen size increases using the component's display option.

In this example, the button is bound to an ojButton component with component options defined for icons and a label. The code sample below shows the markup for the button.

<div id="samplecontainer">
<button id="bttndisplay"
data-bind="ojComponent: {
component:'ojButton',
icons: {start: 'oj-fwk-icon oj-fwk-icon-calendar'},
label: 'calendar',
display: large() ? 'all' : 'icons'
}"></button>
</div>

The code sample also sets the ojButton display option to all, which displays both the label and icon when the large() method returns true, and icons only when the large() method returns false.

The code sample below shows the code that sets the value for large() and completes the knockout binding. In this example, lgQuery is set to the LG_UP framework query key which applies when the screen size is large or up. self.large is initially set to true as the result of the call to oj.ResponsiveKnockoutUtils.createMediaQueryObservable(lgQuery). When the screen changes to a smaller size, the self.large value changes to false, and the display option value becomes icons.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'ojs/ojbutton'],
function(oj, ko, $)
{
function MyModel(){
var self = this;

// observable for large screens
var lgQuery = oj.ResponsiveUtils.getFrameworkQuery(
oj.ResponsiveUtils.FRAMEWORK_QUERY_KEY.LG_UP);

self.large = oj.ResponsiveKnockoutUtils.createMediaQueryObservable(lgQuery);

}

$(function() {
ko.applyBindings(new MyModel(), document.getElementById('samplecontainer'));

});
});

The Oracle JET Cookbook contains the complete code for this example which includes a demo that shows a computed observable used to change the button label's text depending on the screen size. You can also find examples that show how to use custom media queries and Knockout computed observables. For details, see Responsive JavaScript Framework Queries.

For additional information about working with ojButton, see Working with Buttons.

Conditionally Loading Content Based on Screen Size

You can change the HTML content based on screen size using the responsive JavaScript classes. For example, you might want to use a larger font or a different background color when the screen size is large.

In this example, the HTML content is defined in Knockout templates. The markup uses Knockout's data-bind utility to display a template whose name depends on the value returned by the large() call. If the screen is small or medium, the application will use the sm_md_template. If the screen is large or larger, the application will use the lg_xl_template.

<div id="sample_container">

<!-- large template -->
<script type="text/html" id="lg_xl_template">
<div id="lg_xl"
style="background-color:lavenderblush;
padding: 10px; font-size: 22px" >
This is the content in the <strong>lg/xl</strong> template.
</div>
</script>

<!-- small template -->
<script type="text/html" id="sm_md_template">
<div id="sm_md"
style="background-color:lightcyan;
padding: 10px; font-size: 10px" >
This is the content in the <strong>sm/md</strong> template.
</div>
</script>

<!-- display template -->
<div data-bind="template: {name: large() ? 'lg_xl_template' :
'sm_md_template'}"></div>
</div>

The code that sets the value for large() is identical to the code used for setting component option changes. For details, see Changing a Component's Option Based on Screen Size.

For information about working with Knockout templates, see Using Knockout.js Templates and the ojModule Binding.

For the complete code used in this example, see the Responsive Loading with JavaScript demo in the Oracle JET Cookbook.

Creating Responsive Images

You can use the responsive JavaScript classes to load a different image when the screen size changes. For example, you may want to load a larger image when the screen size changes from small and medium to large and up.

In this example, the image is defined in a HTML img element. The markup uses Knockout's data-bind utility to display a larger image when the large() call returns true.

<div id="samplecontainer">
<img alt="puzzle" id="puzzle"
data-bind="attr: { src: large() ? 'images/responsive/puzzle.png' :
'images/responsive/puzzle_small.png'}" >

</div>

The code that set the value for large() is identical to the code used for setting component option changes. For details, see Changing a Component's Option Based on Screen Size.

Note:

The image will not begin to load until the JavaScript is loaded. This could be an issue on devices with slower connections. If performance is an issue, you can use responsive CSS as described in Creating Responsive CSS Images. You could also use the HTML picture element which supports responsive images without CSS or JavaScript. However, browser support is limited and may not be an option for your environment.

For the complete code used in this example, see the Oracle JET Cookbook Responsive Images demos.

Using the Responsive Helper Classes

Use the Oracle JET generic responsive utility classes to hide content, end align text, and set float in your grid.

- oj-size-hide: Hide content at the specified size.

- oj-size-text-align-end: In left-to-right languages, set text-align to right. In right-to-left languages, set text-align to left.

- oj-size-float-end: In left-to-right languages, set float to right. In right-to-left languages, set float to left.

- oj-size-float-start: In left-to-right languages, set float to left. In right-to-left languages, set float to right.

To see examples that implement the responsive helper classes, consult the Oracle JET Cookbook at Responsive Helpers.

Creating Responsive CSS Images

You can use CSS generated from Sass media query variables and responsive queries to use a different, larger image when the screen size changes from small to large.

The code below shows the markup that defines the image. In this example, bulletlist is a CSS class generated from the Sass responsive variables and media queries.

<div role="img" class="oj-icon bulletlist" title="bulleted list image"></div>

The following image shows the bulletlist CSS class. When the screen is small or medium size, the icon_small.png image loads. When the screen increases to large or larger, or to print, the icon.png loads instead.

The Oracle JET Cookbook includes the Sass variables and queries used to generate the bulletlist CSS class. You can also find a Sass mixin that makes generating the CSS easier, but you are not required to use SCSS to create responsive CSS images.

In addition, the Oracle JET Cookbook includes examples that show high resolution images, sprites, button images, and more. For details, see Responsive CSS Images.

Note:

You can also use responsive JavaScript to change the images based on screen size. For details, see Creating Responsive Images.

Identifying the Responsive Design Patterns

Oracle JET includes support for the column drop, layout shift, and off-canvas responsive design patterns.

- Column drop: Columns drop below each other for smaller screens. At the widest breakpoint, content displays in columns. As the display size is reduced, columns drop from the rightmost side of the display and add as rows below the remaining column(s).

- Layout shift: Column layout changes for smaller screens. Layout shape may differ at each breakpoint as content is repositioned. Rather than simply adding or removing columns, for example, the leftmost column could transition to a row at the top of the display.

The difference between the two design patterns is subtle, and you can get a better feel for the difference by looking at the Oracle JET Cookbook examples at differing widths or on different devices. In the figure below, the column drop and layout shift patterns are shown at three different screen widths on a desktop display. In this example, the difference is noticeable in the middle figure for each pattern.

- Off-canvas push and overlay: You can use the Oracle JET framework offCanvasUtils to make an off-canvas partition that responsively change its position from off-screen to fixed inside the viewport when the browser width is changed.
In the image below, when the screen size is extra large, the off-canvas design shows three columns: the off-canvas partition on the start edge labeled A, the main content labeled B, and the off-canvas partition on the end edge labeled C. When the screen size is large, the off-canvas position on the end edge (C) is hidden off-screen, and the launch button indicates its availability. For medium screens and smaller, both the start edge and end edge partitions are hidden off-screen, and two launch buttons indicate their availability.

For additional information about using offCanvasUtils in your application layout, see Working with offCanvasUtils.

For examples that illustrate the responsive design patterns, see Responsive Design Patterns.

Changing Default Font Size

By default, the Oracle JET framework includes themes such as Alta that set a default font size on the root (html) element. This font size is optimized for visibility and touchability on mobile devices, but you can customize the size as needed for your application.

Topics

- Changing Default Font Size Across the Application

- Changing Default Font Size Based on Device Type

Changing Default Font Size Across the Application

The browser's font size is defined in the Sass $rootFontSize variable and included in the generated CSS html class. You can use Sass to change the variable or override the generated CSS.

To change the browser default font size across your application, do one of the following:

- In a custom Sass settings file, modify the Sass $rootFontSize variable, and regenerate the CSS.

For details about customizing Oracle JET themes, see Customizing Oracle JET Themes.

- In your application-specific CSS, override the font-size setting for the html class.

For example, to set the browser's default font size to 12 pixels, add the following to your application-specific CSS:

html {
font-size: 12px;
}

See Also:

Using REM

Changing Default Font Size Based on Device Type

You can change the default font size based on device type by detecting the device type used to access the browser and then setting the appropriate style on the html element.

To change the browser default font size based the user���s device type:

1. Use whatever means you like to detect that the browser is running on the specified device

For example, you may want to change the browser���s default font size on a desktop device. Use your own code or a third party tool to detect the device type.

2. When your application detects that the user is accessing the browser with the specified device, on the html element in your markup, set style="font-size: xxpx". Substitute the desired pixel size for xx.

For example, to set the font size to 12 pixels when the application detects the specified device, add logic to your application to add the highlighted code to your markup.

<html style="font-size: 12px">
... contents omitted
</html>

Note:
Be sure to perform this step before initializing components since some Oracle JET components measure themselves.

4 Using RequireJS for Modular Development

The Oracle JET framework includes RequireJS, a third party JavaScript library that you can use in your application to load only the Oracle JET libraries you need. Using RequireJS, you can also implement lazy loading of modules or create JavaScript partitions that contain more than one module.

Topics:

- Typical Workflow for Using RequireJS

- Oracle JET and RequireJS

- Using RequireJS in an Oracle JET Application

- Troubleshooting RequireJS in an Oracle JET Application

- Using RequireJS for Lazy Loading Modules in an Oracle JET Application

- Using JavaScript Partitions and RequireJS in an Oracle JET Application

Typical Workflow for Using RequireJS

To start using RequireJS for modular development in Oracle JET, refer to the typical workflow described in the following table:

Task

Description

More Information

Understand Oracle JET's use of RequireJS

Understand Oracle JET's module organization and why you might use RequireJS in your Oracle JET application.

Oracle JET and RequireJS

Configure RequireJS

Configure RequireJS in your Oracle JET application to load Oracle JET modules as needed.

Using RequireJS in an Oracle JET Application

Troubleshoot RequireJS

Troubleshoot issues with RequireJS.

Troubleshooting RequireJS in an Oracle JET Application

Use RequireJS for lazy loading

Configure RequireJS in your Oracle JET application to load Oracle JET modules only when needed.

Using RequireJS for Lazy Loading Modules in an Oracle JET Application

Use JavaScript partitioning and RequireJS

Add JavaScript partitioning with RequireJS to your Oracle JET application.

Using JavaScript Partitions and RequireJS in an Oracle JET Application

Oracle JET and RequireJS

RequireJS is a JavaScript file and module loader that makes it easier to manage library references and is designed to improve the speed and quality of your code.

RequireJS implements the Asynchronous Module Definition (AMD) API which provides a mechanism for asynchronously loading a module and its dependencies.

Oracle JET's modular organization enables application developers to load a subset of needed features without having to execute require() calls for each referenced object. Each Oracle JET module represents one functional area of the framework, and it typically defines more than one JavaScript object. The ojs/ojcore module defines the oj namespace object, and all subsequently loaded modules place their exported objects within the oj namespace.

Note:

Oracle JET reserves the oj namespace, and you may not use oj as a namespace in your Oracle JET application.

You do not have to use RequireJS to reference Oracle JET libraries, but it is required if you plan to use Oracle JET's internationalization or data visualization components in your application. The Oracle JET download includes the RequireJS library, and it is used by default in the Oracle JET QuickStart templates and Cookbook examples.

For more information about RequireJS, see http://requirejs.org.

Oracle JET Module Organization

The Oracle JET modules are listed in the following table with description and usage tips. Use this table to determine which modules you must load in your application.

Oracle JET Module

Description

When to Use?

ojs/ojcore

Core framework module that defines a base Oracle JET object. Includes support for prototype-based JavaScript object inheritance and extending JavaScript objects by copying their properties. The module returns oj namespace. You must include this module in any Oracle JET application.

Always

ojs/ojmodel

Oracle JET's Common Model

Use if your application uses the Oracle JET Common Model.

ojs/ojknockout-model

Utilities for integrating Oracle JET's Common Model into Knockout.js

Use if your application uses the Oracle JET Common Model, and you want to integrate with Knockout.js.

ojs/ojvalidation

Data validation and conversion services

Use if your application uses Oracle JET validators or converters outside of Oracle JET editable components.

ojs/ojknockout-validation

Support for the invalidComponentTracker binding option on input components

Use if your application uses validators or converters, and you want to track the validity of the Oracle JET components in your application.

ojs/ojcomponent:

Examples:

ojs/ojbutton

ojs/ojtoolbar

ojs/ojtabs

Oracle JET component modules. Most Oracle JET components have their own module with the same name in lowercase, except for the following components:

- ojButtonset: ojs/ojbutton

- ojInputPassword: ojs/ojinputtext

- ojTextArea: ojs/ojinputtext

- ojCombobox: ojs/ojselectcombobox

- ojSelect: ojs/ojselectcombobox

- ojSparkChart: ojs/ojchart

- ojDialGauge: ojs/ojgauge

- ojLedGauge: ojs/ojgauge

- ojRatingGauge: ojs/ojgauge

- ojStatusMeterGauge: ojs/ojgauge

Use component modules that correspond to any Oracle JET component in your application.

ojs/ojknockout

Oracle JET ojComponent binding and services for Knockout.js

Use if your application includes Oracle JET components and you want to use ojComponent binding for these components in Knockout.js.

ojs/ojrouter

Class for managing routing in single page applications

Use if your single page application uses oj.Router for routing.

ojs/ojmodule

Binding for Knockout.js that implements navigation within a region of a single page application

Use if your single page application uses the ojModule binding for managing content replacement within a page region.

ojs/ojoffcanvas

Methods for controlling off-canvas regions

Use if your application uses oj.offCanvasUtils for managing off-canvas regions.

ojs/ojcube

Class for aggregating data values in ojDataGrid

Use if your application renders aggregated cubic data in an ojDataGrid component.

Note:

Oracle JET includes several modules that aren't listed in this table because they are dependencies of other modules. When you load an Oracle JET component module, the module's dependencies are also loaded by default, and you do not need to include them explicitly. For example, ojTabs requires the ojs/ojcomponentcore module, and the ojs/ojcomponentcore module will load automatically when you specify the ojs/ojtabs module in your RequireJS bootstrap file.

Using RequireJS in an Oracle JET Application

Oracle JET includes the RequireJS library and sample bootstrap file in the Oracle JET download. To use RequireJS in your application, edit the bootstrap file to add the Oracle JET modules you need. You can also add your own modules as needed for your application code.

The code below shows the main-template.js bootstrap file distributed with Oracle JET. Typically, you place the bootstrap file in your application's js directory and rename it to main.js . The comments in the code describe the purpose of each section. The sections that you normally edit are highlighted in bold.

requirejs.config({
// Path mappings for the logical module names
paths: {
'knockout': 'libs/knockout/knockout-3.3.0',
'jquery': 'libs/jquery/jquery-2.1.3.min',
'jqueryui-amd': 'libs/jquery/jqueryui-amd-1.11.4.min',
'ojs': 'libs/oj/v1.1.2/min',
'ojL10n': 'libs/oj/v1.1.2/ojL10n',
'ojtranslations': 'libs/oj/v1.1.2/resources',
'signals': 'libs/js-signals/signals.min',
'crossroads': 'libs/crossroads/crossroads.min',
'text': 'libs/require/text',
'promise': 'libs/es6-promise/promise-1.0.0.min',
'hammerjs': 'libs/hammer/hammer-2.0.4.min'
},

// Shim configurations for modules that do not expose AMD
shim: {
'jquery': {
exports: ['jQuery', '$']
},
'crossroads': {
deps: ['signals'],
exports: 'crossroads'
}
},

// This section configures the i18n plugin. It is merging the Oracle JET built-in translation
// resources with a custom translation file.
// Any resource file added, must be placed under a directory named "nls". You can use a path mapping or you can define
// a path that is relative to the location of this main.js file.
config: {
ojL10n: {
merge: {
//'ojtranslations/nls/ojtranslations': 'resources/nls/myTranslations'
}
}
}
});

/**
* A top-level require call executed by the Application.
* Although 'ojcore' and 'knockout' would be loaded in any case (they are specified as dependencies
* by the modules themselves), we are listing them explicitly to get the references to the 'oj' and 'ko'
* objects in the callback
*
* For a listing of which JET component modules are required for each component,
* see the specific component demo pages in the JET cookbook.
*/
require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/knockout', 'ojs/ojbutton', 'ojs/ojtoolbar', 'ojs/ojmenu'],
// add additional JET component libraries as needed
function(oj, ko, $) // this callback gets executed when all required modules are loaded
{
// add any startup code that you want here
}
);

To use RequireJS in an Oracle JET Application:

1. Install Oracle JET and RequireJS as described in Using RequireJS to Manage Library, Link, and Script References.

2. In the bootstrap file or your application scripts, in the require() definition, add additional Oracle JET modules as needed using the modules listed in Oracle JET Module Organization.

For example, if your application uses the Oracle JET Common Model integrated with Knockout and includes an ojDialog component, you would add the highlighted code to your bootstrap file or application script.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojmodel', 'ojs/ojknockout-model','ojs/ojdialog'],
function(oj, ko) // obtaining a reference to the oj namespace
{
}
);

3. Add any scripts that your application uses to the require() definition and update the function(oj, ko) definition to include the script.

For example, if your script is named app.js, add the highlighted code to your require() definition.

require(['app', 'ojs/ojcore', 'knockout', 'jquery', 'ojs/ojmodel', 'ojs/ojknockout-model', 'ojs/ojdialog'],
function(app, oj, ko) // obtaining a reference to the oj namespace
{
}
);

Note:
You can also use RequireJS with the ojModule binding to define view templates and viewModels for page sections in a single-page application. For example, the Oracle JET QuickStart Basic Template uses the ojModule binding with RequireJS to use a different view and viewModel when the user clicks one of the navigation buttons.
For additional information about the Oracle JET QuickStart Basic Template, see Using the Oracle JET QuickStart Templates. For more information about using the ojModule binding and Knockout templates, see Creating Single-Page Applications.

4. Add any application startup code to the callback function.

For example, the following code adds a Knockout binding call to the callback function for an element named dialogWrapper.

require(['app', 'ojs/ojcore', 'knockout', 'jquery', 'ojs/ojmodel', 'ojs/ojknockout-model', 'ojs/ojdialog'],
function(app, oj, ko) // obtaining a reference to the oj namespace
{
ko.applyBindings(new app()/*View Model instance*/,
document.getElementById('dialogWrapper'));
}
);

5. If your application includes resource bundles, enter the path to the bundle in the merge section.

config: {
ojL10n: {
merge: {
'ojtranslations/nls/ojtranslations': 'resources/nls/myTranslations'
}
}
}

Troubleshooting RequireJS in an Oracle JET Application

RequireJS issues are often related to modules used but not defined.

Use the following tips when troubleshooting issues with your Oracle JET application that you suspect may be due to RequireJS:

- Check the JavaScript console for errors and warnings. If a certain object in the oj namespace is undefined, locate the module that contains it based on the information in Oracle JET Module Organization and add it to your application.

- If the Oracle JET widgets you specified using Knockout.js binding are not displayed and you are not seeing any errors or warnings, verify that you have added the ojs/ojknockout module to your application.

Using RequireJS for Lazy Loading Modules in an Oracle JET Application

You can configure your application to load Oracle JET modules only when needed.

The first require() call in the main configuration file should only request modules that are needed for the initial display of the page. If you need other modules after certain user actions, such as displaying a dialog or transitioning to a different external template, you can load them with separate require() calls.

You can also execute a require() call without a callback function if you want to preload some modules in anticipation of user actions. The modules would still need to be requested using the require() call when they would actually be used, but they would already be downloaded and executed due to the preload.

You can also choose not to wait for some heavier components to be downloaded before calling the initial ko.applyBindings(). To do this, use a ko.observable() to supply the component name and set it initially to null. With the initial value being null, the component will not be displayed. Once the module is loaded, you can change the value to the actual component name.

// In your View Model:
this.statusGaugeComponent = ko.observable(null);

// In your markup:
<div data-bind="ojComponent: {
component: statusGaugeComponent,
min: 0,
max: 100,
value: statusGaugeValue,
}">
</div>

// Request ojs/ojgauge after the rest of the UI is already displayed:
require(['knockout, 'ojs/ojknockout', 'ojs/ojgauge'],
function(ko)
{
// Mutate the observable with the actual component name
myViewModel.statusGaugeComponent(
"ojStatusMeterGauge");
}
);

Note:

You can also configure your application to lazy load content. For example, you can configure an ojTree component to populate child nodes only when selected. See the Oracle JET Cookbook at Lazy Loading (ojTree) for an example.

Using JavaScript Partitions and RequireJS in an Oracle JET Application

RequireJS supports JavaScript partitions that contain more than one module.

You must name all modules using the RequireJS bundles option and supply a path mapping with the configuration options.

requirejs.config(
{
bundles:
{
'commonComponents': ['ojL10n', 'ojtranslations/nls/ojtranslations',
'ojs/ojcore', 'ojs/ojknockout', 'ojs/ojcomponentcore',
'ojs/ojbutton', 'ojs/ojpopup'],
'tabs': ['ojs/ojtabs', 'ojs/ojconveyorbelt']    }
}
);

In this example, two partition bundles are defined: commonComponents and tabs.

RequireJS ships with its own Optimizer tool for creating partitions and minifying Javascript code. The tool is designed to be used at build time with a complete project that is already configured to use RequireJS. It analyzes all static dependencies and creates partitions out of modules that are always loaded together. The Oracle JET team recommends that you use an optimizer to minimize the number of HTTP requests needed to download the modules.

For additional information about the RequireJS Optimizer tool, see http://requirejs.org/docs/optimization.html.

For additional information about optimizing performance of Oracle JET applications, see Optimizing Performance.

5 Creating Single-Page Applications

The Oracle JET framework includes the Knockout.js library, ojModule binding, and oj.Router framework class that you can use to create single-page applications to simulate the look and feel of desktop applications. The ojModule binding for Knockout.js manages content replacement within a particular region of the page. The ojModule binding can work in conjunction with oj.Router , which provides routing support for Oracle JET applications..

Topics:

- Typical Workflow for Creating Single-Page Applications in Oracle JET

- Designing Single-Page Applications Using Oracle JET

- Using Knockout.js Templates and the ojModule Binding

Typical Workflow for Creating Single-Page Applications in Oracle JET

To create a single-page application in Oracle JET, refer to the typical workflow described in the following table:

Task

Description

More Information

Create a single-page Oracle JET application

Identify Oracle JET's framework support for single-page applications and how to use it to design your Oracle JET application.

Designing Single-Page Applications Using Oracle JET

Create view templates and viewModels

Identify the features and benefits of Knockout templates and the ojModule binding and how to use them in your Oracle JET application.

Using Knockout.js Templates and the ojModule Binding

Designing Single-Page Applications Using Oracle JET

The Oracle JET framework includes Knockout for separating the model layer from the view layer and managing the interaction between them. Using Knockout, the Oracle JET ojModule binding, and the Oracle JET oj.Router framework class, you can create single-page applications that look and feel like a standalone desktop application.

Topics:

- Understanding Oracle JET Framework Support for Single-Page Applications

- Creating a Single-Page Application in Oracle JET

Understanding Oracle JET Framework Support for Single-Page Applications

Single-page applications (SPAs) are typically used to simulate the look and feel of a standalone desktop application. Rather than using multiple web pages with links between them for navigation, the application uses a single web page that is loaded only once. If the page changes because of the user's interaction, only the portion of the page that changed is redrawn.

The Oracle JET framework includes support for single page applications using the oj.Router class for virtual navigation in the page, the ojModule binding for managing view templates and viewModel scripts, and Knockout for separating the model layer from the view layer and managing the interaction between them.

In the Oracle JET SPA-ojModule-ojRouter application shown in the image below, the index.html page displays a simple page with a toolbar for choosing the Home, Book, and Tables content.

When the user selects a toolbar item such as the Book button, the new content displays, and the URL changes to reflect the user's current location on the page.

If the user chooses several chapters to display, the browser remembers the previous selections. When the user selects the browser's back function, the URL and page content change to reflect the user's previous selection.

In this example, routing is handled using path segments (web_site/book), but you can also configure routing to use query parameters (web_site/index.html?root=book).

In general, use query parameters when your application contains only a few views that the user will bookmark and that are not associated with a complex state. Use path segments to display simpler URLs, especially for nested paths such as book/preface/intro.

The Oracle JET Cookbook and Oracle JET sample applications use the native templating mechanism included with Knockout.js, and many use the Oracle JET ojModule namespace to manage the Knockout binding. With ojModule, you can store your HTML content for a page section in a template file and the JavaScript functions that contain your viewModel in a viewModel file.

When ojModule and oj.Router are used in conjunction, you can configure an ojModule object where the module name is the router state. When the router changes state, ojModule will automatically load and render the content of the module name specified in the value of the current RouterState object.

ojModule is not specific to single-page applications, and you can use it to reuse content in multi-page applications. For additional information about Knockout templates and ojModule, see Using Knockout.js Templates and the ojModule Binding

Creating a Single-Page Application in Oracle JET

The Oracle JET Cookbook includes complete examples and recipes for creating a single-page application using path segments and query parameters for routing and examples that use routing with the ojModule binding. Regardless of the routing method you use, the process to create the application is similar.

To create a single-page application in Oracle JET:

1. Create the application that will house your main HTML5 page and supporting JavaScript. For additional information, see Getting Started with Oracle JET.

2. Design the application's structure.
Identify the templates and ViewModels that your application will require. For example, the SPA-ojModule-ojRouter single-page sample application defines templates for the header and footer. The content for the main container will vary, depending upon the router configuration. The code sample below shows the index.html file.

<!DOCTYPE html>

<html lang="en-us">
<head>
... contents omitted
</head>
<body>
<div id="globalBody" style="display: none">
<header id="headerWrapper" role="banner" data-bind="ojModule: 'header'"></header>
<!-- This is where your main page content will be loaded -->
<div id="mainContainer" role="main" data-bind="ojModule: router.moduleConfig"></div>
<footer id="footerWrapper" role="contentinfo" data-bind="ojModule: 'footer'"></footer>
</div>
</body>
</html>

In this example, ojModule manages content replacement for the header, main content, and footer sections of the body, and oj.Router provides routing support. For additional information about working with Knockout templates and ojModule, see Using Knockout.js Templates and the ojModule Binding.

The application also contain content that displays when the user clicks Book and Tables in the application header. To manage the content for those sections, the application includes the bookContent.html and tablesContent.html view templates with corresponding bookContent.js and tablesContent.js ViewModels.

The image below shows the directory structure for the SPA-ojModule-ojRouter single-page sample application. The ViewModel definitions are contained in JavaScript files in the js/viewModels folder, and the view templates are contained in HTML files in the js/views folder.

3. Add code to your application's main script that defines the states that the router can take, and add the ojs/ojrouter module to your require() list.
For example, in the SPA-ojModule-ojRouter sample application, the router can be in the home, book, or tables states. The code sample below shows the code that configures the router.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'ojs/ojmodule', 'ojs/ojrouter', 'text'],
function(oj, ko, $) // this callback gets executed when all required modules are loaded
var router = oj.Router.rootInstance;
router.configure({
'home':   { label: 'Home',   value: 'homeContent', isDefault: true },
'book':   { label: 'Book',   value: 'bookContent' },
'tables': { label: 'Tables', value: 'tablesContent' }
});
// Only the router is need in the viewModel
var viewModel = {
router: router
};

// To change the URL adapter, un-comment the following line
// oj.Router.defaults['urlAdapter'] = new oj.Router.urlParamAdapter();

oj.Router.sync().then(
function() {
ko.applyBindings(viewModel);
$('#globalBody').show();
},
function(error) {
oj.Logger.error('Error when starting router: ' + error.message);
});
});

To configure the router for query parameters, remove the comment as directed above:

oj.Router.defaults['urlAdapter'] = new oj.Router.urlParamAdapter();

To configure the router for path segments, you must also set the baseUrl property to the base URL of the application. This provide the router with a base to calculate which part belongs to the router state and which part is the existing URL.

requirejs.config({
baseUrl: "<a target="_blank" href="http://myApp/myLocation"/">http://myApp/myLocation"/</a>,
// Path mappings for the logical module names
paths: {
... contents omitted
});

Note:

Routing with path segments also requires that the web server recognizes the paths as existing resources and routes the requests to the root page. If you're using the Apache web server, you can use the mod_rewrite module to rewrite requested URLs on demand. For other web servers, you can create a servlet filter or use one of the publicly available URL rewrite filters.

4. Add code to the markup that triggers the state transition and displays the content of the current state.
For example, the Oracle JET SPA-ojModule-ojRouter single-page sample application defines buttons in a button set in the header section that trigger the router state transition when the user clicks a button. The code sample below shows a portion of the header.html markup.

<div class="demo-appheader-toolbar-container">
<div class="demo-appheader-toolbar oj-toolbar-half-chrome" aria-controls="player"
data-bind="ojComponent: {component:'ojToolbar'}">
<div class="oj-button-half-chrome demo-appheader-toolbar-button"
data-bind="ojComponent: { component: 'ojButtonset',
checked: $root.router.stateId(),
focusManagement: 'none'}">
<!-- ko foreach: $root.router.states -->
<label data-bind="attr: {for: id}"></label>
<input type="radio" name="view"
data-bind="value: id, click: go, attr: {id: id},
ojComponent: {component: 'ojButton', label: label}"/>
<!-- /ko -->
</div>
</div>
</div>

When the user clicks one of the toolbar buttons in the header, the content is loaded according to the router's current state. For example, when the user clicks the Book button, the method specified in the click option executes. In this example, the go() method of the RouterState object associated with the Book button executes. Once the state successfully changes to book, the value of router.moduleConfig changes to an object representing the book module, and ojModule changes the content to display the bookContent.html view and load the bookContent.js ViewModel.

For additional information about creating templates and ViewModels, see Using Knockout.js Templates and the ojModule Binding.

5. To manage routing within a module, add a child router using oj.Router.createChildRouter().
For example, when the user clicks Books , the page displays a list of chapters that the user can select. The user can move back and forth between the chapters, and the child router maintains the state. The HTML markup is stored in the bookContent.html template and is shown below.

<div id="chapter" class="oj-row">
<div class="oj-xl-2 oj-lg-2 oj-md-2 oj-sm-12 oj-col">
<br>
<div id="menu" data-bind="ojComponent:{ component: 'ojNavigationList',
selection: router.stateId(),
beforeSelect: selectHandler,
drillMode: 'none' }">
<ul data-bind="foreach: router.states">
<li data-bind="attr: {id: id}">
<a data-bind="text: label"></a>
</li>
</ul>
</div>
</div>
<div class="oj-xl-10 oj-lg-10 oj-md-10 oj-sm-12 oj-col" data-bind="if: router.stateId()">
<div role="main" class="oj-panel demo-page-content-area" data-bind="with: router.currentState()">
<h2 id="currentPage" class="oj-header-border" data-bind="text: label"/>
<h4 data-bind="text: value"/>
</div>
</div>
</div>

The template defines the Oracle JET ojNavigationList component and uses the router's state IDs as an argument to the ojNavigationlist selection option. To display the chapter list, the template iterates through each RouterState object in the router.states property.

The code sample below shows the bookContent.js file that defines the child router and a portion of the book content. As with the parent router, the code defines all possible states for the page region.

define(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout',
'ojs/ojrouter', 'ojs/ojnavigationlist'], function(oj, ko, $) {
var chapters = {
'preface': 'Darn beamed hurriedly because banal more ...',
'chapter1': 'Affectingly and yikes one that along ...'
'chapter2': 'More up mistaken for a kissed therefore ...',
'chapter3': 'Reindeer up while the far darn falcon...'
};

// The view model for the book page
var viewModel = {
router: undefined,

initialize: function(params) {
// Retrieve parentRouter from ojModule parameter
var parentRouter = params.valueAccessor().params;

// Restore current state from parent router, if exist.
var currentState = parentRouter.currentState();
if (!currentState.storage) {
currentState.storage = chapters;
}
this.router = parentRouter.createChildRouter('chapter')
.configure({
'preface': {  label: 'Preface',   value: currentState.storage['preface'] },
'chapter1': { label: 'Chapter 1', value: currentState.storage['chapter1'] },
'chapter2': { label: 'Chapter 2', value: currentState.storage['chapter2'] },
'chapter3': { label: 'Chapter 3', value: currentState.storage['chapter3'] }
});

// Now that the router for this view exist, synchronise it with the URL
oj.Router.sync();
},

selectHandler: function(event, ui) {
if ('menu' === event.target.id && event.originalEvent) {
// Invoke go() with the selected item.
viewModel.router.go(ui.key);
}
},

dispose: function() {
this.router.dispose();
this.router = null;
}
};

return viewModel;
});

6. Add any remaining code needed to complete the content or display.

You can download the Oracle JET SPA-ojModule-ojRouter application at SPA-ojModule-ojRouter.zip. The sample application includes the simple index.html page displayed in the preceding example and the content for the Book and Tables sections.

The Oracle JET Cookbook also includes additional Routing Demos that implement oj.Router and a link to the oj.Router API documentation.

Using Knockout.js Templates and the ojModule Binding

The Oracle JET Cookbook and many sample applications use the native templating mechanism included with Knockout.js and the Oracle JET ojModule namespace to manage the binding. Knockout templates capture the HTML markup contained in an element and use it as a template to render against an arbitrary data item. Knockout templates allow you to reuse code and provide a simple mechanism for building UI structures as a function of your viewModel data.

For example, the SPA-ojModule-ojRouter sample single-page application uses five templates to define the HTML markup for the application. The image below shows the main page for the Oracle JET Sample Single Page application as it runs on the desktop, with arrows pointing to the names of the templates defining view content for the application.

The homeContent template is shown below. In the highlighted code, the first data-bind definition uses Knockout's text binding to set the h1 element's content to a text node containing the value of $root.title. The second data-bind definition uses Knockout's foreach binding to iterates through the content, and the list items display the text defined in line.

<div class="oj-row">
<div class="oj-xl-9 oj-lg-9 oj-md-9 oj-sm-12 oj-col">
<div role="main" class="oj-panel demo-page-content-area">
<h2 data-bind="text: title"></h2>
<!-- ko foreach: description -->
<p data-bind="text: line"></p>
<!-- /ko -->
</div>
</div>
<div class="oj-xl-3 oj-lg-3 oj-md-3 oj-sm-12 oj-col">
<div class="oj-panel oj-panel-alt2 demo-page-content-area">
<p>Click on the toolbar buttons to switch which component is displayed in this page.</p>
</div>
</div>
</div>

The code that defines the title and line is contained in the viewModel for the home section's content, stored in the homeContent.js viewModel.

/* Home content module, example of singleton view model object. */
define(['knockout', 'ojs/ojknockout', 'ojs/ojbutton'], function(ko) {
return {
title: 'Welcome to the JET Router demo',
description: [{
line: 'This application demonstrates how the Jet Router \
library can simplify building large applications.'
}, {
line: 'This is a single page application made of three independent components: \
Home, Book and Tables. You are currently looking at the Home component.'
}]
};
});

To add Knockout.js templates and the ojModule binding to your Oracle JET application:

1. Create the application that will house your main HTML5 page and supporting JavaScript. For additional information, see Getting Started with Oracle JET.

2. To modify the default location of the application���s view templates and viewModel scripts, add code to the application's main script that initializes the location of the viewModels and view templates and defines the suffix for the view templates.

The ojModule binding namespace contains the default location and names of managed templates and viewModels.

Property

Description

viewPath

Defines the path to the view templates. Defaults to text!..views/

viewSuffix

Defines the suffix for view templates. Defaults to .html.

modelPath

Defines the location of the viewModel scripts. Defaults to viewModels/

The Oracle JET SPA-ojModule-ojRouter sample application uses the default locations and paths for its view templates and viewModels. However, the Oracle JET QuickStart Basic Template application stores the templates in the js/templates folder, and the viewModels in the modules/ folder. The application also uses .tmpl.html for the view templates' suffix. The code sample below shows the lines to add to your application's main script to change the default locations and names of managed templates and viewModels.

oj.ModuleBinding.defaults.modelPath = 'modules/';
oj.ModuleBinding.defaults.viewPath = 'text!../templates/';
oj.ModuleBinding.defaults.viewSuffix = '.tmpl.html';

3. In your RequireJS bootstrap file (typically main.js) add ojs/ojmodule to the list of RequireJS modules, along with any other modules that your application uses.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'ojs/ojmodule', 'ojs/ojrouter', 'text'],

4. If needed, create a templates folder in the default location or in the viewPath if you defined one in the previous step.

5. Create your view templates and add them to the viewPath folder.

Use the default viewSuffix or the value you set for the viewSuffix in Step 2.

6. If needed, create a folder for your viewModels in the default location or in the modelPath you specified in Step 2.

7. As needed, create your viewModel scripts and add them to the modelPath folder.
Use the same name for the module that you used for the template in Step 5. For example, if your template is named bookContent.html, use bookContent.js for the viewModel's name.

8. Add code to the application's HTML page to reference the view template or viewModel in the ojModule binding.
If the page section contains only a view template, use ojModule with the viewName option:

<header id="headerWrapper" role="banner" data-bind="ojModule: { viewName: 'sampleView'}"></div>

To reference a viewModel with a view template, use ojModule with the name option:

<header id="headerWrapper" role="banner" data-bind="ojModule: { name: 'sampleViewModel'}"></div>

If you're using oj.Router, use ojModule with the router.moduleConfig option.

<div id="mainContainer" data-bind="ojModule: router.moduleConfig"></div>

For more information about oj.Router and ojModule, see the Oracle JET oj.Router and ojModule API documentation.

For more information about using Knockout's template binding, see http://knockoutjs.com/documentation/template-binding.html.

6 Understanding Oracle JET User Interface Basics

The Oracle JET framework provides a variety of user interface (UI) components and elements that you can use in your application for working with forms, data collections, data visualizations, menus, buttons, layout, and navigation. The process to add an Oracle JET component to your page is the same for most components, and you may also find the following collection of tips and tricks helpful for working with the Oracle JET UI.

Topics:

- Typical Workflow for Working with the Oracle JET User Interface

- About the Oracle JET User Interface

- Adding an Oracle JET Component to Your Page

- Working with Forms

- Working with Buttons, Button Sets, and Toolbars

- Working with Menus

- Working with Data Collections

- Working with Data Visualizations

- Working with Layout and Navigation

- Adding jQuery UI Components or Effects to Your Oracle JET Application

Typical Workflow for Working with the Oracle JET User Interface

To work with the Oracle JET user interface components, refer to the typical workflow described in the following table:

Task

Description

More Information

Understand the Oracle JET UI framework

Identify Oracle JET UI components, understand their common functionality, and identify Oracle JET reserved words.

About the Oracle JET User Interface

Add an Oracle JET component to your page

Identify the steps you must take to add an Oracle JET component to your HTML5 page.

Adding an Oracle JET Component to Your Page

Work with forms

Identify tips and tricks for working with form elements, including form controls, layout, validation and messaging, label, input, selection, and switch components.

Working with Forms

Work with buttons, button sets, and toolbars

Identify tips and tricks for working with buttons, button sets, and toolbars.

Working with Buttons, Button Sets, and Toolbars

Work with menus

Identify tips and tricks for working with menus, menu buttons, and context menus.

Working with Menus

Work with data collections

Identify tips and tricks for working with tables, data grids, list views, trees, row expanders, and pagination.

Working with Data Collections

Work with data visualizations

Identify tips and tricks for working with data visualizations, including charts, diagrams, gauges, NBoxes, sunbursts, tag clouds, thematic maps, timelines, and treemaps.

Working with Data Visualizations

Work with layout and navigation components, elements, and patterns

Identify tips and tricks for working with collapsibles, accordions, panels, conveyor belts, film strips, masonry layouts, tabs, trains, HTML tags, dialogs, progress indicators, nav lists, drawer utilities, and popups.

Working with Layout and Navigation

Add jQuery UI components or effects to your Oracle JET application

Understand process to download additional jQuery UI modules and integrate them into your Oracle JET application.

Adding jQuery UI Components or Effects to Your Oracle JET Application

About the Oracle JET User Interface

The Oracle JET framework includes many components, patterns, and utilities that are ready for you to use in your application. Each Oracle JET UI component, pattern, and utility includes an API specification (if applicable) and a code example in the Oracle JET Cookbook. The Oracle JET Cookbook includes HTML markup and JavaScript that you can copy and paste into your own application.

Topics:

- Oracle JET and jQuery UI

- Identifying Oracle JET UI Components, Patterns, and Utilities

- Common Functionality in Oracle JET Components

- Oracle JET Reserved Namespaces and Prefixes

Oracle JET and jQuery UI

Oracle JET components encapsulate jQuery UI widgets, which are stateful plugins with a full life cycle that you can add to your page. jQuery UI widgets include methods and events which are described in jQuery UI API documentation at http://api.jqueryui.com.

By encapsulating jQuery UI widgets, Oracle JET components can take advantage of Knockout.js two-way data binding. Knockout is not required, however, and you can also work with Oracle JET components using standard jQuery calls.

Note:

The jQuery UI libraries included with Oracle JET contain the UI Core module and only those modules needed by the Oracle JET framework. For information about what is included in jQuery UI Core, see http://jqueryui.com/download. For information about downloading jQuery UI components or effects not included in the Oracle JET distribution, see Adding jQuery UI Components or Effects to Your Oracle JET Application.

Identifying Oracle JET UI Components, Patterns, and Utilities

The table below shows the list of Oracle JET UI components with links to an overview, the API documentation, and the code sample in the Oracle JET Cookbook.

Component

Overview

API Specification

Cookbook Example

Accordion

Working with Layout and Navigation

ojAccordion

Accordions

Button

Working with Buttons

ojButton

Buttons

Button set

Working with Button Sets

Button Sets

Button Sets

Chart

Working with Data Visualizations

ojChart

Charts

Checkbox Set

Working with Checkbox and Radio Sets

ojCheckboxset

Checkbox Sets

Collapsible

Working with Collapsibles

ojCollapsible

Collapsibles

Combobox

Working with Comboboxes

ojCombobox

Comboboxes

Conveyor Belt

Working with Conveyor Belts

ojConveyorBelt

Conveyor Belts

Data Grid

Working with Data Grids

ojDataGrid

Data Grids

Date and Time Picker

Working with Text Input Components

ojInputDateTime

Date and Time Pickers

Date Picker

Working with Text Input Components

ojInputDate

Date Pickers

Diagram

Working with Data Visualizations

ojDiagram

Diagrams

Dial Gauge

Working with Data Visualizations

ojDialGauge

Dial Gauges

Dialog

Working with Dialogs

ojDialog

Dialogs

Drawer Utilities

Working with offCanvasUtils

oj.OffcanvasUtils

Drawer Utilities

Film Strip

Working with Film Strips

ojFilmstrip

Film Strips

Input Number

Working with Text Input Components

ojInputNumber

Input Number

Input Password

Working with Text Input Components

ojInputPassword

Input Password

LED Gauge

Working with Data Visualizations

ojLedGauge

LED Gauges

Legend

Working with Data Visualizations

ojLegend

Legends

List View

Working with List Views

ojListView

List Views

Masonry Layout

Working with Masonry Layouts

ojMasonryLayout

Masonry Layouts

Menu

Working with Menus

ojMenu

Menus

Nav List

Working with Nav Lists

ojNavigationList

Nav Lists

NBox

Working with Data Visualizations

ojNBox

NBoxes

Pagination

Working with Pagination

ojPagingControl

Pagination

Popup

Working with Popups

ojPopup

Popups

Progress Indicator

Working with Progress Indicators

ojProgressbar

Progress Indicators

Radioset

Working with Checkbox and Radio Sets

ojRadioset

Radio Sets

Rating Gauge

Working with Data Visualizations

ojRatingGauge

Rating Gauges

Row Expander (Tree Table)

Working with Row Expanders

ojRowExpander

Row Expanders

Select

Working with Select

ojSelect

Select

Slider

Working with Sliders

ojSlider

Sliders

Spark Chart

Working with Data Visualizations

ojSparkChart

Spark Charts

Status Meter Gauge

Working with Data Visualizations

ojStatusMeterGauge

Status Meter Gauges

Sunburst

Working with Data Visualizations

ojSunburst

Sunbursts

Switch

Working with Switches

ojSwitch

Switches

Table

Working with Data Collections

ojTable

Tables

Tabs

Working with Tabs

ojTabs

Tabs

Tag Cloud

Working with Data Visualizations

ojTagCloud

Tag Clouds

Text Area

Working with Text Input Components

ojTextArea

Text Areas

Textbox

Working with Text Input Components

ojInputText

Textboxes

Thematic Map

Working with Data Visualizations

ojThematicMap

Thematic Maps

Time Picker

Working with Text Input Components

ojInputTime

Time Pickers

Timeline

Working with Data Visualizations

ojTimeLine

Timelines

Toolbar

Working with Toolbars

ojToolbar

Toolbars

Train

Working with Trains

ojTrain

Trains

Tree

Working with Trees

ojTree

Trees

Treemap

Working with Data Visualizations

ojTreemap

Treemaps

Common Functionality in Oracle JET Components

All Oracle JET components extend HTML elements, and you add the components to the HTML tags on your page.

Some Oracle JET components extend a single HTML element. For example, the ojTable component extends the HTML table element, and the ojInputText component extends input.

Other Oracle JET components can extend multiple HTML elements. For example, the ojButton component can extend button, input, and div. In some cases, the behavior of the component changes depending on which HTML element you are extending. The inputDateTime component displays a calendar inline if you use it to extend the div element, but it will display an input field with a calendar popup if you use it to extend the input element.

The Oracle JET Cookbook and JavaScript API Reference for Oracle�� JavaScript Extension Toolkit (JET) provide examples that illustrate which HTML element to extend if you use the component. In addition, the Cookbook provides editing capability that allows you to modify the sample code directly and view the results without having to download the sample.

Oracle JET components also have the following functionality in common:

- getNodebySubId() and getSubIdByNode() methods
The getNodeBySubId() and getSubIdByNode() methods provide safe access to an Oracle JET component's internal parts to check values and test components. Most Oracle JET components will consist of one or more internal parts. For example, an Oracle JET table component has table cells that you can access with the getNodeBySubId() method. For additional information, see Testing Oracle JET Applications.

- getContextByNode() method
The getContextByNode() method is available on most DVT components and provides access to the component���s internal child DOM nodes. The method returns an object containing the context for the given node, including the child node���s subid and optional component-specific information. For additional information about the method and context objects, see the API documentation for the given component.

- rootAttributes option
Most Oracle JET components provide the rootAttributes option which enables you to set attributes on the component's root DOM element at create time. Supported attributes include id, which overwrites any existing value, and class and style, which are appended to the current class and style, if any.

- Keyboard navigation and other accessibility features
Oracle JET components that support keyboard navigation list the end user information in their API documentation. For additional information about Oracle JET components and accessibility, see Developing Accessible Applications.

- Setting component state
In Oracle JET applications, when setting component state after create time, the correct approach depends on whether the component has a JavaScript (JS) API for that state.

State with a JS API, such as a button's disabled state, checked state, and label, should be set after creation through that API (option(), for example) and not by directly manipulating the DOM after creation. This can be done by calling that JS API directly or by binding a component option such as disabled to a Knockout observable using the ojComponent binding. In the latter case, the application should make any updates to the component option through the observable because any updates to the observable made by the application automatically update the component option. Likewise, options like value that can change because of user interaction automatically update the observable.

State with no JS API should be set by manipulating the DOM directly in an allowable way, and then calling refresh() on the affected components. For example, call refresh() if the reading direction is changed by setting the dir attribute on the html node.

When using a built-in Knockout binding instead of the ojComponent binding, keep in mind that those bindings do not execute the necessary refresh() call after updating the DOM. Updates that flow from the component to the observable, because of user interaction, are not problematic. But updates in the other direction, that programmatically update the DOM because the observable changed, will not be picked up until the next refresh().

Oracle JET Reserved Namespaces and Prefixes

Oracle JET reserves the oj namespace and prefixes. This includes, but is not limited to component names, namespaces, pseudo-selectors, public event prefixes, CSS styles, Knockout binding keys, and so on.

Adding an Oracle JET Component to Your Page

Use the Oracle JET Cookbook recipes and API documentation for examples using the specific component you want to add to your page.

To add an Oracle JET component to your page:

1. Create the application that will house your main HTML5 page and supporting JavaScript. For additional information, see Getting Started with Oracle JET.

2. Identify the Oracle JET component that you want to add.

You can use the table in About the Oracle JET User Interface to identify the Oracle JET component.

3. Use the Oracle JET Cookbook for the recipe and markup to use to add your component to the HTML page.

All Oracle JET recipes include the basic format for initializing the component using Knockout.js data-bind syntax. The code below shows the markup for the ojInputDateTime example shown in the Date and Time Pickers demos.

<div id="div1">
<label for="dateTime">Default</label>
<input id="dateTime"
data-bind="ojComponent: {component: 'ojInputDateTime', value: value}"/>
<br/><br/>
<span class="oj-label">Current component value is:</span>
<span data-bind="text: value"></span>
</div>

In this example, the ojInputDateTime component is defined with the value option using the ojComponent binding, which is a Knockout binding that initializes the Oracle JET component. Each Oracle JET component includes additional options that are defined in the component's API documentation.

You can also use standard jQuery syntax to initialize the component, and the API documentation provides examples for doing so. However, the Oracle JET team recommends that you use the Knockout binding to simplify working with your view model.

For more information about Knockout.js data-bind syntax, see http://knockoutjs.com/documentation/binding-syntax.html.

Note:

If you use the foreach Knockout binding with an Oracle JET component, you cannot place it on the same node as the ojComponent binding. Instead, create a nested virtual element and place it before the ojComponent binding.

<!-- ko foreach: drinkRadios -->
<label data-bind="attr: {for: id}"></label>
<input type="radio" name="beverage"
data-bind="value: id, attr: {id: id},
ojComponent: {component: 'ojButton', label: label}"/>
<!-- /ko -->

4. Use the Oracle JET Cookbook for example scripts and the syntax to use for adding the component to your RequireJS bootstrap file.

For example, the basic demo for the ojInputDateTime component includes the following script that you can use in your application.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'ojs/ojdatetimepicker'],
function (oj, ko, $)
{

function SimpleModel()
{
this.value = ko.observable(oj.IntlConverterUtils.dateToLocalIso(new Date(2013, 0, 1)));
}

$(document).ready(function ()
{
ko.applyBindings(new SimpleModel(), document.getElementById('div1'));
});

});

If you already have a RequireJS bootstrap file, compare your file with the Cookbook sample and merge in the differences. If you're not using RequireJS, you can use the HTML script element to add the $(document).ready(function()) to your page. However, RequireJS is required for internationalization and Oracle JET data visualization component support and is also recommended by the Oracle JET team. For details about working with RequireJS, see Using RequireJS for Modular Development.

Working with Forms

The Oracle JET framework includes classes that you can use to create responsive form layouts and components that you can add to your form to manage labels, form validation and messaging, input, and selection. The input components also include attributes that you can use to mark an input disabled or read only.

Topics:

- Working with Form Layout Features

- Working with Form Controls

- Working with Form Validation and User Assistance

- Working with Labels

- Working with Sliders

- Working with Text Input Components

- Working with Selection Components

Working with Form Layout Features

Oracle JET provides style classes that you can use to create form layouts that adjust to the size of the user's screen. For additional information, see Creating Responsive Form Layouts. For examples that illustrate best practices for form layout in Oracle JET applications, see Form Layout.

Working with Form Controls

Oracle JET components that support input, such as the ojInputText component, provide form controls that you can use to indicate that a component is disabled or, in some cases, read only. When the component is disabled, the input fields appear grayed out, and keyboard navigation is also disabled. When the component is set to read only, the input field is not displayed, and keyboard navigation is disabled as well.

To set a component to disabled or read only, you set the disabled or readOnly option in the markup and specify the method that will be called when the component is marked disabled or readOnly. The following code sample shows the markup for the ojInputText component.

<div id="form-container">
... contents omitted
<div class="oj-col">
<label for="inputcontrol">input</label>
</div>
<div class="oj-col">
<input id="inputcontrol"
data-bind="ojComponent: {component: 'ojInputText', value:'text',
disabled: disableFormControls,
readOnly: readonlyFormControls}"/>
</div>
</div>

The disableFormControls() and readonlyFormControls() methods set the Knockout observable to false.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'ojs/ojinputtext'],
function(oj, ko, $)
{
function StateModel() {
this.disableFormControls = ko.observable(false);
this.readonlyFormControls = ko.observable(false);
}
$(document).ready(
function()
{
ko.applyBindings(new StateModel(),
document.getElementById('form-container'));
}
);
});

Note:

You can also set disabled as an attribute on the input element. If you use this method, then disabled will only be picked up at component creation. Changing the native input element's disabled state after creation will have no effect.

The Oracle JET Cookbook at Form Controls includes the complete example for the ojInputText component as well as the other Oracle JET components that support disabled and readOnly options. In addition, you can find examples for using placeholder text and controlling the form's width and height.

Working with Form Validation and User Assistance

The Oracle JET editable components display help, converter and validator hints, title, and messaging content by default. If needed, you can customize the defaults for displaying the content.

The image below shows examples of converter hints and title. The top example uses default converter hints, and the bottom example uses custom placeholder text. The title text by default appears in the note window

You can create multiple validators on a component. The image below shows an example that uses multiple validators on an ojInputDateTime component.

The Oracle JET Cookbook contains complete examples that you can use to customize help, converter and validator hints, title, and messaging content. See Help, Hints, and Messaging.

For more information about best practices for form validation, see Applying Form Validation Best Practices.

For information about validating and converting input on the Oracle JET input components, see Validating and Converting Input. For information about using and customizing Oracle JET user assistance, see Working with User Assistance.

Working with Labels

The Oracle JET input components (ojInputText, ojTextArea, ojInputDate, and so on) automatically find their label and apply additional DOM and styling to the label element. To allow the input components to find their label, you must do one of the following:

- Use for on the label to point to the id of the input component.

<label for="input">input</label>
<input id="input"
data-bind="ojComponent: {component: 'ojInputText', value:'text'}"/>

- Use aria-labelledby on the DOM node to point to the id of the label.

<label id="inputtextlabel">input</label>
<div id="input" aria-labelledby="inputtextlabel"
data-bind="ojComponent: {component: 'ojInputText', value:'text'}"/>

Labels are top aligned by default, following best practices for mobile devices.

You can modify the labels to display inline by adding the oj-label-inline class to the HTML label element.

<div>
<label for="input" class="oj-label-inline">input</label>
<input id="input"
data-bind="ojComponent: {component: 'ojInputText', value:'text'}"/>
</div>

When the user runs the page, the label for the ojInputText component displays inline.

The Oracle JET Cookbook includes additional examples for using help and required modifiers. In addition, the cookbook contains examples for displaying access keys, making multiple labels on one field accessible, and making multiple fields on one label accessible. For details, see Labels.

Working with Sliders

A slider component displays a horizontal or vertical bar representing a numeric range and one or two thumbs, also called handles. The Oracle JET ojSlider component enhances the HTML input element to provide a slider component that is themable and WAI-ARIA compliant.

Topics

- About the ojSlider Component

- Creating Sliders

- Formatting Tips for ojSlider

About the ojSlider Component

The ojSlider component supports horizontal or vertical sliders with one or two thumbs. The user can use gestures, mouse, or keyboard on the thumb to adjust the value within the slider���s range when one thumb is present or set a range within the slider when two thumbs are present.

The following image shows three ojSlider components. The top two components illustrate sliders with horizontal orientation. In the first slider, the slider���s current value is shown as 100. In the middle slider, the user selected a range from 100 to 400. The bottom slider shows a slider with the vertical orientation, with current value set to 100.

Creating Sliders

To create the ojSlider component, add the HTML input element to a div container element or your form container and use the ojComponent binding to create the component. Use the component's min and max options to set the slider range and the component���s value option to set the thumb���s initial value.

To add the ojSlider component to your page:

1. Add the markup to your page for the HTML container element, the HTML input element, and the ojComponent binding for the ojSlider component. Use the component���s type option to specify whether the slider has one thumb or two.

a. To create a slider with a single thumb, set the component���s type option to single (the default), fromMin, or fromMax.

The following code sample shows the markup for the horizontal slider with a single thumb shown in this section. In this example, the type option is set to fromMin, which will color the bar from the minimum (min) value to the slider thumb.

<div id="slider-container">
<label for="slider-id"> ojSlider component for="slider-id"> ojSlider component</label>
<input id="slider-id"
data-bind="ojComponent: {
component: 'ojSlider',
type: 'fromMin',
max:max,
min:min,
step:step,
value:currentValue
}"/>
<span> Current Value: </span>
<span> id="curr-value" data-bind="text: currentValue"></span>
</div>

For additional information about the fromMin option and other formatting tips, see Formatting Tips for ojSlider

b. To create a slider with two thumbs, set the type option to range and the value option to an array containing two numbers.

The following code sample shows the markup for the horizontal slider with two thumbs shown in this section. In this example, the type option is set to range , and the value option is set to currentValueArray which is a variable representing a two-number array.

<div id="slider-container">
<label for="slider-id"> ojSlider component for="slider-id"> ojSlider component</label>
<input id="slider-id"
data-bind="ojComponent: {
component: 'ojSlider',
type: 'range',
max:max,
min:min,
step:step,
value:currentValueArray
}"/>
<span> Current Value: </span>
<span> id="curr-value" data-bind="text: currentValueArray()"></span>
</div>

For additional information about adding an Oracle JET component to your page, see Adding an Oracle JET Component to Your Page

Note:
For accessibility, the div container includes a label element that associates the ojSlider component with the label. See the ojSlider API documentation for accessibility details and associated keyboard and touch end user support.

2. Add code to your application script that sets the values for the options you specified in the previous step.

The min, max, step,currentValue, and currentValueArray variables specified for the ojSlider component's options are defined in the application's main script, shown below. The min and max variables represent the start and end values of the slider���s range. The currentValue variable represents the current value of the thumb. The currentValueArray, shown in a comment, represents the initial range for a slider with two thumbs.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'ojs/ojslider'],
function(oj, ko, $)
{
function SliderModel()
{
var self = this;
self.max = ko.observable(200);
self.min = ko.observable(0);
self.currentValue = ko.observable(100);
// self.currentValueArray = ko.observableArray([100, 400]);
self.step = ko.observable(10);
}
var sliderModel = new SliderModel();
$(document).ready(
function()
{
ko.applyBindings(sliderModel, document.getElementById('slider-container'));
}
);
});

The step option indicates the size of the interval the slider takes between the min and max values.

Note:
The full specified value of the range (max - min) should be evenly divisible by step.

Formatting Tips for ojSlider

The ojSlider component provides options that allow you to customize a horizontal slider���s width, change the slider���s orientation to vertical, adjust a vertical slider���s height, change the location of the bar���s coloring, or disable it.

You may find the following tips helpful when working with sliders.

- To change the horizontal slider���s width, enter a style value in the value the ojSlider component���s rootAttributes option. The example below show how you could specify an absolute width of 25 em on the ojSlider used in this section.

<label for="slider-id"> ojSlider component for="slider-id"> ojSlider component</label>
<input id="slider-id"
data-bind="ojComponent: {
component: 'ojSlider',
range: 'fromMin',
max:max,
min:min,
step:step,
value:currentValue,
rootAttributes: {style:'max-width:25em'}}"/>

To specify a width as a percentage of the maximum width available, set the max-width style to a percentage.

rootAttributes: {style:'max-width:100%'}

- To create a vertical slider, set the ojSlider component���s orientation option to vertical.

<label for="slider-id"> ojSlider component for="slider-id"> ojSlider component</label>
<input id="slider-id"
data-bind="ojComponent: {
component: 'ojSlider',
orientation: 'vertical',
... contents ommited
}"/>

- To change the vertical slider���s height, set the style attribute directly on the input element.

<label for="slider-id"> ojSlider component for="slider-id"> ojSlider component</label>
<input id="slider-id" style="height: 150px"
data-bind="ojComponent: {
component: 'ojSlider',
orientation: 'vertical',
... contents ommited
}"/>

- To color the bar from the slider maximum value to the slider thumb, set the component���s range option to fromMax. The ojSlider component���s range option defaults to fromMin, which will color the bar from the minimum value to the slider thumb.

- To remove coloring from the slider bar, set the component���s range option to none.

- For sliders with two thumbs, set the component���s range option to between to color the bar between the thumbs.

- To display a slider that displays a value but does not allow interaction, set the component���s disabled option to true.

Cookbook Examples

The Oracle JET cookbook includes the complete examples shown in this section at Sliders. You can also find examples that show disabled sliders and sliders with icons on the bar to manipulate the thumb.

Working with Text Input Components

The Oracle JET text input components enhance standard HTML input and textarea elements. Enhancements include support for custom validation and conversion, accessibility, internationalization, and more. The Forms page in the Oracle JET Cookbook includes examples for working with the following Oracle JET input components.

Oracle JET Component

Image

HTML5 Element

ojInputDate

input type="text"

ojInputDate enhances the HTML input type="text" element to generate an element that contains an ISO date. The Oracle JET component enhances the text type input element instead of the HTML5 date input type (input type="date") due to lack of universal browser support.

ojInputDateTime

input type="text"

ojInputDateTime enhances the HTML input type="text" element to generate an element that contains an ISO date and time. The Oracle JET component enhances the text type input element instead of the HTML5 datetime input type (input type="datetime") due to lack of universal browser support.

ojInputNumber

input type="text"

ojInputNumber enhances the HTML input type="text" element to generate an element that contains numbers. The Oracle JET component enhances the text type input element instead of the HTML5 number input type (input type="number") due to lack of universal browser support.

ojInputPassword

input type="password"

ojInputText

input type="text"

ojInputTime

input type="text"

ojInputTime enhances the HTML input type="text" element to generate an element that contains an ISO time. The Oracle JET component enhances the text type input element instead of the HTML5 time input type (input type="time") due to lack of universal browser support.

ojTextArea

textarea

The editable input components include converters and validators that you can customize as needed. For additional information, see Validating and Converting Input.

The components also support help and hint messages that you can customize to provide user assistance in your application. For additional information, see Working with User Assistance.

Working with Selection Components

The Oracle JET selection components include the ojCombobox, ojSelect, ojCheckboxset, ojRadioset, and ojSwitch. All components are themable and WAI-ARIA compliant. All components support single selection, and some components support multiple selection, text input, and search filtering.

Topics:

- Working with Comboboxes

- Working with Select

- Working with Checkbox and Radio Sets

- Working with Switches

Working with Comboboxes

The Oracle JET ojCombobox enhances the HTML input and datalist elements to display dropdown lists that are themable and WAI-ARIA compliant. ojCombobox supports single-select, multi-select, free text input, and search filtering.

The image below shows three single-select comboboxes and one multi-select combobox. In this example, the first combobox displays the default dropdown list. The other single-select combo boxes illustrate a disabled item option and items that include images with the item text.

The user can select one of the items from the dropdown list or erase the current value and enter text in the input field to search the list of available options. The user can also enter non-matching text to add a new item. In the example below, the user typed re which matches the Internet Explorer and Firefox list items.

Tip:

You can use the Oracle JET ojSelect component to create read-only dropdown lists. For additional information, see Working with Select.

To create the combobox, you can use the ojComponent binding to create an ojCombobox component on the input DOM node. Add a datalistto your markup which contains the options displayed in the combobox. The code sample below shows the markup for the single-select combobox with all option items enabled.

<form id="form1">
<label for="combobox">Single-select Combobox</label>
<input id="combobox" list="browsers"
data-bind="ojComponent: {component: 'ojCombobox', value: val,
rootAttributes: {style:'max-width:20em'}}"/>
<datalist id="browsers">
<option value="Internet Explorer">Internet Explorer</option>
<option value="Firefox">Firefox</option>
<option value="Chrome">Chrome</option>
<option value="Opera">Opera</option>
<option value="Safari">Safari</option>
</datalist>

The code that defines the val value is defined in the ValueModel() constructor function, shown below.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'ojs/ojselectcombobox'],
function(oj, ko, $)
{
$(document).ready(
function()
{
function ValueModel() {
this.val = ko.observableArray(["Chrome"]);
}
ko.applyBindings(new ValueModel(), document.getElementById('form1'));
}
);
});

Note:

The HTML datalist element is not supported on Internet Explorer (IE) 9. If your application must support IE9, you can create the ojCombobox using an options array instead of the datalist. The options array is an array of objects with value/label properties in string format.

The Oracle JET Cookbook contains complete examples for configuring the single-select and multi-select comboboxes at Comboboxes. You can also find examples for implementing the options array, setting the width, handling events, adding new entries, including images with the list items, and using a Knockout foreach binding to initialize the combobox.

Working with Select

You can use the Oracle JET ojSelect component to display read-only, dropdown lists that are themable and WAI-ARIA compliant. The ojSelect component enhances the HTML select and option elements and supports single and multiple selection with search filtering.

The dropdown list displays when the user does one of the following:

- Clicks on the select box.

- Sets focus on the select box and starts typing or presses the Enter, Arrow Up, or Arrow Down key.

A search box automatically displays with the dropdown list when the number of available list items is greater than the value in the component's minimumResultsForSearch option. The minimumResultsForSearch option's value defaults to 10, and a search box will display automatically whenever the number of list items is greater than 10.

For example, there are five items in the dropdown list shown above so a search box is not displayed by default. However, the user can still display a search box by typing in the search box.

Tip:

You can also use the Oracle JET ojCombobox component to create dropdown lists that support single and multiple selection. The ojCombobox component also supports user input to add items to the dropdown list. For additional information, see Working with Comboboxes.

The code sample below shows the markup used to create the multi-select ojSelect component shown in this section. In this example, the minimumResultsForSearch option's value is 3, and a search box will display automatically. The multiple option is true, and the component will support multiple selection.

<form id="form1">
<label for="multiSelect">Multi Select</label>
<select id="multiSelect"
data-bind="ojComponent: {component: 'ojSelect',
value: val,
multiple: true,
minimumResultsForSearch: 3,
rootAttributes: {style:'max-width:20em'}}">
<option value="IE">Internet Explorer</option>
<option value="FF">Firefox</option>
<option value="CH">Chrome</option>
<option value="OP">Opera</option>
<option value="SA">Safari</option>
</select>
</form>

Note:

For accessibility, ojSelect requires that you set the for attribute on the label element to point to the id of the select element. For additional information about creating accessible Oracle JET components, see Using the Accessibility Features of Oracle JET Components.

The code sample also defines max-width using the rootAttributes style option. Use max-width instead of width to ensure that the component adjusts its width automatically when the display width changes.

The code that defines the val value is defined in the ValueModel() function, shown below. val is defined as a Knockout observable, with its initial values set to Chrome and Safari.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'ojs/ojselectcombobox'],
function(oj, ko, $)
{
$(document).ready(
function()
{
function ValueModel() {
this.val = ko.observableArray(["Chrome","Safari"]);
}
ko.applyBindings(new ValueModel(), document.getElementById('form1'));
}
);
});

The Oracle JET Cookbook contains the complete example for configuring the ojSelect component. You can also find examples that show how to disable the component, group related components in the dropdown list, bind an event handler to the component's optionChange event, and more. For details, see Select.

Working with Checkbox and Radio Sets

The Oracle JET ojCheckboxset component enhances a group of HTML input elements with type=checkbox, and the ojRadioset component enhances a group of input elements with type=radio.

The ojCheckboxset and ojRadioset components manage the selected value of their group and add required validation. In addition, the components manage the styles of the input elements, adding and removing the Oracle JET styles depending upon state.

To create the ojCheckboxset or ojRadioset, add the DOM element that will contain the group of input elements and use the ojComponent binding to create the component. The initial value of the checkbox or radio button is defined in the component's value option. The following code example shows the markup that defines the ojCheckboxset shown in the image above.

<form id="formId">
<label id="mainlabelid">Colors</label>
<!-- You must set the aria-labelledby attribute to make this accessible.
role="group" is set for you by ojCheckboxset. -->
<div id="checkboxSetId" aria-labelledby="mainlabelid"
data-bind="ojComponent: {component: 'ojCheckboxset', value: currentColor}">
<span class="oj-choice-row">
<input id="blueopt" type="checkbox" name="rbb" value="blue">
<label for="blueopt">Blue</label>
</span>
<span class="oj-choice-row">
<input id="greenopt" type="checkbox" name="rbb" value="green">
<label for="greenopt">Green</label>
</span>
<span class="oj-choice-row">
<input id="redopt" type="checkbox" name="rbb" value="red">
<label for="redopt">Red</label>
</span>
<span class="oj-choice-row">
<input id="limeopt" type="checkbox" name="rbb" value="lime">
<label for="limeopt">Lime</label>
</span>
<span class="oj-choice-row">
<input id="aquaopt" type="checkbox" name="rbb" value="aqua">
<label for="aquaopt">Aqua</label>
</span>
</div>
</form>

Note:

For accessibility, the ojCheckboxset and ojRadioset components require that you set the aria-labelledby attribute on the DOM element containing the component. You must also set each input element's id attribute, and refer to that id in the input label's for attribute. For additional information about creating accessible Oracle JET components, see Using the Accessibility Features of Oracle JET Components.

The code that defines the currentColor value is defined in the checkboxsetModel() function, shown below.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'ojs/ojbutton', 'ojs/ojcheckboxset'],
function(oj, ko, $)
{
function checkboxsetModel()
{
var self = this;
self.currentColor = ko.observable(["red"]);
}

var vm = new checkboxsetModel();

$(document).ready(
function()
{
ko.applyBindings(vm, document.getElementById('formId'));
}
);
});

The Oracle JET Cookbook contains complete examples for configuring the ojCheckboxset and ojRadioset components. You can also find examples that show how to disable the component or one of its input elements, display the component inline, and test validation. For details, see and Radio Sets.

Working with Switches

A switch component displays two mutually exclusive choices to a user, typically ON or OFF. The Oracle JET ojSwitch component enhances the HTML input element to provide a switch component that is themable and WAI-ARIA compliant. You can also disable a switch or make it read only using component options and display a switch inline using built-in style classes.

The following image shows an ojSwitch component in on, off, disabled, and read only states. The display changes when the switch has focus to provide a visual clue to the user that the switch is selectable.

To create the ojSwitch component, add the HTML input element to your form or other container element, and use the ojComponent binding to create the component. Use the component's value option to set the initial state to true or false.

The following code sample shows the markup for the ojSwitch shown in this section. For accessibility, the form container includes a label element that associates the ojSwitch component with the label. See the ojSwitch API documentation for accessibility details and associated keyboard and touch end user support.

<form id="formId">
<label id="switchLabel" for="switch">ojSwitch component</label>
<input id="switch" data-bind="ojComponent: {component: 'ojSwitch', value: isChecked}"/><br/>
<span>ojSwitch is </span><span data-bind="text: ((isChecked()) ? 'ON' : 'OFF')"></span>
</form>

The isChecked variable specified for the ojSwitch component's value option is defined in the application's main script, shown below. In this example, the isChecked variable is a boolean set to true by a call to the Knockout observable() function.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'ojs/ojswitch'],
function(oj, ko, $)
{
function SwitchModel(){
this.isChecked = ko.observable(true);
}

var switchModel = new SwitchModel();

$(document).ready(
function()
{
ko.applyBindings(switchModel,
document.getElementById('formId'));
}
);
});

Tip:

You can configure ojSwitch to display inline with its label.

To configure an inline switch, add the oj-label-inline class to the switch's label.

<label id="switchLabel" for="switch" class="oj-label-inline">ojSwitch component</label>

To disable the switch, set the component's disabled option to true. To make the switch read only, set the component���s readOnly option to true.

The Oracle JET cookbook includes the complete example shown in this section at Switches. You can also find examples that implement disabled, read only, and inline switches.

Working with Buttons, Button Sets, and Toolbars

The Oracle JET framework includes the ojButton component that you can use as a standalone component or include in ojButtonset and ojToolbar container components. You can configure ojButton as a push or toggle button, depending upon your application's needs.

Topics:

- Working with Buttons

- Working with Button Sets

- Working with Toolbars

Working with Buttons

Use the Oracle JET ojButton component to display a push or toggle button. Oracle JET buttons are WAI-ARIA compliant and themable, with appropriate styles for hover, active, checked, and disabled.

- Push button: Ordinary button that does not stay pressed when clicked

You can configure push buttons as the HTML button element, anchor (<a>), or input element of type input, submit, or reset. In general, use the button element unless you need the anchor capability. Buttons using the input element are less frequently used since they don't support icons.

<button id= "button"
data-bind="click: buttonClick,
ojComponent: { component: 'ojButton', label: 'A button element' }">
</button>
<a id="anchor" href="#"
data-bind="click: buttonClick,
ojComponent: { component: 'ojButton' }">An anchor</a>

- Toggle button: Button that toggles between a selected state and an unselected state when clicked

You can configure toggle buttons as the HTML input element of type radio or checkbox. The label must be a sibling of the input element and immediately precede it in order to ensure compatibility with Oracle JET's ojComponent binding. Also, the label's for attribute must refer to the input's id attribute.

<label for="standalone">Toggle</label>
<input type="checkbox" id="standalone" data-bind="ojComponent: {component: 'ojButton'}"/>

A given radio button must not be both checked and disabled, unless all radio buttons in the group are disabled, since this removes the entire radio group from the tab order in mainstream browsers. This issue applies to native radios and is not unique to Oracle JET.

The Oracle JET Cookbook at Buttons includes complete examples for all buttons. In addition, the ojButton API documentation describes support for keyboard interaction, accessibility, event handling, pseudo-selectors for jQuery expressions, setting component state, and a comparison of Oracle JET buttons with jQuery UI buttons. In particular, you should make note of the following:

- Register click handlers directly on the button, rather than on an ancestor.

<button id= "button"
data-bind="click: buttonClick,
ojComponent: { component: 'ojButton', label: 'A button element' }">
</button>

If you register the click handler on an ancestor, the click target could be removed if any of the button's DOM is swapped out. For example, if you're alternating the text and icon between Play and Pause, the bubbling will stop if the click target was part of the content that was removed in the swap.

- If you need to set an ojButton component's checked state programmatically, then wrap it in an ojButtonset so that you can use its checked option. It is OK for a button set to contain only one button.

Working with Button Sets

The ojButtonset component is a themable, visual and semantic grouping container for Oracle JET buttons that is also compliant with WAI-ARIA. Use ojButtonset to group related buttons, such as a group of radios or checkboxes.

Create the ojButtonset on a HTML container element, such as the div element. The Oracle JET cookbook at Button Sets contains the complete recipe to create the button set shown above.

Here are some tips for working with button sets:

- A button set that contains radios should contain all radios in the radio group.

- Checkboxes and radio buttons in the button set should specify the value attribute, since the checked option refers to that attribute.

- The application should not do anything to interfere with the focus management. For example, it should not set the tabindex of the buttons.

- Enabled buttons should remain user visible. Otherwise, the arrow-key navigation to the button would cause the focus to seemingly disappear.

- The button set's focusManagement option should be set to none when placing the button set in an ojToolbar component.

- The application is responsible for applying WAI-ARIA aria-label and aria-controls attributes to the button set, as appropriate.

aria-label="Choose only one.  Use left and right arrow keys to navigate."
aria-controls="myTextEditor"

- If the checked option and DOM get out of synch (for example, if a set of buttons contained in a button set changes, possibly due to a Knockout binding), then the application is responsible for updating the checked option.

- The application doesn't need to listen for the optionChange event, since the ojComponent checked binding will update the bound observable whenever the checked state changes.

For additional information about the ojButtonset component's options, events, and methods, see the ojButtonset API documentation.

Working with Toolbars

The ojToolbar component is a WAI-ARIA compliant toolbar, with arrow key navigation and a single tab stop. The tab stop updates on navigation, so that tabbing back into the toolbar returns to the most recently focused button.

The ojToolbar component can contain ojButton and ojButtonset components as well as non-focusable content such as separator icons.

Here are some tips for working with toolbars:

- A toolbar that contains radio buttons should contain all radio buttons in the radio group.

- The application should not do anything to interfere with the focus management.

- Enabled buttons should remain user visible. Otherwise, the arrow-key navigation to the button would cause the focus to seemingly disappear.

- The button set's focusManagement option should be set to none when placed in a toolbar.

The Oracle JET Cookbook includes toolbar examples at Toolbars. For additional information about the ojToolbar component's options, events, and methods, see the ojToolbar API documentation.

Working with Menus

The ojMenu component is a themable, WAI-ARIA compliant menu with mouse and keyboard interactions for navigation. After you create the menu, you can add it as a menu option to an ojButton component to create a menu button, or add it as a context menu to an Oracle JET component or HTML5 element.

Topics:

- Working with ojMenu

- Working with Menu Buttons

- Working with Context Menus

Working with ojMenu

You can create an ojMenu component from any valid markup as long as the elements have a strict parent-child relationship and each menu item has an anchor. Typically, you create the menu from an unordered list, with menu items that contain anchors, which in turn contain the menu item text.

The following code sample shows the markup used to create the basic menu. To handle menu selection, add a select listener.

<ul id="myMenu" style="display:none"
data-bind="ojComponent: {component: 'ojMenu', select: menuItemSelect}">
<li id="zoomin">
<a href="#"><span class="oj-menu-item-icon oj-fwk-icon oj-fwk-icon-arrow-n"></span>Zoom In</a>
</li>
<li id="zoomout">
<a href="#"><span class="oj-menu-item-icon demo-icon-font demo-bookmark-icon-16"></span>Zoom Out</a>
</li>
<li id="divider"></li>
<li id="save">
<a href="#"><span class="oj-menu-item-icon demo-icon-font demo-palette-icon-24"></span>Save</a>
</li>
<li id="print" class="oj-disabled">
<a href="#"><span class="oj-menu-item-icon demo-icon-font demo-chat-icon-24"></span>Print...</a>
</li>
</ul>
<!-- To handle menu item selection, use a select listener as shown above, not a click listener. The markup below displays the selection. -->
<p class="bold">Last selected menu item:
<span id="results" data-bind='text: selectedMenuItem'></span>
</p>

The following script defines the selection listener.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'ojs/ojmenu'],
function(oj, ko, $)
{
function MenuModel() {
var self = this;
self.selectedMenuItem = ko.observable("(None selected yet)");
self.menuItemSelect = function( event, ui ) {
self.selectedMenuItem(ui.item.children("a").text());
};
}
});

For additional information about the ojMenu component's options, events, and methods, see the ojMenu API documentation.

The Oracle JET cookbook includes advanced examples for working with ojMenu, including demos for working with sub-menus and templates. For details, see Menu (Advanced).

Working with Menu Buttons

Menu buttons are ojButton components that display an ojMenu component when the user does one of the following:

- Clicks on the button.

- Sets focus on the button and presses the Enter, Spacebar, or Arrow Down key.

To create the menu button, add the basic ojMenu component as a menu option to an ojButton component configured on button or anchor tags. In the markup, place the ojMenu markup immediately after the ojButton markup.

The following code sample shows the markup for the menu button, with the details for the basic menu omitted.

<div id='menubutton-container'>
<button id="menuButton"
data-bind="ojComponent: {component: 'ojButton', label: 'Actions',
menu: '#myMenu'}">
</button>
<ul id="myMenu" style="display:none"
data-bind="ojComponent: {component: 'ojMenu', select: menuItemSelect}">
<li id="zoomin">
<a href="#"><span class="oj-menu-item-icon oj-fwk-icon oj-fwk-icon-arrow-n"></span>Zoom In</a>
... contents omitted
</ul>
<p>
<p class="bold">Last selected menu item:
<span id="results" data-bind='text: selectedMenuItem'></span>
</p>
</div>

The following code sample shows the code that initializes the menu button.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'ojs/ojbutton', 'ojs/ojmenu'],
function(oj, ko, $)
{

function MenuModel() {
var self = this;
self.selectedMenuItem = ko.observable("(None selected yet)");

self.menuItemSelect = function( event, ui ) {
self.selectedMenuItem(ui.item.children("a").text());
};
}

$(function() {
ko.applyBindings(new MenuModel(), document.getElementById('menubutton-container'));
});

});

The Oracle JET Cookbook includes the complete code sample for the menu button shown in this section. For details, see Menu Buttons.

Working with Context Menus

Context menus are ojMenu components placed on an Oracle JET component or an HTML5 element using the contextmenu attribute. The element on which the context menu binding is placed should be user-focusable, for keyboard accessibility through the Shift+F10 key, since focus is returned to the element when the menu is dismissed.

In this example, the ojMenu component is placed on an ojButton component and the HTML anchor element. The code sample below shows the markup for the ojButton component and the HTML anchor element, with the details for the basic menu omitted.

<div id="button-container">
<h3>A JET component with a context menu:</h3>
<!-- Use the HTML5 contextmenu attribute for JET components -->
<button id= "myButton" contextmenu="myMenu"
data-bind="ojComponent: { component: 'ojButton',
label: 'Right-click me. Shift-F10 me. Press and hold me.' }">
</button>
<h3>An ordinary HTML element with a context menu:</h3>
<!-- Use the ojContextMenu binding for elements that aren't JET components -->
<a href="#" id="myAnchor" contextmenu="myMenu"
data-bind="ojContextMenu: {}">Right-click me. Shift-F10 me. Press and hold me.</a>
</div>
<div id='menu-container'>
<!-- To handle menu item selection, use a select listener as shown,
not a click listener. -->
<ul id="myMenu" style="display:none"
data-bind="ojComponent: {component: 'ojMenu', select: menuItemSelect,
beforeOpen: menuOpen}">
... contents omitted
</ul>
<p>
<p class="bold">Last selected menu item:
<span id="results" data-bind='text: selectedMenuItem'></span>
</p>
</div>

When you add a context menu to an Oracle JET component, you apply the ojComponent binding as shown above. If you add the context menu to an HTML5 element, use the ojContextMenu binding, also shown above.

The following code sample shows the code to initialize the context menu.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'ojs/ojbutton', 'ojs/ojmenu'],
function(oj, ko, $)
{
function MenuModel() {
var self = this;
self.selectedMenuItem = ko.observable("(None selected yet)");
self.menuLauncher= ko.observable("(Not launched yet)");

self.menuItemSelect = function( event, ui ) {
self.selectedMenuItem(ui.item.children("a").text());
};

self.menuOpen = function( event, ui ) {
self.menuLauncher(ui.openOptions.launcher.attr("id"));
};
}

$(function() {
ko.applyBindings(new MenuModel(), document.getElementById('button-container'));
});

The Oracle JET cookbook contains the complete example, including the CSS for the menu icons, at: Context Menus.

Working with Data Collections

The Oracle JET data collection components include ojTable, ojDataGrid, ojTree, and ojListView, and you can use them to display records of data. ojTable and ojDataGrid both display data in rows and columns, and your choice of component depends upon your use case. Use ojTree to display hierarchical data such as a directory structure and ojListView to display a list of data. The framework also includes pagination and row expanders that display hierarchical data in a data grid or table row.

Topics:

- Choosing a Table or Data Grid

- Working with Tables

- Working with Data Grids

- Working with Trees

- Working with List Views

- Working with Row Expanders

- Working with Pagination

Choosing a Table or Data Grid

Oracle JET provides both the ojTable and ojDataGrid components for displaying records of data in rows and columns, and this section can help you decide which component to use in your application.

The ojTable component displays records of data in a per row basis. It's best used when you have simple data that can be presented as rows of fields, and it should be your first choice unless you require advanced features. A selection in the table provides you with the row of data and all of the fields in that row or record. The sizing of the table is based on the content itself. The height and width of the cells is adjusted for the content included. ojTable is based on the HTML table element. You can write templates using table elements such as tr, td, th, and so on.

The ojDataGrid is designed to provide grid functionality. It provides the ability to select individual or ranges of cells of data. It's best used when you need to display totals or tallies of data across columns or rows of data. The ojDataGrid is designed to be much more flexible in its layout and functionality than the ojTable component. It's a low level component that you can shape in your application to how you want the data to be displayed. The overall size of the data grid is not determined by its content, and the developer specifies the exact height and width of the container. The data grid acts as a viewport to the contents, and its size doesn't affect the size of the columns and rows like a table does. ojDataGrid is based on the HTML div element, and you can host the template content inside a div DOM structure.

The table below provides a feature comparison of the ojTable and ojDataGrid components.

Feature

ojTable

ojDataGrid

Column/Row sizing

Controlled by content or CSS styles. Percent values supported for width and height.

Controlled by cell dimensions. Does not support percent values for width and height.

User can resize column/row

No

Yes

Row reordering

No

Yes

Column sorting

Yes

Yes

Column/Row selection

Yes

Yes

Cell selection

No

Yes

Marquee selection

No

Yes

Row header support

No

Yes

Pagination

Page, high water mark

Page, high water mark, virtual scrolling (see note)

Custom cell templates

Yes

Yes

Custom row templates

Yes

No

Custom cell renderers

Yes

Yes

Custom row renderers

Yes

No

Row expander support

Yes

Yes

Cell stamping

Yes

Yes

Render aggregated cubic data

No

Yes

Base HTML element

table

div

Custom footer template

Yes (provides access to column data for passing to a JavaScript function)

No (cell level renderers used for column and row data manipulations)

Note:

True virtual scrolling is available as a feature of ojDataGrid. Modern design principles should be considered and implemented before implementing virtual scrolling. It is much more desirable to present the end user with a filtered list of data that will be more useful to them, than to display thousands of rows of data and expect them to scroll through it all. True virtual scrolling means that you can perform scrolling in both horizontal and vertical directions with data being added and removed from the underlying DOM. High water mark scrolling (with lazy loading) is the preferred method of scrolling, and you should use it as a first approach.

Working with Tables

The Oracle JET ojTable component enhances the HTML table element to provide support for accessibility, custom cell and row templates and renderers, theming, row expansion, and pagination.

You can define the table's data in an array using the oj.ArrayTableDataSource object or in a Collection using the oj.CollectionTableDataSource object. The code sample below shows the markup for the ojTable component shown in this example.

<table id="table" summary="Department List" data-bind="ojComponent: {component: 'ojTable', data: datasource, columnsDefault: {sortable: 'none'}, columns:
[{headerText: 'Department Id', field: 'DepartmentId'},
{headerText: 'Department Name', field: 'DepartmentName'},
{headerText: 'Location Id', field: 'LocationId'},
{headerText: 'Manager Id', field: 'ManagerId'}]}">
</table>

Note:

The summary attribute on the table element describes the purpose of the table and is an accessibility requirement. Alternatively, you can add the caption child tag to the table element. See the ojTable API documentation for details about accessibility and supported keystrokes and gestures.

The script that defines the datasource object and completes the component binding is shown below. For the sake of brevity, some table data is omitted.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'promise', 'ojs/ojtable'],
function(oj, ko, $)
{
function viewModel()
{
var self = this;

var deptArray = [{DepartmentId: 1001, DepartmentName: 'ADFPM 1001 neverending', LocationId: 200, ManagerId: 300},
{DepartmentId: 556, DepartmentName: 'BB', LocationId: 200, ManagerId: 300},
{DepartmentId: 10, DepartmentName: 'Administration', LocationId: 200, ManagerId: 300},
{DepartmentId: 20, DepartmentName: 'Marketing', LocationId: 200, ManagerId: 300},
... contents omitted
{DepartmentId: 130, DepartmentName: 'Human Resources15', LocationId: 200, ManagerId: 300}];
self.datasource = new oj.ArrayTableDataSource(deptArray, {idAttribute: 'DepartmentId'});
}
var vm = new viewModel;

$(document).ready
(
function()
{
ko.applyBindings(vm, document.getElementById('table'));
}
);
});

The Tables demos in the Oracle JET Cookbook include the complete example for this table and a link to the ojTable API documentation. The cookbook also includes an example that creates the ojTable component using data defined in an oj.CollectionTableDataSource object and examples that show tables with custom row and cell templates, selection, sorting, scrolling, and custom cell renderers.

Understanding ojTable and Sorting

ojTable enables single column sorting by default if the underlying data supports sorting. Using the sortable attribute of the ojTable component's columnDefaults option, you can control sorting for the entire table, or you can use the sortable attribute of the columns option to control sorting on specific columns.

When you configure a column for sorting, the column header displays arrow indicators to indicate that the column is sortable when the user hovers over the column header. In the following image, the Department ID is sortable, and the sort indicator is showing an up arrow to indicate that the sort is currently ascending. The user can select the up arrow to change the sort to descending.

The sortable attribute supports the following options:

- auto: Sort the table or indicated column if the underlying data supports sorting.

- none: Disable sorting on the table or indicated column.

- enabled: Enable sorting on the entire table or indicated column.

To enable sorting on specific columns:

- Set the sortable attribute to none on the table's columnDefaults option to remove the auto default behavior.

- Set the sortable attribute to enabled on the columns that you want to sort.

The following code sample shows the markup to create the department table shown in this section. In this example, the table is configured to enable sorting on only the Department Id column.

<table id="table" summary="Department List" data-bind="ojComponent: {component: 'ojTable', data: datasource, columnsDefault: {sortable: 'none'}, columns:
[{headerText: 'Department Id', field: 'DepartmentId', sortable: 'enabled'},
{headerText: 'Department Name', field: 'DepartmentName'},
{headerText: 'Location Id', field: 'LocationId'},
{headerText: 'Manager Id', field: 'ManagerId'}]}">
</table>

Note:

The ojTable component supports single column sorting only, and the behavior for secondary columns is browser-dependent.

For additional information about ojTable and sorting options, see the ojTable API documentation.

For examples in the Oracle JET Cookbook that implement table sorting, see Tables.

Working with Data Grids

The ojDataGrid component displays data in cells inside a grid consisting of rows and columns. ojDataGrid is themable and supports WAI-ARIA authoring practices for accessibility. You can configure the ojDataGrid for cell selection with row and column headers or for row selection with column headers.

Note:

When you configure the data grid for row selection, the grid has a look and feel that is similar to the ojTable component. However, there are distinct differences in functionality between the ojDataGrid and ojTable components. For additional information, see Choosing a Table or Data Grid.

To create the ojDataGrid, add the HTML div element to your markup and define the ojDataGrid component on that element. Assign an id to the div and optional styling for width and height.

<div id="datagrid" style="width:202px;height:110px"
aria-label="Data Grid Cell Based Grid Demo"
data-bind="ojComponent: {component: 'ojDataGrid', data: dataSource}">
</div>

In this example, the aria-label is added to the div element for accessibility. ojDataGrid implicitly defines an Aria role as application, and you must add the aria-label to distinguish it from other elements defined with the Aria application role. For additional information about Oracle JET and accessibility, see Developing Accessible Applications.

The data is defined in the dataSource object and can be one of the following:

- oj.ArrayDataGridDataSource: Use to define data in a static array.
The array can be a single array where each item in the array represents a row in the data grid, or a two dimensional array where each item represents a cell in the grid. For the data grid shown in this section, the data is defined as a two dimensional array.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'ojs/ojdatagrid'],
function(oj, ko, $)
{
$(document).ready(
function()
{
ko.applyBindings({dataSource: new oj.ArrayDataGridDataSource({
['X', 'O', 'X'},
['O', 'X', 'O'},
['X', 'O', 'X'}
])}, document.getElementById('datagrid'));
}
);
});

- oj.CollectionDataGridDataSource: Use to define data using the Oracle JET Common Model. The data grid will respond to events generated by the underlying oj.Collection.
For more details aboutoj.CollectionDataGridDataSource , see the oj.CollectionDataGridDataSource API documentation.

- oj.PagingDataGridDataSource: Use to include pagination. For additional information, see Working with Pagination.

- oj.FlattenedTreeDataGridDataSource: Use to display hierarchical data in the data grid. The user can expand and collapse rows in the data grid. For additional information, see Working with Row Expanders.

- oj.CubeDataGridDataSource: Use to include aggregate values on column headers, row headers, or both. For additional information, see Working with oj. CubeDataGridDataSource.

- Custom data source: Use to provide your own data source for the data grid. The Oracle JET Cookbook contains examples for creating custom data sources, including an example with nested headers.

The Oracle JET Cookbook includes the complete example for the data grid used in this section and a link to the ojDataGrid component's API documentation at Data Grids. The cookbook also includes examples that show row-based data grids and data grids with pie charts, gauges, and custom cell renderer and data sources.

Working with oj. CubeDataGridDataSource

You can use oj.CubeDataGridDataSource to render aggregated cubic data in your data grid. You can aggregate values on column headers, row headers, or both column and row headers.

For example, you may have a collection that contains data for sales, number of units sold, and sales tax data for vehicles sold by car dealerships, and you'd like to aggregate the data to show sales, unit, and tax data by year and city. Your data also contains the type of vehicle sold, its color, and type of drive train, and you'd also like to aggregate the data to show the sales, unit, and tax data grouped by product, color, and drive train.

You can configure a ojDataGrid with the oj.CubeDataGridDataSource to achieve the desired grouping. The following image shows the runtime display.

The data grid uses JSON data for its data source. The code sample below shows a portion of the JSON array.

[
{
"index": 0,
"units": 80,
"sales": 535,
"tax": 0.0234,
"year": "2014",
"gender": "Male",
"product": "Coupe",
"city": "New York",
"drivetrain": "FWD",
"color": "White"
},
{
"index": 1,
"units": 95,
"sales": 610,
"tax": 0.0721,
"year": "2015",
"gender": "Male",
"product": "Coupe",
"city": "New York",
"drivetrain": "FWD",
"color": "White"
},
{
"index": 2,
"units": 27,
"sales": 354,
"tax": 0.0988,
"year": "2014",
"gender": "Female",
"product": "Coupe",
"city": "New York",
"drivetrain": "FWD",
"color": "White"
},

]

The data also contains a column for the gender of the buyer which isn't included in the display. The totals displayed in the grid come from applying the aggregation across any JSON rows that match up on type, color, drivetrain, year, and city. For the data in this example, this has the effect of grouping the Male and Female values and applying the aggregation. For example, the units shown in the grid for the New York sales in 2014 of white FWD coupes comes from totaling the highlighted values:

80 + 27 = 107 units

The following code sample shows the markup for the data grid.

<div id="datagrid"
style="width:100%;height:400px;max-width:851px;"
aria-label="Cubic Data Source Grid Demo"
data-bind="ojComponent: {component: 'ojDataGrid',
data: dataSource}">
</div>

In this example, the datasource is defined in the application's main script.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'ojs/ojmodel',
'promise', 'ojs/ojcube', 'ojs/ojdatagrid'],
function(oj, ko, $)
{
function generateCube(dataArr, axes) {
return new oj.DataValueAttributeCube(dataArr, axes,
[{attribute:'units',aggregation:oj.CubeAggType['SUM']},
{attribute:'sales'},
{attribute:'tax',aggregation:oj.CubeAggType['AVERAGE']}]);
};

function dataGridModel(collection) {
var vm = this;

var dataArr = collection.map(function(model) {
return model.attributes;
});
var axes = [
{axis: 0, levels: [
{attribute: 'city'},
{attribute: 'year'},
{dataValue: true}]},
{axis: 1, levels: [
{attribute: 'product'},
{attribute: 'color'},
{attribute: 'drivetrain'}]}];

this.dataSource = new oj.CubeDataGridDataSource(
generateCube(dataArr, axes));

};

var collection = new oj.Collection(null, {
url: 'cookbook/dataCollections/dataGrid/cubeGrid/cubedata.json'
});

collection.fetch({success:function() {
ko.applyBindings(new dataGridModel(collection),
document.getElementById('datagrid'));
}});
});

The oj.CubeDataGridDataSource parameter is instantiated with the return value of the generateCube() function, which is an oj.Cube object. The oj.Cube class provides functions for the oj.DataValueAttributeCube class which creates the object to convert the row set data into grouped, cubic data. The oj.DataValueAttributeCube constructor takes the following parameters:

- rowset: An array of objects containing name-value pairs
In this example, the JSON data is mapped to the dataArr object which is defined as an oj.Collection object.

var dataArr = collection.map(function(model) {
return model.attributes;
});
var collection = new oj.Collection(null, {
url: 'cookbook/dataCollections/dataGrid/cubeGrid/cubedata.json'
});

- layout: An array of objects that contains the axis number and levels to use for the aggregation
The axis number indicates where you want the aggregated data displayed: 0 for column headers, and 1 for row headers. The levels tell the cube which values to aggregate and the order to display them. The code sample below shows the layout used in this example. The dataValue property indicates which level to display for the units, sales, and tax aggregated values.

var axes = [
{axis: 0, levels: [
{attribute: 'city'},
{attribute: 'year'},
{dataValue: true}]},
{axis: 1, levels: [
{attribute: 'product'},
{attribute: 'color'},
{attribute: 'drivetrain'}]}];

- dataValues: An array of objects that contains the name of the attribute in the row set that represents the data, an optional label, and the aggregation type. The aggregation type is also optional and defaults to SUM. You can also set it to one of the aggregation types shown in the following table.

Aggregation Type

Description

AVERAGE

Average the values.

COUNT

Count the number of values.

CUSTOM

Specify a custom callback function to do the aggregation

FIRST

Substitute the first value encountered in the collection.

MAX

Calculate the maximum of the values.

MIN

Calculate the minimum of the values

NONE

Substitute a null for the value

STDDEV

Calculate the standard deviation of the values.

SUM

Total the values.

VARIANCE

Calculate the variance of the values

The code sample below shows the function that defines the dataValues for the cube used in this section. The cube will sum the units and sales data and will average the sales tax data.

function generateCube(dataArr, axes) {
return new oj.DataValueAttributeCube(dataArr, axes,
[{attribute:'units',aggregation:oj.CubeAggType['SUM']},
{attribute:'sales'},
{attribute:'tax',aggregation:oj.CubeAggType['AVERAGE']}]);
};

The Oracle JET Cookbook demos at Data Grids (Cubic Data Source) contain the complete code for the example used in this section. They also contain the link to the oj.CubeDataGridDataSource API documentation which contains additional detail and methods that you can use for working with the cube.

Working with Trees

The ojTree component displays hierarchical data, such as hierarchical directory structures or categorical data. Each element in the tree is called a node, and the top levels of the hierarchy are referred to as the root nodes. The descendents of the root nodes are its children, and each child node can also contain children. Users select a node to display its children.

In this example, the Links node is a root node, and the Oracle, IBM, and Microsoft nodes are its children. The Microsoft child node contains the USA, Europe, and Asia children.

To create the ojTree, add the HTML div element to your markup and define the ojTree component on that element. Assign an id to the div and optional styling for width and height.

<div id="tree" style="float:left;width: 180px;height: auto;"
data-bind="ojComponent:
{
component: 'ojTree',
selectionMode: 'multiple',
data:{data: getJson},
dnd: {reorder : 'enable'}
}">
</div>

To define the data for the tree, you can use standard HTML list elements (ul, li) or provide the data in JSON format. In this example, the tree uses JSON data which is defined in the getJson() function, shown below. The sample code also shows the Knockout applyBindings() call to complete the component binding.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'ojs/ojtree'],
function(oj, ko, $)
{
$(document).ready(
function()
{
ko.applyBindings(null, document.getElementById('tree'));
}
);
});

function getJson(node, fn) // get local json
{
var data = [
{
"title": "Home",
"attr": {"id": "home"}
},
{
"title": "News",
"attr": {"id": "news"}
},
{
"title": "Blogs",
"attr": {"id": "blogs"},
"children": [ { "title": "Today",
"attr": {"id": "today"}
},
{ "title": "Yesterday",
"attr": {"id": "yesterday"}
},
{ "title": "2 Days Back",
"attr": {"id": "2daysback"}
},
{ "title": "Archive",
"attr": {"id": "archive"}
}
]
},
... contents omitted
];
fn(nodeData) ;  // pass to ojTree using supplied function
};

The Oracle JET Cookbook contains the complete recipe and code for the sample used in this section at Trees. The cookbook also includes a link to the ojTree API documentation and examples for creating a tree using the HTML list elements, lazy loading a tree for performance, adding and removing nodes dynamically, customizing the node icons, displaying a context menu, and creating a tree using JSON data defined in a JsonTreeDataSource object.

Working with List Views

The Oracle JET ojListView component enhances the HTML list (ul) element to provide a themable, WAI-ARIA compliant component that displays a list of data. ojListView supports single and multiple selection, high water mark scrolling when working with table data, and hierarchical content.

Understanding Data Requirements for List Views

The data source for the ojListView component can be one of the following:

- Flat or hierarchical static HTML
The following image shows examples of list views that display static content, one with flat content and one using a nested list for hierarchical content.

The following code sample shows a portion of the markup used to create the ojListView component with hierarchical static content and the Oracle JET component binding. The component allows multiple selection and expands both list item groups A and B upon initial display.

<ul id="listview"
data-bind="ojComponent: {component: 'ojListView',
selectionMode: 'multiple',
expanded: ['a', 'b']}">
<li id="a">
<span>A</span>
<ul>
<li id="amybartlet">
<span class="avatar" style="background-image: url('images/Amy.png')"></span>
<div class="container">
<div>
<span class="name">Amy Bartlet</span>
</div>
<div>
<span class="title">Vice President</span>
</div>
</div>
</li>
... contents omitted
</ul>
</li>
<li id="b">
<span>B</span>
<ul>
... contents omitted
</ul>
</li>
</ul>

Tip:

ojListView uses the children of the root ul element for its content. If you have an existing HTML list in your application, you can add the ojComponent binding as shown above and take advantage of ojListView features.

The code to apply the binding is shown below.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'promise', 'ojs/ojlistview'],
function(oj, ko, $)
{
$(document).ready(
function()
{
ko.applyBindings(null, document.getElementById('listview'));
}
);
});

- Oracle JET TreeDataSource, including oj.JsonTreeDataSource and oj.CollectionTreeDataSource.
Typically, you use one of the Oracle JET TreeDataSource components when your list data contains groups. To use a TreeDataSource, you specify the method that returns the tree data in the data option for the component.

data-bind="ojComponent: {component: 'ojListView', data: datasource,
selectionMode: 'multiple',
expanded: ['a', 'b']}">

The Oracle JET Cookbook contains the complete example for creating a list view with an oj.JsonTreeDataSource at List View Using Hierarchical JSON Data.

- Oracle JET TableDataSource, including oj.ArrayTableDataSource, oj.CollectionTableDataSource, and oj.PagingTableDataSource
Use the TableDataSource data option when you have flat data or want to add scrolling or pagination to your ojListView. The following image shows a list view using an oj.CollectionTableDataSource object for its data.

In this example, high water mark scrolling is enabled through the component's root attributes scrollPolicy.

data-bind="ojComponent: {component: 'ojListView', data: dataSource,
selectionMode: 'single',
rootAttributes: {style: 'width:100%;height:300px;overflow:auto'},
scrollPolicy: 'loadMoreOnScroll'}">

Note:

If you do not specify a data source in the list view component's data option, Oracle JET will examine the child elements inside the root element and use it for static content. If the root element has no children, Oracle JET will render an empty list.

See the Oracle JET Collection at List View Using oj.Collection for the complete example, including the script that creates the oj.CollectionTableDataSource object.

Working with List Views and Knockout Templates

You can use a Knockout template to contain the markup for your list item content and reference the name of the template in the ojListView component's item option.

The code sample below shows a portion of the markup and template for a list view using an oj.ArrayTableDataSource object for its data. In this example, the template is named server_template.

<ul id="listview"
data-bind="ojComponent: {component: 'ojListView', data: dataSource, item: {template: 'server_template'}, selectionMode: 'single'}">
</ul>

<script type="text/html" id="server_template">
<li data-bind="attr: {id: $data.get('name')}">
<div class="oj-row">
<div class="oj-lg-1 oj-col">
<img data-bind="attr: {src: 'images/listView/'+$data.get('name')+'.png',
alt: $data.get('name')}"></img>
</div>
<div class="oj-lg-11 oj-col">
<div class="oj-row row">
<div class="oj-lg-4 oj-col">
<span class="header" data-bind="text: 'MyWebLogic '+$data.get('name')"></span>
</div>
</div>
... content omitted
</div>
</div>
</li>
</script>

The template uses the Oracle JET responsive grid classes to change the display from one column for smaller displays to multiple columns for larger displays.

You can find the complete code sample for this list view at: List Views.

For additional information about the Oracle JET responsive grid, see Designing Responsive Applications. For additional information about working with Knockout templates, see Using Knockout.js Templates and the ojModule Binding.

Working with Row Expanders

Use the Oracle JET ojRowExpander component to expand or collapse rows in a data grid or table to display hierarchical data. ojRowExpander renders the expand/collapse icon with the appropriate indentation and works directly with the flattened data source. In the following image, the row expander is used with an ojTable component, and the user can expand the tasks to display subtasks and dates.

To use ojRowExpander with ojTable, add the ojRowExpander component to the HTML markup, and specify the table's data in an oj.FlattenedTreeTableDataSource object. In the code sample below, the ojRowExpander is defined in the table's row template. The context option references the object obtained from the table's column renderer.

<table id="table" summary="Task List"
data-bind="ojComponent: {component: 'ojTable', data: datasource, rowTemplate: 'row_template', columns:
[{headerText: 'Task Name', sortProperty: 'name'},
{headerText: 'Resource', sortProperty: 'resource'},
{headerText: 'Start Date', sortProperty: 'start'},
{headerText: 'End Date', sortProperty: 'end'}]}">
</table>

<script type="text/html" id="row_template">
<tr>
<td>
<div data-bind="ojComponent: {component: 'ojRowExpander', context: $rowContext}"></div>
<span data-bind="text: name"></span>
</td>
<td>
<span data-bind="text: resource"></span>
</td>
<td>
<span data-bind="text: start"></span>
</td>
<td>
<span data-bind="text: end"></span>
</td>
</tr>
</script>

The data for the oj.FlattenedTreeTableDataSource object can come from local or fetched JSON, or an oj.Collection object. In the example in this section, the data is read from a JSON file. The code sample below shows a portion of the JSON.

[
{"attr": {"id": "t1",
"name": "Task 1",
"resource": "Larry",
"start": "1/1/2014",
"end": "10/1/2014"
},
"children": [
{"attr": {"id": "t1:1",
"name": "Task 1-1",
"resource": "Larry",
"start": "1/1/2014",
"end": "3/1/2014"
},
"children": [
{"attr": {"id": "t1:1:1",
"name": "Task 1-1-1",
"resource": "Larry",
"start": "1/1/2014",
"end": "2/1/2014"
}
},
{"attr": {"id": "t1:1:2",
"name": "Task 1-1-2",
"resource": "Larry",
"start": "2/1/2014",
"end": "3/1/2014"
}
}
]
},
... contents omitted
]
},
... contents omitted
{"attr": {"id": "t4",
"name": "Task 4",
"resource": "Larry",
"start": "11/1/2014",
"end": "12/1/2014"
}
}
]

The script that reads the JSON file and defines the datasource object as an oj.FlattenedTreeTableDataSource is shown below.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'ojs/ojtable', 'ojs/ojrowexpander'],
function(oj, ko, $)
{
$(document).ready(
function()
{
$.getJSON("cookbook/dataCollections/rowExpander/tableRowExpander/projectData.json",
function(data)
{
var options = [];
var datasource =
new oj.FlattenedTreeTableDataSource(new oj.FlattenedTreeDataSource(new oj.JsonTreeDataSource(data), options));
ko.applyBindings({datasource:datasource}, document.getElementById('table'));
});
}
);
});

To use the row expander with ojDataGrid, add the ojRowExpander component to the HTML markup, and specify the data grid's data in an oj.FlattenedTreeDataGridDataSource object. The Oracle JET Cookbook at Row Expanders contains an example that uses the row expander with ojDataGrid. The cookbook also contains the complete code for the example in this section and a link to the API documentation for ojRowExpander. In addition, you can find examples that use an oj.Collection object for the table's data and initialize the row expander with one or more rows expanded.

For additional information about working with the ojTable component, see Working with Tables. For more information about working with the ojDataGrid component, see Working with Data Grids.

Working with Pagination

Use the ojPagingControl component to add pagination to the ojTable and ojDataGrid components or the HTML list element. Pagination displays the number of pages and rows in the table or grid, and the user can use pagination to move between pages, jump to a specific page, or navigate to the first or last page of data.

In the following image, ojPagingControl is added to the ojTable component and initialized with the default display.

To add pagination to a table, define the table's data as a PagingTableDataSource object, and add the ojPagingControl component using the same PagingTableDataSource object for its data option. Specify the number of rows to display in the ojPagingControl component's pageSize option. The code sample below shows the markup defining the table and pagination components. In this example, pageSize is set to 10.

<div id="pagingControlDemo" style="width: 500px;">
<table id="table" summary="Department List"
data-bind="ojComponent: {component: 'ojTable', data: pagingDatasource, columns:
[{headerText: 'Department Id', field: 'DepartmentId'},
{headerText: 'Department Name', field: 'DepartmentName'},
{headerText: 'Location Id', field: 'LocationId'},
{headerText: 'Manager Id', field: 'ManagerId'}],
rootAttributes: {'style':'width: 100%;'}}">
</table>
<div class="oj-table-panel-bottom">
<div id="paging" data-bind="ojComponent: {component: 'ojPagingControl', data: pagingDatasource, pageSize: 10}">
</div>
</div>
</div>

The script that populates the pagingDatasource with data and completes the Knockout binding is shown below. In this example, the table's data is defined in an ArrayTableDataSource object, and the pagingDatasource defines the PagingTableDataSource as a new ArrayTableDataSource object.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'ojs/ojtable', 'ojs/ojpagingcontrol'],
function(oj, ko, $)
{
function viewModel()
{
var self = this;
var deptArray = [{DepartmentId: 10015, DepartmentName: 'ADFPM 1001 neverending', LocationId: 200, ManagerId: 300},
{DepartmentId: 556, DepartmentName: 'BB', LocationId: 200, ManagerId: 300},
{DepartmentId: 10, DepartmentName: 'Administration', LocationId: 200, ManagerId: 300},
{DepartmentId: 20, DepartmentName: 'Marketing', LocationId: 200, ManagerId: 300},
... contents omitted
{DepartmentId: 13022, DepartmentName: 'Human Resources15', LocationId: 200, ManagerId: 300}];
self.pagingDatasource = new oj.PagingTableDataSource(new oj.ArrayTableDataSource(deptArray, {idAttribute: 'DepartmentId'}));
}
var vm = new viewModel;

$(document).ready
(
function()
{
ko.applyBindings(vm, document.getElementById('pagingControlDemo'));
}
);
});

To add a paging control to ojDataGrid, define the data grid's data as a oj.PagingDataGridDataSource object, and add the ojPagingControl component using the same oj.PagingDataGridDataSource object for its data option. Set the pageSize option equal to the fetch size for the data collection, if creating the data grid from an oj.CollectionDataGridDataSource object.

The Oracle JET Cookbook contains complete examples for adding pagination to ojTable, ojDataGrid, and HTML lists at Pagination. You can also find the link to the ojPagingControl API documentation as well as examples that show different options for customizing the paging display.

For additional information about working with the ojTable component, see Working with Tables. For more information about working with the ojDataGrid component, see Working with Data Grids.

Working with Data Visualizations

The Oracle JET data visualization components include customizable charts, gauges, and other components that you can use to present flat or hierarchical data in a graphical display for data analysis.

Topics:

- Choosing a Data Visualization Component for Your Application

- Using Attribute Groups With Data Visualization Components

Choosing a Data Visualization Component for Your Application

The table describes the Oracle JET data visualization components available for use in your application, along with usage suggestions.

Data Visualization Component

Image

Description

Usage Suggestions

Charts:

Area

Displays series of data whose values are represented by filled-in areas. Areas can be stacked or unstacked. The axis is often labeled with time periods such as months.

Use to show cumulative trends over time, such as sales for the last 12 months.

Area charts require at least two groups of data along an axis.

If you are working with multiple series and want to display unstacked data, use line or line with area charts to prevent values from being obscured.

Bar

Displays data as a series of rectangular bars whose lengths are proportional to the data values. Bars display vertically or horizontal and can be stacked or unstacked.

Use to compare values across products or categories, or to view aggregated data broken out by a time period.

Bubble

Displays three measures using data markers plotted on a two-dimensional plane. The location of the markers represents the first and second measures, and the size of the data markers represents the proportional values of the third measure.

Use to show correlations among three types of values, especially when you have a number of data items and you want to see the general relationships.

For example, use a bubble chart to plot salaries (x-axis), years of experience (y-axis), and productivity (size of bubble) for your work force. Such a chart enables you to examine productivity relative to salary and experience.

Combination

Displays series of data whose values are represented by a combination of bars, lines, or filled-in areas.

Use to display team average rating along with individual team member ratings on a yearly basis.

Funnel

Visually represents data related to steps in a process as a three-dimensional chart that represents target and actual values, and levels by color. The steps appear as vertical slices across a horizontal cone-shaped section. As the actual value for a given step or slice approaches the quota for that slice, the slice fills.

Use to watch a process where the different sections of the funnel represent different stages in the process, such as a sales cycle.

The funnel chart requires actual values and target values against a stage value, which might be time.

Line

Displays series of data whose values are represented by lines.

Use to compare items over the same time.

Charts require data for at least two points for each member in a group. For example, a line chart over months requires at least two months. Typically a line of a specific color is associated with each group of data such as the Americas, Europe, and Asia.

Lines should not be stacked which can obscure data. To display stacked data, use area or line with area charts.

Line with Area

Displays series of data whose values are represented as lines with filled-in areas.

Pie

Represents a set of data items as proportions of a total. The data items are displayed as sections of a circle causing the circle to look like a sliced pie.

Use to show relationship of parts to a whole such as how much revenue comes from each product line.

Consider treemaps or sunbursts if you are working with hierarchical data or you want your visual to display two dimensions of data.

Polar

Displays series of data on a polar coordinate system. The polar coordinate system can be used for bar, line, area, combination, scatter, and bubble charts. Polygonal grid shape (commonly known as radar) is supported for polar line and area charts.

Use to display data with a cyclical x-axis, such as weather patterns over months of the year, or for data where the categories in the x-axis have no natural ordering, such as performance appraisal categories.

Range

Displays a series of data whose values are represented either as an area or bar proportional to the data values.

Use to display a range of temperatures for each day of a month for a city.

Scatter

Displays two measures using data markers plotted on a two-dimensional plane.

Use to show correlation between two different kinds of data values, such as sales and costs for top products. Scatter charts are especially useful when you want to see general relationships among a number of items.

Spark

Display trends or variations as a line, bar, floating bar, or area. Spark charts are simple and condensed.

Use to provide additional context to a data-dense display. Sparkcharts are often displayed in a table, dashboard, or inline with text.

Stock

Display stock prices and, optionally, the volume of trading for one or more stocks. When any stock or candlestick chart includes the volume of trading, the volume appears as bars in the lower part of the chart.

Gauges:

Dial

Displays a metric value plotted on a circular axis in relation to the minimum and maximum possible values for the metric. An indicator points to the dial gauge's metric value on the axis

The circular status meter is usually a better choice because of its more modern look and feel and efficient use of space.

LED

Graphically depicts a measurement, such as a key performance indicator (KPI). Several styles of shapes are available, including round or rectangular shapes that use color to indicate status, and triangles or arrows that point up, left, right, or down in addition to the color indicator.

Rating

Displays and optionally accepts input for a metric value.

Use to show ratings for products or services, such as the star rating for a movie.

Status Meter

Displays a metric value on a horizontal, vertical, or circular axis. An inner rectangle shows the current level of a measurement against the ranges marked on an outer rectangle. Optionally, status meters can display colors to indicate where the metric value falls within predefined thresholds.

Others:

Diagram

Models, represents, and visualizes information using a shape called a node to represent data, and links to represent relationships between nodes.

Use to highlight both the data objects and the relationships between them.

Legend

Displays a panel which provides an explanation of the display data in symbol and label pairs.

Consider using the legend component when multiple visualizations on the same page are sharing a coloring scheme.

NBox

Displays data items across two dimensions. Each dimension can be split into multiple ranges, whose intersections result in distinct cells representing data items.

Use to visualize and compare data across a two-dimensional grid, represented visually by rows and columns.

Sunburst

Displays quantitative hierarchical data across two dimensions, represented visually by size and color. Uses nodes to reference the data in the hierarchy. Nodes in a radial layout, with the top of the hierarchy at the center and deeper levels farther away from the center.

Use for identifying trends for large hierarchical data sets, where the proportional size of the nodes represents their importance compared to the whole. Color can also be used to represent an additional dimension of information.

Use sunbursts to display the metrics for all levels in the hierarchy.

Tag Cloud

Displays textual data where font style and size emphasizes the importance of each data item.

Use for quickly identifying the most prominent terms to determine their relative importance.

Thematic Map

Displays data that is associated with a geographic location.

Use to show trends or patterns in data with a spatial element to it.

Timeline

Displays a set of events in chronological order and offers rich support for graphical data rendering, scale manipulation, zooming, resizing, and objects grouping.

Use to display time specific events in chronological order.

Treemap

Displays quantitative hierarchical data across two dimensions, represented visually by size and color. Uses nodes to reference the data in the hierarchy. Nodes are displayed as a set of nested rectangles.

Use for identifying trends for large hierarchical data sets, where the proportional size of the nodes represents their importance compared to the whole. Color can also be used to represent an additional dimension of information

Use treemaps if you are primarily interested in displaying two metrics of data using size and color at a single layer of the hierarchy.

For examples that implement data visualization component, see the Oracle JET Cookbook at Data Visualizations.

Note:

To use an Oracle JET data visualization component, you must configure your application to use RequireJS. For details about adding RequireJS to your application, see Using RequireJS to Manage Library, Link, and Script References.

Using Attribute Groups With Data Visualization Components

Attribute groups allow you to provide stylistic values for color and shape that can be used as input for supported data visualization components, including bubble and scatter charts, sunbursts, thematic maps, and treemaps. In addition, you can share the attribute values across components, such as a thematic map and a legend, using an attribute group handler.

Using attribute groups is also one way that you can easily provide visual styling for data markers for a given data set. Instead of manually choosing a color for each unique property and setting a field in your data model, you can use an attribute group handler to get back a color or shape value given a data value. Once an attribute group handler retrieves a color or shape value given a data value, all subsequent calls that pass in the same data value will always return that color or shape.

Oracle JET provides the following classes that you can use for adding attribute groups to your data visualization components:

- oj.ColorAttributeGroupHandler: Creates a color attribute group handler that will generate color attribute values.
Colors are generated using the values in the .oj-dvt-category-index* tag selectors.

- oj.ShapeAttributeGroupHandler: Creates a shape attribute group handler that will generate shape attribute values.
Supported shapes include square, circle, human, triangleUp, triangleDown, diamond, and plus.

You can see the effect of applying attribute groups to a bubble chart in the following figure. In this example, the shape of the markers (round, diamond, and plus) indicates the year for which the data applies. The color differentiates the brand. The example also uses the oj.Legend data visualization component to provide a legend for the bubble chart.

The code excerpt below shows the JavaScript to create the bubble chart with color and shape attribute groups. The code relating to the attribute groups is highlighted in bold font.

var colorHandler = new oj.ColorAttributeGroupHandler();
var shapeHandler = new oj.ShapeAttributeGroupHandler();
shapeHandler.getValue();
function ChartModel() {
/* chart data */
var data = [{xvalue:15, yvalue:25, zvalue:5, company: "Coke", year: "2010"},
{xvalue:25, yvalue:30, zvalue:12, company: "Coke", year: "2011"},
{xvalue:25, yvalue:45, zvalue:12, company: "Coke", year: "2012"},
{xvalue:15, yvalue:15, zvalue:8, company: "Pepsi", year: "2010"},
{xvalue:20, yvalue:35, zvalue:14, company: "Pepsi", year: "2011"},
{xvalue:40, yvalue:55, zvalue:35, company: "Pepsi", year: "2012"},
{xvalue:10, yvalue:10, zvalue:8, company: "Snapple", year: "2010"},
{xvalue:18, yvalue:55, zvalue:10, company: "Snapple", year: "2011"},
{xvalue:40, yvalue:50, zvalue:18, company: "Snapple", year: "2012"},
{xvalue:8, yvalue:20, zvalue:6, company: "Nestle", year: "2010"},
{xvalue:11, yvalue:30, zvalue:8, company: "Nestle", year: "2011"},
{xvalue:30, yvalue:40, zvalue:15, company: "Nestle", year: "2012"}];
this.seriesItems = [];
this.bubbleGroups = [];
for(var i = 0; i < data.length; i++){
this.seriesItems.push({x: data[i]["xvalue"], y: data[i]["yvalue"], z: data[i]["zvalue"],
color: colorHandler.getValue(data[i]["company"]),
markerShape: shapeHandler.getValue(data[i]["year"]),
categories: [data[i]["company"],data[i]["year"]]});
this.bubbleGroups.push("Group " + i);
}
}
var chartModel = new ChartModel();
$(document).ready(function() {
ko.applyBindings(chartModel, document.getElementById('chart-container'));
});

The bubble chart's legend uses the same attribute group handlers for color and shape. Since the color and shape values were initially set in the colorHandler.getValue() and shapeHandler.getValue() calls above, the calls to getValue() below will return the same values for color and shape.

var legendSections =
[{title: "Brand",
items:[{color: colorHandler.getValue("Coke"), text: "Coke", id: "Coke"},
{color: colorHandler.getValue("Pepsi"), text: "Pepsi", id: "Pepsi"},
{color: colorHandler.getValue("Snapple"), text: "Snapple", id: "Snapple"},
{color: colorHandler.getValue("Nestle"), text: "Nestle", id: "Nestle"}]},
{title: "Year",
items: [{markerShape:shapeHandler.getValue("2010"),
color: "#999999", text: "2010", id: "2010"},
{markerShape:shapeHandler.getValue("2011"),
color: "#999999", text: "2011", id: "2011"},
{markerShape:shapeHandler.getValue("2012"),
color: "#999999", text: "2012", id: "2012"}]}];
$(document).ready(function(){
ko.applyBindings({legendSections:ko.observableArray(legendSections)},
document.getElementById('legend-container'));

The Oracle JET Cookbook provides the complete code for implementing both bubble charts at Bubble Charts.

You can also initialize an attribute group with match rules which consist of a map of key value pairs for categories and the matching attribute values. For example, if you wanted to specify colors for specific categories instead of using the default colors, you could define the color attribute group with match rules.

var colorHandler = new oj.ColorAttributeGroupHandler({"soda":"#336699",
"water":"#CC3300",
"iced tea":"#F7C808"});

For detailed information about oj.ColorAttributeGroupHandler, see the oj.ColorAttributeGroupHandler API documentation. For more information about oj.ShapeAttributeGroupHandler, see the oj.ShapeAttributeGroupHandler API documentation.

Working with Layout and Navigation

The Oracle JET framework includes a collection of components, patterns, and enhanced HTML tags that you can use to control the visual layout and navigation on your page. Using ojCollapsible, ojAccordion, ojTab, ojNavigationList, and offCanvasUtils, you can control the initial data display and allow the user to access additional content by expanding sections or selecting a tab. Navigation components such as ojConveyorBelt, ojFilmStrip, and ojTrain use visual arrows or dots that the user can select to move backward or forward through data.

To control layout, you can use the Oracle JET panel design pattern or ojMasonryLayout component to present content in panels. You can also use ojDialog, and ojPopup components to present additional information to the user on demand. For HTML elements such as simple lists, you can use the standard HTML tags directly on your page, and Oracle JET will apply styling based on the application's chosen theme. Use ojProgressbar to display progress against a task.

The Oracle JET Cookbook and JavaScript API Reference for Oracle�� JavaScript Extension Toolkit (JET) include complete demos and examples for using the layout and navigation components, and you may also find the following tips and tricks helpful.

Topics:

- Working with Collapsibles

- Working with Accordions

- Working with Panels

- Working with Conveyor Belts

- Working with Film Strips

- Working with Masonry Layouts

- Working with Tabs

- Working with Trains

- Working with Dialogs

- Working with Popups

- Working with Progress Indicators

- Working with Nav Lists

- Working with offCanvasUtils

- Working with HTML Tags

Working with Collapsibles

The Oracle JET ojCollapsible component contains a header and a block of content that expands or collapses when selected.

Define the ojCollapsible on the HTML div element. Add the header and content elements as children of the component. You can use any valid markup to represent the header and block of content. In this example, the collapsible is using the h3 element to contain the header and a p element to contain the content.

<div id="collapsiblePage" data-bind="ojComponent: {component: 'ojCollapsible'}">
<h3>Header 3</h3>
<p>I'm a  Collapsible.</p>
</div>

To apply the binding, you can use the Knockout applyBindings() method and reference the id of the div element that contains the ojCollapsible component.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'ojs/ojcollapsible'],
function(oj, ko, $)
{
$(document).ready(
function()
{
ko.applyBindings(null, document.getElementById('collapsiblePage'))
}
);
});

The Oracle JET Cookbook Collapsibles demos contain the complete example for creating this collapsible as well as examples that show nested collapsibles, collapsibles with different header elements or borders, and event handling.

Working with Accordions

The Oracle JET ojAccordion component contains a list of ojCollapsible components. Each child element of the ojAccordion expands or collapses when the user selects its header to display the child element's content.

You can define the ojAccordion on the HTML div element. For each collapsible, add a div child element and add the collapsible's header and block of content as children of the div element. You can use any valid markup to define the header and block of content.

ojAccordion will add the ojCollapsible binding to each div child element by default. However, you can also specify the ojCollapsible binding explicitly to control the collapsible's behavior.

The following code shows a portion of the markup used to create the accordion shown in this section. In this example, the second collapsible (Header 3) is explicitly bound to an ojCollapsible component, and the first collapsible (Header 1) uses the default ojCollapsible binding added by the ojAccordion component.

<div id="accordionPage" data-bind="ojComponent: {component: 'ojAccordion'}">
<div id="c1">
<span><span class="demo-icon-font demo-education-icon-24"></span> Header 1</span>
<p class="oj-p">Content 1.</p>
</div>
<div id="c3" data-bind="ojComponent: {component: 'ojCollapsible', expanded:true}">
<span>Header 3</span>
<div>
<label id="mainlabelid">Colors</label>
<div id="radiosetSetBasicDemoId" aria-labelledby="mainlabelid"
data-bind="ojComponent: {component: 'ojRadioset',
value: 'red'}" >
<span class="oj-choice-row">
<input id="blueopt" type="radio" name="rbb" value="blue">
<label for="blueopt">Blue</label>
</span>
<span class="oj-choice-row">
<input id="greenopt" type="radio" name="rbb" value="green">
<label for="greenopt">Green</label>
</span>
<span class="oj-choice-row">
<input id="redopt" type="radio" name="rbb" value="red">
<label for="redopt">Red</label>
</span>
</div>
</div>
</div>
... content omitted
</div>

The Oracle JET Cookbook at Accordions contains the sample code to create the accordion pictured in this section. You can also find examples for expanding multiple child elements and responding to events.

For additional information about working with the ojCollapsible component, see Working with Collapsibles.

Working with Panels

Panels use Oracle JET styles included with the Alta theme to display a bounded section on the page. You can customize the size, color, and content of the panel.

In this example, three panels are displayed with three different colors. The content for the first two panels is defined using the HTML header and paragraph elements. The content for the third panel is defined as an ojCollapsible component. The oj-panel-* classes are defined on the div elements that represent the panels.

<div id="panelPage">
<div class="oj-panel demo-panel-customizations">
<h3>Header</h3>
<p>Hello world!</p>
How is it going out there?
</div>

<div class="oj-panel oj-panel-alt1 demo-panel-customizations">
<h3 class="oj-header-border">Header</h3>
<p>Hello world!</p>
It's going great in JET land.
</div>

<div class="oj-panel oj-panel-alt2 demo-panel-customizations">
<div data-bind="ojComponent: {component: 'ojCollapsible', collapsed: false}">
<h3>Header</h3>
<div>
<p>I'm a collapsible inside a panel</p>
When you close the collapsible the panel will shrink.
</div>
</div>
</div>
</div>

You can customize the size or display using styles, or you can create a custom style class. In this example, the panel is customized using the demo-panel-customizations class, shown below.

.demo-panel-customizations {
width:  200px;
display: inline-block;
margin: 10px;
vertical-align: top;
}

The Oracle JET Cookbook contains the complete code for this example at Panel Content. You can also find an example that shows the available panel colors at Panel Colors.

For additional information about using and customizing the Oracle JET themes included with Oracle JET, see Theming Applications. For more information about the ojCollapsible component, see Working with Collapsibles.

Working with Conveyor Belts

The Oracle JET ojConveyorBelt component manages a group of sibling child elements to control the number of child elements displayed and provides horizontal or vertical scrolling to cycle through the other child elements.

Define the ojConveyorBelt on the HTML div element. You can add the sibling child elements as either direct children of the conveyor belt or as the children of a container element which is the direct child of the conveyor belt. In this example, the ojConveyorBelt is configured for horizontal scrolling with a maximum width of 200 pixels, and the sibling child elements are defined as Oracle JET ojButton components.

<div id="conveyorbelt-horizontal-example">
<div style="max-width:200px;"
data-bind="ojComponent: {component: 'ojConveyorBelt'}">
<button data-bind="ojComponent: {component: 'ojButton'}">Hydrogen</button>
<button data-bind="ojComponent: {component: 'ojButton'}">Helium</button>
<button data-bind="ojComponent: {component: 'ojButton'}">Lithium</button>
<button data-bind="ojComponent: {component: 'ojButton'}">Beryllium</button>
<button data-bind="ojComponent: {component: 'ojButton'}">Boron</button>
<button data-bind="ojComponent: {component: 'ojButton'}">Carbon</button>
<button data-bind="ojComponent: {component: 'ojButton'}">Nitrogen</button>
<button data-bind="ojComponent: {component: 'ojButton'}">Oxygen</button>
<button data-bind="ojComponent: {component: 'ojButton'}">Fluorine</button>
<button data-bind="ojComponent: {component: 'ojButton'}">Neon</button>
<button data-bind="ojComponent: {component: 'ojButton'}">Sodium</button>
<button data-bind="ojComponent: {component: 'ojButton'}">Magnesium</button>
</div>
</div>

Note:

The ojConveyorBelt component does not provide accessibility features such as keyboard navigation. It is the responsibility of the application developer to make the items in the conveyor belt accessible. For tips and additional detail, see the ojConveyorBelt API documentation.

When you configure the child elements as direct children of the ojConveyorBelt, the component will ensure that they are laid out according to the specified style. If, however, you configure the child elements as the children of a container element, you must take additional steps to ensure the correct display. For details, see the ojConveyorBelt API documentation.

The Oracle JET Cookbook Conveyor Belts demos contain the complete code for this example. In addition, you will find examples for a vertical conveyor belt and conveyor belts with nested content, tab-based scrolling, and programmatic scrolling.

Note:

The Oracle JET ojFilmStrip component also manages a group of sibling child elements to provide horizontal or vertical scrolling to cycle through the other child elements. However, it also provides the ability to:

- layout a set of items across discrete logical pages.

- control which and how many items are shown.

- hide items outside the current viewport from tab order and screen readers.

For additional information, see Working with Film Strips.

Working with Film Strips

The Oracle JET ojFilmStrip component manages a group of sibling child elements to lay out its children in a single row or column across logical pages and provides horizontal or vertical scrolling to cycle through the other child elements. You can configure the film strip to use arrows or add the ojPagingControl component which uses dots for scrolling through the child elements.

The following image shows two ojFilmStrip components configured for horizontal scrolling, The sibling child elements are panels, using the Oracle JET panel design pattern. In the top film strip, the user selects arrows for navigating through the content, and the user selects dots for navigating through the bottom film strip content.

Configuring Film Strips

Define the ojFilmStrip on the HTML div element and add the sibling child elements as direct children of the film strip. The code sample below shows the markup for the film strip example using arrows for navigation.

<div id="filmStripDiv" class="oj-panel" style="margin: 20px;">
<div id="filmStrip" aria-label="Set of chemicals"
data-bind="ojComponent: {component: 'ojFilmStrip'}">
<!-- ko foreach: chemicals -->
<div class="oj-panel oj-panel-alt2 demo-filmstrip-item"
data-bind="style: {display: getItemInitialDisplay($index())}">
<span data-bind="text: name"></span>
</div>
<!-- /ko -->
</div>
</div> <!-- end filmStripDiv -->

You can use the arrowPlacement option to control the location of the arrows. By default, it is set to adjacent which displays arrows outside the content, but you can set it to overlay to overlay the arrows on the content.

In this example, the film strip uses the Knockout foreach binding to iterate through the list of chemicals defined in the application's main script, shown below.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'ojs/ojfilmstrip'],
function(oj, ko, $)
{
$(document).ready(
function()
{
function MyModel() {
var self = this;
self.chemicals = [
{ name: 'Hydrogen' },
{ name: 'Helium' },
{ name: 'Lithium' },
{ name: 'Beryllium' }
{ name: 'Boron' },
{ name: 'Carbon' },
{ name: 'Nitrogen' },
{ name: 'Oxygen' },
{ name: 'Fluorine' },
{ name: 'Neon' },
{ name: 'Sodium' },
{ name: 'Magnesium' }
];

getItemInitialDisplay = function(index)
{
return index < 3 ? '' : 'none';
};
};

var model = new MyModel();

ko.applyBindings(model, document.getElementById('filmStripDiv'));
}
);
});

ojFilmStrip will lay out the child items across multiple logical pages and allow for changing between logical pages. When the component is resized, the layout will adjust automatically, and the number of pages and items shown per page may change. To control the display when the page changes, use the ojFilmStrip component's getPagingModel() method.

The Oracle JET Cookbook at Film Strips includes the complete code for the example used in this section. You can also find examples for film strips with pagination, vertical film strips, lazy loading a film strip, film strips that contain master-detail data, and film strips that use the getPagingModel() to display paging information.

Note:

ojFilmStrip is a layout component, and it is the responsibility of the application developer to make the items in the film strip accessible. For tips and additional detail, see the Accessibility section in the ojFilmstrip API documentation.

Working with Masonry Layouts

Use the Oracle JET ojMasonryLayout component to create a responsive grid of tiles containing arbitrary content. You can specify the size of each tile by defining the number of rows and columns that the tile will contain relative to the other tiles in the layout.

The image below shows a basic masonry layout with eight tiles. In this example, the first tile in the layout contains two columns and one row, and the remaining tiles occupy one column and one row. As the screen size changes from small to large, the tile layout changes, and the first tile maintains its size relative to the other tiles.

Topics:

- Configuring Masonry Layouts

- Understanding the ojMasonryLayout Layout Process

- ojMasonryLayout Size Style Classes

Configuring Masonry Layouts

Define the ojMasonryLayout on the HTML div element and add the group of sibling child elements that the component will manage. To specify the relative size of the tiles, add one of the ojMasonryLayout size style classes to each child element.

The code sample below shows the markup for the basic ojMasonryLayout shown in this section. The example uses the Knockout foreach binding to iterate through the child elements.

<div id="masonrylayout-basic-example">
<div class="demo-scroll-container">
<div id="masonryLayout" data-bind="ojComponent: {component: 'ojMasonryLayout'}">
<!-- ko foreach: chemicals -->
<div class="oj-panel oj-panel-alt2 demo-tile" data-bind="text: name, css: sizeClass"></div>
<!-- /ko -->
</div>
</div>
</div>

The size of each tile is determined by the value in the sizeClass variable which is defined in the application's main script shown below.

require(['ojs/ojcore', 'knockout', 'jquery',
'ojs/ojknockout', 'ojs/ojmasonrylayout'],
function(oj, ko, $)
{
$(document).ready(
function()
{
function MyModel() {
var self = this;

self.chemicals = [
{ name: 'Hydrogen', sizeClass: 'oj-masonrylayout-tile-2x1' },
{ name: 'Helium', sizeClass: 'oj-masonrylayout-tile-1x1' },
{ name: 'Lithium', sizeClass: 'oj-masonrylayout-tile-1x1' },
{ name: 'Beryllium', sizeClass: 'oj-masonrylayout-tile-1x1' },
{ name: 'Boron', sizeClass: 'oj-masonrylayout-tile-1x1' },
{ name: 'Carbon', sizeClass: 'oj-masonrylayout-tile-1x1' },
{ name: 'Nitrogen', sizeClass: 'oj-masonrylayout-tile-1x1' },
{ name: 'Oxygen', sizeClass: 'oj-masonrylayout-tile-1x1' }
];
}

ko.applyBindings(new MyModel(),
document.getElementById('masonrylayout-basic-example'));
}
);
});

The Oracle JET Cookbook at Masonry Layouts contains the complete example for the basic masonry layout shown in this section. You can also find demos that illustrate the different tile sizes, and masonry layouts that you can resize, reorder, and flip.

Note:

The ojMasonryLayout component does not provide accessibility features such as keyboard navigation. It is the responsibility of the application developer to make the items in the layout accessible. For tips and additional detail, see the ojMasonryLayout API documentation.

Understanding the ojMasonryLayout Layout Process

ojMasonryLayout lays out its child tiles based on the size of the screen, the size of the tiles, and the order in which you define them.

To determine the layout, ojMasonryLayout:

- Processes the tiles in the order in which they originally appear in the DOM.

- Determines the number of columns to display based on the width of the component and the width of a 1x1 tile.

- Determines the number of rows to display based on the number of columns and the number and sizes of tiles to lay out.

- Lays out the grid cells in a left-to-right, top-to-bottom order (or right-to-left, top-to-bottom order when the reading direction is right-to-left).
Tiles will be positioned in the first empty cell in which they fit. This can result in empty cells in the layout. Subsequent tiles may fill those earlier gaps if they fit.

If the component is resized, ojMasonryLayout will redo the layout, and the number of columns and rows may change.

ojMasonryLayout Size Style Classes

ojMasonryLayout supports tile sizes ranging from one to three columns and one to three rows, as shown in the following table.

Style Class

Description

oj-masonrylayout-tile-1x1

A tile that spans one column and one row

oj-masonrylayout-tile-1x2

A tile that spans one column and two rows

oj-masonrylayout-tile-1x3

A tile that spans one column and three rows

oj-masonrylayout-tile-2x1

A tile that spans two columns and one row

oj-masonrylayout-tile-2x2

A tile that spans two columns and two rows

oj-masonrylayout-tile-2x3

A tile that spans two columns and three rows

oj-masonrylayout-tile-3x1

A tile that spans three columns and one row

oj-masonrylayout-tile-3x2

A tile that spans three columns and two rows

Working with Tabs

You can use the Oracle JET ojTabs component to create themable, sortable, and removable tabs that follow WAI-ARIA authoring practices for accessibility. The tab bar is customizable, and you can add buttons, radiosets, or other components as needed. The tab bar position is also customizable, and you can configure the tab bar to display on the top, bottom, or side (start or end) of the tab's content, as shown in the following image.

To create the ojTabs component, add it to a HTML div container element on your page. To create the tab bar, add the HTML ul element, and add li child elements for each tab. To define the tab content, add div elements for each as a direct child of the container div in the order in which you want the content to appear.

The code sample below shows the markup for an ojTabs component that contains four tabs that display text. In this example, the tab bar position is set to bottom, and the fourth tab is disabled.

<div id="tabs-container">
<div id="tabs" data-bind="ojComponent:{component: 'ojTabs', disabledTabs: [3], edge: 'bottom'}">
<!-- tab bar -->
<ul>
<li><span>Tab 1</span></li>
<li><span>Tab 2</span></li>
<li><span>Tab 3</span></li>
<li><span>Disabled Tab</span></li>
</ul>

<!-- tab contents -->
<div id="tabs-1">
<p>Tab 1 Content</p>
</div>
<div id="tabs-2">
<p>Tab 2 Content</p>
</div>
<div id="tabs-3">
<p>Tab 3 Content</p>
</div>
<div id="tabs-4">
<p>Disabled Tab Content</p>
</div>
</div>
</div>

Note:

Although the ojTabs component is wrapped as a jQuery UI widget, its structure differs from the jQuery UI tabs widget. For additional detail, see the ojTabs API documentation.

The Oracle JET Cookbook includes the code sample for creating a basic ojTabs component pictured in this section at Tabs. In addition, you will find samples that show events that are triggered on the ojTabs component, add and remove tabs to a page, create horizontal tabs inside vertical tabs, and create tabs that are sortable, contain icons for the header, or that truncate depending on the width of the display.

Working with Trains

The ojTrain component displays a navigation visual that enables the user to move back and forth between different points. Typically, the train displays steps in a task or process.

Each step can display information about its visited state (visited, unvisited, or disabled) and a message icon of type error, confirmation, warning, info, or fatal.

You can create the ojTrain component on the HTML div element. Use the Knockout data-bind syntax to define the ojTrain component and any desired options. The code sample below shows a portion of the markup for the ojTrain shown in this section.

<div id="train-container" >
<div id="train"
data-bind="ojComponent:{component: 'ojTrain', selected: currentStepValue, steps: stepArray}">
</div>
... contents omitted
</div>

The code sample below shows the code that applies the binding, defines the steps and captures the step selection.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'ojs/ojtrain', 'ojs/ojbutton'],
function(oj, ko, $)
{
function TrainData() {
this.currentStepValue = ko.observable('stp1');
this.stepArray =
ko.observableArray(
[{label:'Step One', id:'stp1'},
{label:'Step Two', id:'stp2'},
{label:'Step Three', id:'stp3'},
{label:'Step Four', id:'stp4'},
{label:'Step Five', id:'stp5'}]);
};

var trainModel = new TrainData();

$(function() {
ko.applyBindings(trainModel, document.getElementById('train-container'));
});
});

The Oracle JET Cookbook includes the complete code for this example at Trains. You can also find additional examples that show a stretched train, a train with messages, and a train with button navigation.

Working with Dialogs

You can use the Oracle JET ojDialog component to display dialogs that are themable and follow WAI-ARIA authoring practices for accessibility. By default, the ojDialog component renders modal dialogs which require user interaction before control returns to the calling window.

Typically, you create the ojDialog component on the HTML div element. Define the dialog title in the div element's title attribute and use the Knockout data-bind syntax to define the ojDialog. Add content to the dialog using the oj-dialog-body and oj-dialog-footer sections.

The ojDialog component includes support for the header close icon and close handler, but you must add your own markup for creating the OK button in the oj-dialog-footer section, as shown in the code sample below.

<div id="dialogWrapper">
<div style="display:none" id="modalDialog1" title="Modal Dialog"
data-bind="ojComponent:{component: 'ojDialog', initialVisibility: 'hide'}">
<div class="oj-dialog-body">
The dialog window can be moved, resized and closed with the 'x' icon.
Arbitrary content can be added to the oj-dialog-body and oj-dialog-footer
sections.
</div>
<div class="oj-dialog-footer">
<button id="okButton" data-bind="ojComponent: {component: 'ojButton', label: 'OK'}">
</button>
</div>
</div>
<button id="buttonOpener"
data-bind="ojComponent: {component: 'ojButton', label: 'Open Modal Dialog'}">
</button>
</div>

You must also add code to handle the events on the OK and button opener buttons, in addition to the Knockout applyBindings() call that completes the component binding.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'ojs/ojbutton', 'ojs/ojdialog'],
function(oj, ko, $)
{
function dialogModel() {
var self = this;
self.handleOpen = $("#buttonOpener").click(function() {
$("#modalDialog1").ojDialog("open"); });
self.handleOKClose = $("#okButton").click(function() {
$("#modalDialog1").ojDialog("close"); });
}
$(function() {
ko.applyBindings(new dialogModel(), document.getElementById('dialogWrapper'));
});
});

Note:

Although the ojDialog component is wrapped as a jQuery UI widget, its structure differs from the jQuery UI dialog widget. For additional detail, see the ojDialog API documentation.

The Oracle JET Cookbook includes the complete code for this example at Dialogs. You can also find samples for creating a modeless ojDialog and dialogs rendered with custom headers and other display options.

Working with Popups

The Oracle JET popup framework includes the ojPopup component that you can use to create popups on your page. To manage stacking order of ojPopup and all Oracle JET components that use popups internally, such as ojDialog and ojMenu, the popup framework uses the CSS z-index property and re-parents the popup DOM into a zorder container.

Topics:

- Working with ojPopup

- Working with the Oracle JET Popup Framework

Working with ojPopup

You can use the Oracle JET ojPopup component to create themable popups that follow WAI-ARIA authoring practices for accessibility. The image below shows a popup displayed with default options, but you can customize the popup's position, tail, and chrome.

You can create the ojPopup on the HTML div or span element. Add the popup's content as the child of that element. For the image shown above, the ojPopup is defined on the div element, with the content defined in the span element.

<div style="display:none" id="popup1"
data-bind="ojComponent:{component: 'ojPopup'}">
<span>Hello World!!!</span>
</div>

In this example, the popup displays when the user clicks Go. The Go button is defined as an ojButton component that references the popup's id attribute to display the popup when clicked.

<div id="popupWrapper">
<div style="display:none" id="popup1"
data-bind="ojComponent:{component: 'ojPopup'}">
<span class="blink-rainbow">Hello World!!!</span>
</div>
<button id="btnGo"
data-bind="ojComponent: {component: 'ojButton', label: 'Go'},
click: function()
{
$('#popup1').ojPopup('open', '#btnGo');
}">
</button>
</div>

The Oracle JET Cookbook contains the complete example for this popup at Popups. You can also find examples that customize the popup and that use the popup as a tooltip for accessibility.

Note:

The ojPopup component defines default roles for accessibility and keyboard navigation. You can find details about the component's accessibility support in the ojPopup API documentation. In addition, you can find some general recommendations about best practices for making the gestures that launch the popup accessible.

Working with the Oracle JET Popup Framework

The popup framework uses the CSS z-index property and re-parents the popup DOM to manage the stacking order of ojPopup and all Oracle JET components that use popups internally, such as ojDialog and ojMenu. z-index defaults should be sufficient for most purposes, but you can modify them using SCSS variables to generate new CSS or modify the CSS styles directly.

When a popup of any type opens, the Oracle JET framework re-parents it into a zorder container in the document body and re-parents it back to its original location when closed. For example, if you add the ojPopup component shown in Working with ojPopup to the main content in an Oracle JET QuickStart Basic application, the browser DOM reflects its initial placement within the document body.

When the user clicks the Go button to display the popup, the Oracle JET framework re-parents it into the oj_zorder_container div as a direct child of the body element.

The purpose of re-parenting is to better manage the stacking context as it relates to how popups are used versus where they are defined in the document. The zorder container has a default root container that holds popups open. When the popup is re-parented, it is wrapped in a div containing the oj-popup-layer style and assigned a z-index weight. If there are multiple open popups on the page, each popup is re-parented to the zorder container, and the active popup will be the popup with the highest z-index weight.

For example, at initial display, the ojPopup's layer is marked with the oj-popup-layer style which has a z-index value of 1000. Popups of the same type are assigned the same z-index values. If there are multiple popups open, the popup that has active focus will be assigned a greater z-index value of 1001, and the oj-popup-layer.oj-focus-within style is applied.

In most cases, you should never need to modify the CSS z-index defaults since the resulting behavior may be unpredictable. If needed, however, you can update the SCSS variables used to generate the application's CSS or modify the CSS styles directly. The following table shows the default CSS style selectors, SCSS variables, and z-index values.

CSS Selector

SCSS Variable

Z-Index Value

oj-popup-layer

$popupZindex

1000

oj-popup-layer.oj-focus-within

$popupZindex + 1

1001

oj-popup-layer.oj-popup-tail-simple

$noteWindowZindex

1030

oj-popup-layer.oj-popup-tail-simple.oj-focus-within

$noteWindowZindex + 1

1031

oj-listbox-drop-layer

$popupZindex

1000

oj-menu-layer

$popupZindex

1000

oj-dialog-layer

$dialogZindex

1050

oj-dialog-layer.oj-focus-within

$dialogZindex + 1

1051

oj-component-overlay

$dialogZindex

1050

When popup components are initially defined on the page, they are defined with a default z-index value of 1 using the CSS selectors shown in the following table. The root popup is absolutely positioned on the page in relation to its parent container. Setting the value to 1 ensures that the root popup's children will display above the popup.

Oracle JET Component

CSS Selector

SCSS Variable

Z-Index Value

ojMenu

oj-menu

$defaultZindex

1

ojPopup

oj-popup

$defaultZindex

1

ojDialog

oj-dialog

$defaultZindex

1

ojCombobox, ojSelect

oj-listbox-drop

$defaultZindex

1

ojInputDateTime, ojInputDate, ojInputTime

oj-popup

$defaultZindex

1

Editable components using note windows for messaging

oj-popup.oj-popup-tail-simple

$defaultZindex

1

For additional information about Oracle JET's popup strategy, see the ojPopup API documentation.

For additional information about Oracle JET's use of CSS and SCSS, see Theming Applications. For more information about the CSS z-index property, see http://www.w3.org/wiki/CSS/Properties/z-index.

Working with Progress Indicators

You can use ojProgressbar to indicate progress against a task in a horizontal meter. Set the value for the progress indicator in the ojProgressbar value option. In the image below, the progress indicator's value option is set to 70 to indicate that the task is 70% complete.

To indicate that the value is indeterminate, set the value option to -1, and the progress indicator will change to reflect the indeterminate status.

To create the ojProgressbar component, you can use the ojComponent binding with Knockout's data-bind syntax.

<div id="progressbarWrapper">
<div id="progressbar" data-bind="ojComponent:{component: 'ojProgressbar', value: progressValue}">
</div>
</div>

The script that sets the value defines a Knockout observable and sets the initial value. In this example, the progress indicator's initial value is set to -1, to indicate that the value is indeterminate.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'ojs/ojprogressbar'],
function(oj, ko, $)
{
function ViewModel()
{
var self = this;
self.progressValue = ko.observable(-1);
}

ko.applyBindings(new ViewModel(), document.getElementById('progressbarWrapper'));
});

The Oracle JET Cookbook at Progress Indicators contains a complete example for an ojProgressbar that shows the effect of adjusting the progress indicator's value. You can also find examples that show a progress indicator with labeling and a progress indicator that is linked to changing data.

Working with Nav Lists

The Oracle JET ojNavigationList component enhances the HTML list (ul) element to provide a themable, WAI-ARIA compliant component that displays a list of vertical or horizontal navigation links. You can configure the nav list to slide in and out of view, expand and collapse, and respond to changes in screen size.

Topics:

- Understanding Data Requirements for Nav Lists

- Working with Nav Lists and Knockout Templates

Understanding Data Requirements for Nav Lists

The data source for the ojNavigationList component can be one of the following:

- Flat or hierarchical static HTML
The following image shows a vertical nav list that displays static, hierarchical HTML.

The following code sample shows a portion of the markup used to create the ojNavigationList component with hierarchical static content and the Oracle JET component binding. The markup uses ul and li HTML elements to define the nav list, with nested lists for the hierarchical data. The markup also specifies selectedItem as a Knockout observable in the component's selection option that will update when the user selects a list item.

<div id="navlistdemo" class="oj-row">
<div class="oj-col oj-sm-3" >
<div data-bind="ojComponent:{
component:'ojNavigationList',
selection: selectedItem,
drillMode:'none'}">
<ul>
<li id="save" >
<a href="#" >Save</a>
</li>
<li id="zoomin" >
<a href="#" >Zoom In</a>
</li>
<li id="zoomout">
<a href="#" >This is Label with very long text</a>
</li>
<li id="print" class="oj-disabled">
<a href="#" >Print...</a>
</li>
<li id="playback">
<a href="#">Playback</a>
<ul>
<li id="prev">
<a href="#">Previous</a>
</li>
... contents omitted
</ul>
</li>
</ul>
</div>
</div>

The code to apply the binding and define selectedItem is shown below. In this example, the initial value of the Knockout observable is set to save, and the nav list will initially display with the Save item selected.

require(['ojs/ojcore','knockout','jquery','ojs/ojknockout','ojs/ojnavigationlist'],
function(oj, ko, $)
// this callback gets executed when all required modules are loaded
{
function ViewModel(){
this.selectedItem = ko.observable("save");
}
var vm = new ViewModel();
ko.applyBindings(vm, document.getElementById('navlistdemo'));
}
);

- Oracle JET TreeDataSource, including oj.JsonTreeDataSource and oj.CollectionTreeDataSource.
Typically, you use one of the Oracle JET TreeDataSource components when your list data contains groups. To use a TreeDataSource, you specify the method that returns the tree data in the data option for the ojNavigationList component.

<div data-bind="ojComponent:{
component:'ojNavigationList',
drillMode: 'sliding',
optionChange : onSelect,
data : dataSource,
item: {template: 'folder_template'}
}">
</div>

The Oracle JET Cookbook contains the complete example for creating a nav list with an oj.JsonTreeDataSource object.

- Oracle JET TableDataSource, including oj.ArrayTableDataSource, and oj.CollectionTableDataSource
Use oj.ArrayTableDataSource when the underlying data is a static array or Knockout observableArray. If you use an observableArray, the nav list will automatically react when items are added or removed from the array.

Use oj.CollectionTableDataSource when oj.Collection is the model for the underlying data. The nav list will automatically react to model events from the underlying oj.Collection. See the documentation for oj.CollectionTableDataSource for more details on the available options.

To use a TableDataSource, specify the method that returns the table data in the data option for the ojNavigationList component.

<div data-bind="ojComponent:{
component: 'ojNavigationList',
drillMode: 'none',
selection: selectedItem,
data: dataSource,
item: {template: 'server_template'}}">
</div>

The Oracle JET Cookbook contains a complete example for creating a nav list with an oj.ArrayTableDataSource object.

The Oracle JET Cookbook contains a number of ojNavigationList examples , including ones that use each of the supported data sources. For details, see Nav Lists.

Working with Nav Lists and Knockout Templates

You can use a Knockout template to contain the markup for your list item content. Reference the name of the template in the ojNavigationList component's template option.

The code sample below shows a portion of the markup and template for a nav list using an oj.ArrayTableDataSource object for its data. In this example, the template is named server_template.

<div data-bind="ojComponent:{
component: 'ojNavigationList',
drillMode: 'none',
selection: selectedItem,
data: dataSource,
item: {template: 'server_template'}}">
</div>

<script type="text/html" id="server_template">
<li data-bind="attr:{ id : $data['id']}, css:{'oj-disabled' : $data['disabled']=='true'}">
<a href="#" data-bind="text: $data['name']"></a>
</li>
</script>

At runtime, the nav list iterates through the array and displays the content contained in name and applies styling for disabled items.

You can find the complete code sample for this nav list at Nav Lists.

For additional information about working with Knockout templates, see Using Knockout.js Templates and the ojModule Binding.

Working with offCanvasUtils

The Oracle JET framework offCanvasUtils are useful if you want to store content in a partition that is not part of the viewport. With the offCanvasUtils, you can configure the partition to slide in and out of view at the start, end, top, or bottom of the viewport, either by pushing existing content out of view or by overlaying the partition.

The following image shows two examples of partitions configured to slide in at the start of the viewport. In the partition configured for push, offCanvasUtils pushes aside as much of the viewport content as needed to display the partition. In the partition configured for overlay, the content is displayed over the main content, obscuring the content.

Configuring an Off-Canvas Partition

To configure an off-canvas partition, create a HTML div wrapper to contain both the content and the off-canvas partition and use offCanvasUtils to show, hide, or toggle the partition view.

The Oracle JET Cookbook Drawer Utilities demos contain the sample code that implements the off-canvas partitions shown in this section and links to the oj.OffcanvasUtils API documentation. You can also find examples that implement the off-canvas partitions as responsive design patterns that change their position from off screen to fixed inside the viewport based on a media query. For more information about responsive design and media queries, see Designing Responsive Applications.

Working with HTML Tags

You can add HTML tags to your Oracle JET page as you would for any other HTML application. However, you should be aware that Oracle JET provides styling directly on the following tags:

- Header (h1, h2, h3, h4)

- Horizontal rule (hr)

- Link (a)

- List (ul, ol, li)

- Paragraph (p)

There may be use cases where you do not want to use aspects of the default theming because it causes compatibility issues. For example, you may be embedding JET components or regions in a page controlled by another technology, such as Oracle ADF. In these cases, Oracle JET provides options for theming for compatibility. For additional information, see Understanding Oracle JET Theming For Compatibility.

Adding jQuery UI Components or Effects to Your Oracle JET Application

The Oracle JET distribution includes only the jQuery UI modules needed by the Oracle JET framework. If you are using RequireJS to manage your Oracle JET modules and want to add a jQuery UI component or effect to your existing Oracle JET application, you can download the additional jQuery UI module that contains the jQuery UI component or effect and add it to the Oracle JET folder containing the existing jQuery UI modules.

To add a jQuery UI component or effect to your Oracle JET application:

1. To add the debug version of the new jQuery UI module to your application, do the following:

a. Download the module that contains the component or effect you need at: https://github.com/jquery/jquery-ui/tree/1.11.4/ui.

b. Place the downloaded module in the Oracle JET jQuery UI debug folder: js/libs/jquery/jqueryui-amd-1.11.4.

2. To add the minified version of the new jQuery UI module to your application, do the following:

a. On your local system, install jQuery UI using bower, a package management tool:

bower -V install jquery-ui

For details about downloading bower and using it with jQuery UI, see http://learn.jquery.com/jquery-ui/environments/bower/.

b. From the location that contains your bower files, copy the desired module to the Oracle JET jQuery UI minified folder: js/libs/jquery/jqueryui-amd-1.11.4.min.

c. Rename the module to remove .min from the name.
For example, if you copied autocomplete.min.js to the minified folder, rename it to autocomplete.js.

Using the same name for both the debug and minified versions of the module enables you to change the path mapping in your RequireJS bootstrap file to switch between debug and minified versions.

3. Add the new module to your RequireJS bootstrap file, typically main.js.
For example, add the highlighted code below to your bootstrap file to use the autocomplete jQuery UI module.

require(['ojs/ojcore', 'knockout', 'jquery', 'jqueryui-amd/autocomplete'],
function(oj, ko, $) // this callback gets executed when all required modules are loaded
{
// add any startup code that you want here
}
);

For additional information about using RequireJS to manage your application's modules, see Using RequireJS for Modular Development.

Note:

This process is provided as a convenience for Oracle JET developers. Oracle JET will not support the additional modules and cannot guarantee that the additional modules will work correctly with other Oracle JET components or framework features.

7 Using the Common Model and Collection API

The Oracle JET Common Model and Collection API provides a two-way data binding model using Knockout. Using the Model and Collection classes, you can build Create, Read, Update, Delete (CRUD) applications that integrate REST services or data from any web service that returns data in the form of JSON objects.

Topics:

- Typical Workflow for Binding Data in Oracle JET

- About Oracle JET Data Binding

- Using the Oracle JET Common Model and Collection Framework

- Integrating REST Services

- Creating a CRUD Application Using Oracle JET

Typical Workflow for Binding Data in Oracle JET

To use the Oracle JET Common Model for building CRUD applications, refer to the typical workflow described in the following table:

Task

Description

More Information

Understand Oracle JET framework support for data binding

Identify the Oracle JET framework's support for the Model-View-ViewModel design.

About Oracle JET Data Binding

Use Oracle JET's Common Model and Collection

Identify the Oracle JET Common Model and Collection API, its relationship with Knockout, and how to use it in your Oracle JET application.

Using the Oracle JET Common Model and Collection Framework

Integrate REST services

Understand how to integrate REST services into your Oracle JET application.

Integrating REST Services

Create a CRUD application

Create a CRUD application using the Oracle JET Common Model and Collection API.

Creating a CRUD Application Using Oracle JET

About Oracle JET Data Binding

The Oracle JET framework supports two-way data binding between the View and Model layers in the Model-View-ViewModel (MVVM) design. Data changes in the ViewModel are sent to the UI components, and user input from the UI components is written back into the ViewModel.

The Oracle JET framework uses Knockout to perform the data binding between the UI elements and the ViewModel. The ViewModel normally contains data fields for the UI state as well as references to external data. One of the ways to provide external data is to use the Common Model and Collection API.

Data for an Oracle JET application can come from any web data source that generates JSON data, such as a REST service, Server Sent Event (SSE), or WebSocket. In addition, Oracle JET also provides specific support for integrating web service data based on the Oracle REST standard.

The Oracle JET framework also provides UI components for the View layer that include properties for data binding with Knockout. For additional information about Oracle JET's UI components and data binding options, see Understanding Oracle JET User Interface Basics.

Using the Oracle JET Common Model and Collection Framework

The Oracle JET Common Model and Collection API provides a collection-of-records object model that includes classes for bringing external data into an Oracle JET application and mapping the data to the application���s view model.

Topics:

- About the Oracle JET Common Model and Collection API

- About Oracle JET Data Binding and Knockout

- Using the Oracle JET Common Model and Collection API

About the Oracle JET Common Model and Collection API

The Oracle JET Common Model and Collection API provides a collection-of-records object model that includes the following classes:

- oj.Model: Represents a single record from a data service such as a RESTful web service

- oj.Collection: Represents a set of data records and is a list of oj.Model objects of the same type

- oj.Events: Provides methods for event handling

- oj.KnockoutUtils: Provides methods for mapping the attributes in a oj.Model or oj.Collection object to Knockout observables for use with component ViewModels.

oj.Model and oj.Collection include client-side API that provides one way to bring external data into an Oracle JET application. oj.KnockoutUtils provides the map() method to map the attributes in a model object or the attributes of all models in a collection object to the application's view data model.

About Oracle JET Data Binding and Knockout

Knockout provides bindings between components as well as binding data from a ViewModel to components or HTML elements in an Oracle JET application. Knockout is an integral part of Oracle JET's framework and is included in the Oracle JET distribution.

The Oracle JET Model and Collection API includes the KnockoutUtils class which contains the map() method to convert the attributes in a model object (or the attributes of all models in a collection object) into Knockout observables for use with components' ViewModels.

The example below maps the data collection to the tasks ViewModel.

renderTaskViews = function(tasksData) {
this.tasks = oj.KnockoutUtils.map(data);
}

To bind UI components in Oracle JET applications to the data model, the Oracle JET components support Knockout's data-bind attribute, both for standard and Oracle JET UI components. For additional information about working with Oracle JET UI components, see Understanding Oracle JET User Interface Basics.

<ul data-bind="foreach: tasks">
<li data-bind="text: name"></li>
</ul>
<div data-b

For additional information about Knockout, see http://www.knockoutjs.com.

Using the Oracle JET Common Model and Collection API

To use a Model or Collection class, an application must extend oj.Model or oj.Collection to create a foundation object to represent a data record or list of records from its data service. The application provides the data service's URL used for fetching and updating task records (when a task record's ID is appended), along with various options giving users the ability to map data service records to their client-side ViewModel and vice versa.

To use the Oracle JET Common Model and Collection API:

1. Add JavaScript code to your application that extends oj.Model.

The following script shows a simple example of extending oj.Model to create a model object which defines a TaskRecord. In this example, the data is returned from the REST service at the indicated URL. The parse and parseSave callbacks parse the data and map the attributes received from the REST service to desired ViewModel attribute names.

var TaskRecord = oj.Model.extend({
url: "http://RESTServerIP:port/ADFjs-Tasks-context-root/resources/ojet/tasks",
parse: parseTask
parseSave: parseSaveTaskRecord});

/**
* Callback to map attributes returned from RESTful data service to desired view model attribute names
*/
parseTask = function (response) {
return {Priority: response['PRIORITY'], TaskType: response['TASK_TYPE'],
Severity: response['SEVERITY'],id: response['TASK_ID'], Summary: response['SUMMARY']};
};

/**
* Callback to map view model attributes back to RESTful data service record attribute names on create or update
*/
parseSaveTaskRecord = function (record) {
return {PRIORITY: record['Priority'], TASK_TYPE: record['TaskType'],
SEVERITY: record['Severity'], TASK_ID: record['id'], SUMMARY: record['Summary']};
};

2. Add JavaScript code to your application that extends oj.Collection.

The following code example creates a collection object for its entire data set (or list) of task records and ties that to a specific instance of a task record model. The fetch() method tells the collection to go to the data service and asynchronously retrieve the data services' data set using the given URL, through jQuery AJAX calls. The application's success callback method is invoked when the call successfully returns and the collection has been populated with model records.

var task = new TaskRecord();
task.on("all", onChangeEventHandler, this);

// Create a base object "class" for the entire task dataset
var TaskCollection = oj.Collection.extend({
url: "http://RESTServerIP:Port/Tasks-context-root/resources/ojet/tasks",
model: task,
initialize: function () { // Perform collection initialization here });

// Create a specific instance for the tasks.  This will be filled with instances of the
// model "task" for each record when the data is retrieved from the data service
var tasks = new TaskCollection();

// Get the tasks from the server, and call the success: function when finished for further application processing
tasks.fetch({success:function (collection, response, options) {
tasksData = collection;
renderTaskViews(tasksData);
}});

// Called when any attribute changes on any task model object
onChange = function() {
};

3. Bind the returned data collection to a Knockout ViewModel to make it ready for consumption by one or more components on the application page.

The following code sample maps the tasks Collection object to the renderTaskViews view using the oj.KnockoutUtils.map() function.

renderTaskViews = function(tasksData) {
// self.tasks is the Knockout view model structure
this.tasks = oj.KnockoutUtils.map(data);
var self = this;
}

4. Add code to the application's index.html or main page that consumes the Knockout ViewModel.

The following code examples shows a simple table that is defined with four columns: Priority, Severity, ID, and Owner. The data-bind data property binds the tasks collection to the ViewModel using Knockout.

<table id="taskTable" summary="Task Table"
data-bind="
wijgrid:
{
data: tasks,
allowPaging: true, showColumnHeader: true,
ensurePxWidth: true, pageSize: 10,
pagerSettings: { mode: 'numericFirstLast', pageButtonCount: 5},
columns:
[{dataKey: 'Priority', width: '10%', cellFormatter: priorityCellFormatter},
{dataKey: 'Severity', width: '10%', cellFormatter:severityCellFormatter},
{dataKey: 'ID', width: '6%' }, {dataKey: 'Summary', width: '35%' }, {dataKey: 'Status', width: '12%' },
{dataKey: 'Owner', width: '12%'}, {dataKey: 'Tags', width: '15%'}, {visible: false}, {visible: false}, {visible: false}, {visible: false}, {visible: false}, {visible: false}],
selectionChanged: handleSelectionChanged
}">
</table>

For a complete list of Oracle JET Common Model and Collection API properties and functions, see the oj.Model and oj.Collection API documentation.

Integrating REST Services

The Oracle JET framework is designed to work with any web service that returns data in the form of JSON objects. Because the content of JSON objects can vary widely from service type, the application developer is responsible for examining the content of the JSON object and defining the ViewModel appropriately.

Topics:

- About Oracle JET Framework Support for Integrating REST Services

- Passing Custom AJAX Options in Common Model CRUD API calls

- Supplying a customURL Callback Function

- Replacing oj.sync or oj.ajax Functions

About Oracle JET Framework Support for Integrating REST Services

The Model and Collection classes provide native support for mapping JSON objects obtained from REST web services to Knockout observables. The oj.Collection.url property specifies the path to the web service data.

oj.Collection.extend({url:"http://myserver/departments",...})

Model objects also include the url property. By default, this is set to the model ID appended to the oj.Collection.url property: http://myserver/departments/modelID.

To override the default path set by the Collection object, set the oj.model.urlRoot property, and the application will use the url.Root/modelID as the path to the data.

The Oracle JET framework also provides three ways to customize the AJAX requests that Oracle JET makes when accessing REST services through the Common Model.

- Pass custom AJAX options in Common Model CRUD API calls.

- Supply a customURL callback function.

- Replace the oj.sync or oj.ajax functions.

Passing Custom AJAX Options in Common Model CRUD API calls

Use this method if the default URL behavior is acceptable, but your application needs to pass custom properties such as headers to the REST server.

To customize the AJAX options, add property/value pairs to the options argument of the oj.Collection.create(create), oj.Collection.fetch(read),oj.Model.save(update), and oj.Model.destroy(delete) functions.

The following code example shows how an application could pass in a custom header when doing a read from the REST service.

myOjCollection.fetch(
{headers:{my-custom-header:"header-value"},
beforeSend: myBeforeSendCallbackFunc,
success:function(collection){
}});

Supplying a customURL Callback Function

If you need to customize the URL or AJAX behavior, set the oj.Collection.customURL property to a user-defined callback function when defining the collection.

function myCustomFunction(operation, collection, options) {
...
}
var myCollection = oj.Collection.extend({customURL:myCustomFunction,...})

The callback function should include the following parameters which are passed to it by default:

- operation: create, read, update, patch, or delete

- collection: The oj.Model or oj.Collection object requesting the operation

- options: Information relevant to the operation

Typical options include:

- recordID: Id of the record involved in the operation

- fetchSize: The number of records to return; returns all if not set

- startIndex: Starting record number of the data set

- fromID: Retrieve records starting with the record with the given unique ID

- since: Retrieve records with timestamps after the given timestamp

- until: Retrieve records with timestamps up to the given timestamp

- sort: Field or fields by which to sort

- sortDir: Specific ascending or descending order

The following example shows a customURL callback. By setting this user-created callback function on the Collection's customURL property, the Collection will call out to this function when it needs information to make a REST call.

function myCustomFunction(operation, collection, options) {
// Use the default if operation is create
if (operation === "create") {
return null;
}
if (operation === "delete") {
// Just set a URL if it's delete
return "http://destroy/model='+options['recordID'];
}
var retObj = {};
if (operation === "read") {
retObj['url'] = "http://fetch";
if (options['sort']) {
retObj['url'] += "/order="+options['sort'] + ";" + options['sortDir'];
}
retObj['headers'] = {my-custom-header:"header-value"};
retObj['mimeType'] = "text/plain";
return retObj;
}
// Update or patch
retObj['url'] = "http://update/model="+options['recordID'];
retObj['type'] = "POST";
retObj['beforeSend'] = myBeforeSendCallback;
return retObj;
}

Replacing oj.sync or oj.ajax Functions

You can replace oj.sync() or oj.ajax() when you need to change the entire client-server transport mechanism. For example, this option is best if you want to use WebSockets instead of AJAX calls to the server.

The oj.sync method is the master server access method for all models and collections and accepts the following parameters:

oj.sync = function(method, model, options)

Valid values for the method parameter are the CRUD operations: create, read, update, patch, and delete. The model parameter accepts either the oj.Model being created, read, updated, patched, or deleted, or the oj.Collection being read. Options are passed down from the higher-level common model API call and vary with the type of operation.

The replacement oj.sync() method is completely responsible for implementing all of these operations using whatever transport mechanism is being used, whether it be the application's own AJAX routines, WebSockets, a JavaScript server, or something else. The method must return a Promise object similar to the AJAX XMLHttpRequest (XHR) in order to maintain compatibility with potential virtual API calls being made by the oj.Model and oj.Collection object.

Note:

Replacing oj.sync() replaces the transport mechanism for the JET common model used by all calls within the application. This is a very advanced use of the Oracle JET common model.

The oj.ajax() method is the master AJAX entry point for all oj.Model and oj.Collection server interactions, when they are using the default sync implementations. oj.ajax() passes its parameters and return value through to the jQuery.ajax() method by default. For additional information about the jQuery.ajax() method's expected parameters and return value, see http://api.jquery.com/jquery.ajax.

For additional information about the oj.sync() or oj.ajax() methods, see the Oracle JET oj.sync() and oj.ajax() API documentation.

Creating a CRUD Application Using Oracle JET

Using Knockout and the Oracle JET Common Model API, you can create applications that perform CRUD (Create, Read, Update, Delete) operations on data returned from a REST Service API.

Topics:

- Defining the ViewModel

- Reading Records

- Creating Records

- Updating Records

- Deleting Records

Note:

The application shown in this section also includes code for defining and displaying header and footer detail. You can download the complete sample application here: OracleJET-CommonModel-CRUD.zip.

Defining the ViewModel

Identify the data source for your application and create the ViewModel.

1. Identify your data source and examine the data. For data originating from a REST service, identify the service URL and navigate to it in a browser.

The following example shows a portion of the output of a REST service that returns department data for a fictitious organization from a REST server named RESTServer.

{
"Departments" : [ {
"DepartmentId" : 10,
"DepartmentName" : "Administration",
"ManagerId" : null,
"LocationId" : null,
"version" : "ACED00057...contents truncated",
"links" : {
"self" : {
"rel" : "self",
"href" : "http://RESTServerIP:Port/stable/rest/Departments/10"
},
"canonical" : {
"rel" : "canonical",
"href" : "http://RESTServerIP:Port/stable/rest/Departments/10"
},
"Employees" : {
"rel" : "child",
"href" : "http://RESTServerIP:Port/stable/rest/Departments/10/Employees"
}
}
}, {
"DepartmentId" : 20,
"DepartmentName" : "Retail Marketing",
"ManagerId" : null,
"LocationId" : null,
"version" : "ACED00057...contents truncated",
"links" : {
"self" : {
"rel" : "self",
"href" : "http://RESTServerIP:Port/stable/rest/Departments/20"
},
"canonical" : {
"rel" : "canonical",
"href" : "http://RESTServerIP:Port/stable/rest/Departments/20"
},
"Employees" : {
"rel" : "child",
"href" : "http://RESTServerIP:Port/stable/rest/Departments/20/Employees"
}
}
}, {
... contents omitted
} ],
"links" : {
"self" : {
"rel" : "self",
"href" : "http://RESTServerIP:Port/stable/rest/Departments"
}
},
"_contextInfo" : {
"limit" : 25,
"offset" : 0
}
}

In this example, each department is identified by its DepartmentId and contains information about its name (DepartmentName), manager (ManagerId), and location (LocationId). Each department also contains employees (Employees) which are children of each department.

Tip:
The Oracle JET Common Model CRUD sample application uses JSON data returned from a mock rest service. You can find the mock rest service scripts in the public_html/js/rest folder. You can find the sample JSON data in the departments.json file located in the public_html/js folder.

2. Determine the data you will need for your collection.

For example, the following figure shows a simple Oracle JET table that uses the DepartmentId, DepartmentName, LocationId, and ManagerId returned from the REST service identified in the previous step to display a table of department IDs, names, location IDs, and manager IDs. The table element is defined as an ojTable component, which is included in the Oracle JET UI component library.

3. Add a JavaScript function to your application that will contain your ViewModel.

The following code shows a skeleton function that defines the ViewModel in the Oracle JET Common Model CRUD application. In this example, the function is stored in a file named app.js. The code to complete the ViewModel will be defined in upcoming steps.

define(['ojs/ojcore', 'knockout', 'ojs/ojmodel'],
function(oj, ko)
{
function viewModel() {
// To be defined
};
return {'deptVM': viewModel};
}
)

Note:

This example uses RequireJS for modular development. The RequireJS bootstrap file will be shown in a later step. For additional information about using RequireJS, see Using RequireJS for Modular Development.

4. Add a JavaScript function to the function you defined in the previous step that defines the data model using oj.Model.extend ().

The highlighted code in the example below defines the data model for the application shown in the preceding figure. The Department variable represents a single record in the database and is displayed as a row in the table. Department is declared using the oj.Model.extend function call and instantiated in the declaration for myDept. The urlRoot property defines the data source, which in this case is the REST service URL.

define(['ojs/ojcore', 'knockout', 'ojs/ojmodel'],
function(oj, ko)
{
function viewModel() {
var self = this;
self.serviceURL = 'http://RESTServerIP:Port/stable/rest/Departments';

parseDept = function(response) {
if (response['Departments']) {
var innerResponse = response['Departments'][0];
if (innerResponse.links.Employees == undefined) {
var empHref = '';
} else {
empHref = innerResponse.links.Employees.href;
}
return {DepartmentId: innerResponse['DepartmentId'],
DepartmentName: innerResponse['DepartmentName'],
links: {Employees: {rel: 'child', href: empHref}}};
}
return {DepartmentId: response['DepartmentId'],
DepartmentName: response['DepartmentName'],
LocationId:response['LocationId'],
ManagerId:response['LocationId'],
links: {Employees: {rel: 'child', href: response['links']['Employees'].href}}};
};

// Think of this as a single database record or a single table row.
var Department = oj.Model.extend({
urlRoot: self.serviceURL,
parse: parseDept,
idAttribute: 'DepartmentId'
});

var myDept = new Department();
};

return {'deptVM': viewModel};
};
}

The parse property is an optional user callback function to allow parsing of JavaScript Object Notation (JSON) record objects as they are returned from the data service. In this example, parseDept is the callback function and simply maps the DepartmentId and DepartmentName returned from the REST service to DepartmentId and DepartmentName. If the LocationId or ManagerId records contain data, parseDept maps the attributes to LocationId and ManagerId.

The parse callback can be useful for mapping database attribute names to names that may make more sense. For example, if your database uses Id and Name as the attributes that represent the department ID and department name, you could replace the return call in the parseDept function with:

return {DepartmentId: response['Id'], DepartmentName: response['Name']};

For a complete list of oj.Model properties and functions, see the oj.Model API documentation.

5. Define the collection that will hold the data model object you defined in the previous step using oj.Collection.extend().

The highlighted code in the example below defines the collection object for the Department model object. The DeptCollection variable is declared in the viewModel() function using the oj.Collection.extend function and instantiated in the declaration for self.DeptCol. The url property defines the data source, which in this case is the REST service URL, and limits the collection to 50 records.

define(['ojs/ojcore', 'knockout', 'ojs/ojmodel'],
function(oj, ko){
function viewModel() {
var self = this;
self.serviceURL = 'http://RESTServerIP:Port/stable/rest/Departments';
self.Departments = ko.observableArray([]);
self.DeptCol = ko.observable();
self.datasource = ko.observable();

var parseDept = function(response) {
... contents omitted
};

var Department = oj.Model.extend({
urlRoot: self.serviceURL,
parse: parseDept,
idAttribute: 'DepartmentId'
});

var myDept = new Department();

// this defines our collection and what models it will hold
var DeptCollection = oj.Collection.extend({
url: self.serviceURL + "?limit=50",
model: myDept
});

self.DeptCol(new DeptCollection());
self.datasource(new oj.CollectionTableDataSource(self.DeptCol()));

}
return {'deptVM': viewModel};
}
);

Both the DeptCol and datasource objects are defined as Knockout observables so that changes to the data collection can be handled. The datasource object will contain the column data needed by the ojTable component and is passed the DeptCol observable as a parameter to oj.CollectionTableDataSource().

The Departments object is defined as a Knockout observable array and will be populated in a later step.

For a complete list of oj.Collection properties and functions, see the oj.Collection API documentation.

6. Populate the collection with data by calling oj.Collection.fetch() to read the data from the data service URL.

The highlighted code in the code sample below calls oj.collection.fetch() to add data to the DeptCol data collection and complete the ViewModel.

define(['ojs/ojcore', 'knockout', 'ojs/ojmodel'],        function(oj, ko)        {
function viewModel() {
var self = this;
self.serviceURL = 'http://RESTServerIP:Port/stable/rest/Departments';
self.Departments = ko.observableArray([]);
self.DeptCol = ko.observable();
self.datasource = ko.observable();
self.fetch = function(successCallBack) {
self.DeptCol().fetch({
success: successCallBack,
error: function(jqXHR, textStatus, errorThrown){
console.log('Error in fetch: ' + textStatus);
}
});
}

var parseDept = function(response) {
... contents omitted
};

var Department = oj.Model.extend({
urlRoot: self.serviceURL,
parse: parseDept,
idAttribute: 'DepartmentId'
});

var myDept = new Department();

var DeptCollection = oj.Collection.extend({
url: self.serviceURL + "?limit=50",
model: myDept
});

self.DeptCol(new DeptCollection());
self.datasource(new oj.CollectionTableDataSource(self.DeptCol()));

}
return {'deptVM': viewModel};
}
);

The fetch() function also defines an error callback that will log a message to the console if the fetch() call fails.

7. Add the ViewModel or the file containing the name of your ViewModel to your RequireJS bootstrap file, typically main.js.

If you created your Oracle JET application using an Oracle JET QuickStart template or modified your Oracle JET download as described in Using RequireJS to Manage Library, Link, and Script References, you should already have a main.js file. Locate the line that defines the require modules and add your file to the top of the list.

For example, the code below lists the modules defined for the Common Model Sample. The application stores its ViewModel in the app.js file. The reference to the app.js file is highlighted in bold.

require(['ojs/ojcore',
'knockout',
'jquery',
'app',
'footer',
'ojs/ojmodel',
'ojs/ojknockout',
'ojs/ojknockout-model',
'ojs/ojdialog',
'ojs/ojinputtext',
'ojs/ojinputnumber',
'ojs/ojbutton',
'ojs/ojtable',
'ojs/ojdatacollection-common'],

You must also add the app reference in the callback definition as shown in the following example.

// this callback gets executed when all required modules are loaded
function(ko, $, oj, app, footer)
{
...
}

8. Update your RequireJS bootstrap file to instantiate the ViewModel, create the Knockout bindings, and display the content on the page.

The highlighted code in the code sample below creates a Knockout observable for each element in the deptData collection and assigns the resulting array to the Departments Knockout observable array you defined in a previous step.

require(['ojs/ojcore',
'knockout',
'jquery',
'app',
'footer',
'ojs/ojmodel',
'ojs/ojknockout',
'ojs/ojknockout-model',
'ojs/ojdialog',
'ojs/ojinputtext',
'ojs/ojinputnumber',
'ojs/ojbutton',
'ojs/ojtable',
'ojs/ojdatacollection-common'],
function(ko, $, oj, app, footer) // this callback gets executed when all required modules are loaded
{
var fvm = new footer.footerVM();
$(document).ready(function(){
var vm = new app.deptVM();
ko.applyBindings(fvm, document.getElementById('footerContent'));
vm.fetch(
function(collection, response, options){
var deptData = collection;
// This will create a ko.observable() for each element
// in the deptData response and assign the resulting array
// to the Departments ko observeableArray.
vm.Departments = oj.KnockoutUtils.map(deptData, null, true);
//perform a Knockout applyBindings() call binding this
// viewModel with the current DOM
ko.applyBindings(vm, document.getElementById('mainContent'));
//Show the content div after the REST call is completed.
$('#mainContent').show();
});
});
}
);

Reading Records

To read the records, define the elements that will read the records in your main HTML5 page and use Knockout to bind the elements to the data collection.

The following sample code shows a portion of the index.html file that displays a table of records using the ViewModel defined in the previous steps and the ojTable component. In this example, the mainContent div includes the table definition that creates Department Id, Department Name, Location Id, and Manager Id as the table header text and defines the content for each row.

<div id="mainContent" class="oj-md-12 oj-col page-padding" style="display: none;">
<div class="demo-page-content-area page-padding">
<table id="table"
summary="Demo Table"
data-bind="ojComponent:{component:'ojTable',
data: datasource,
columns: [
{headerText: 'Department Id', field: 'DepartmentId', id: 'column1', sortable: 'enabled'},
{headerText: 'Department Name', field: 'DepartmentName', id: 'column2', sortable: 'enabled'},
{headerText: 'Location Id', field: 'LocationId', id: 'column3'},
{headerText: 'Manager Id', field: 'ManagerId', id: 'column4'},
]}">
</table>
</div>
</div>

Knockout's data-bind utility binds the data retrieved from the REST service to the table elements.

Creating Records

To add the ability to create new records, add elements to your HTML5 page that accept input from the user and create a function that sends the new record to the REST server.

The figure below shows the result of adding the Form component to the Oracle Jet Common Model Sample application. The user can enter a new department number in the provided field or use the side arrows to increment or decrement the value. The user then enters the name and clicks Add.

To add the ability to create new records to the application's ViewModel and HTML5 page:

1. Add elements to the application's main page that accept input from the user.

The highlighted code in the example below adds the form element to the index.html page shown in the previous task.

<div id="mainContent" class="oj-md-12 oj-col demo-page-content-area page-padding" style="display: none;">
<div class="page-padding">
<div id="deptList" class="oj-md-9 oj-col">
<table id="table" summary="Demo Table"
... contents omitted
</table>
<br/>
</div>
<div id="addDept" class="oj-md-3 oj-col right">
<div id="quickUpdate" class="frame">
<div id="newDeptForm">
<form class="oj-form oj-md-odd-cols-6 oj-md-labels-inline" data-bind="submit: addDepartment">
<h3>New Department</h3><hr/>
<div class="oj-row">
<div class="oj-col">
<label for="newDepartId" class="oj-label">Department Id</label>
</div>
<div class="oj-col">
<input id="newDepartId" value="555" class="oj-text-input" data-bind="ojComponent:{component:'ojInputNumber'}" />
</div>
</div>
<div class="oj-row">
<div class="oj-col">
<label for="newDepartName" class="oj-label">Department Name</label>
</div>
<div class="oj-col">
<input id="newDepartName" maxlength='30'
placeholder="enter new name" data-bind="ojComponent:{component:'ojInputText'}"/>
<button id="saveBtn" class="oj-button"
type="submit" data-bind="ojComponent:{component:'ojButton', label: 'Add Department'}">
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>

The form is defined to contain two input fields: an ojInputNumber for the department ID, and an ojInputText for the department name. The ojButton component is used for the form's button.

The form's submit action is bound to the addDepartment function which is defined in the next step.

2. Add code to the ViewModel to add the user's input as a new record (model) in the data collection.

The highlighted code in the example below shows the addDepartment() function that adds the new department number and department name to the DeptCol data collection. In this example, the function calls the oj.Collection.create() method which creates the new model instance, adds it to the data collection, and saves the new DepartmentId and DepartmentName to the data service.

define(['ojs/ojcore', 'knockout', 'ojs/ojmodel'],
function(oj, ko)        {
function viewModel() {
var self = this;
self.serviceURL = 'http://RESTServerIP:Port/stable/rest/Departments';
self.Departments = ko.observableArray([]);
self.DeptCol = ko.observable();
self.datasource = ko.observable();
self.fetch = function(successCallBack) {
... contents omitted
};

function parseDept(response){
... contents omitted
};

var Department = oj.Model.extend({
urlRoot: self.serviceURL,
parse: parseDept,
parseSave:parseSaveDept,
idAttribute: 'DepartmentId'
});

var myDept = new Department();

var DeptCollection = oj.Collection.extend({
url: self.serviceURL + "?limit=50",
model: myDept
comparator: 'DepartmentId'
});

self.DeptCol(new DeptCollection());
self.datasource(new oj.CollectionTableDataSource(self.DeptCol()));

function parseSaveDept(response){
return {Departments: [{DepartmentId: response['DepartmentId'],
DepartmentName: response['DepartmentName'],
LocationId:response['LocationId'],
ManagerId:response['LocationId'],
links: {Employees: {rel: 'child', href: response['links']['Employees'].href}}}]};
};

self.addDepartment = function(formElement, event){
var recordAttrs = {DepartmentId: formElement.elements[0].value,
DepartmentName: formElement.elements[1].value,
ManagerId: "", LocationId: "",
links: {Employees: {rel: 'child', href: 'http://RESTServerIP:Port/stable/rest/Departments/' + formElement.elements[0].value + '/Employees'}}};
this.DeptCol().create(recordAttrs,{
'contentType': 'application/vnd.oracle.adf.resource+json',
error: function(jqXHR, textStatus, errorThrown){
console.log('Error in Create: ' + textStatus);
}
});
}
}
return {'deptVM': viewModel};
}
);

The oj.Collection.create() function accepts options to control the record save. In this example, simple error checking is added. In addition, the create() function sends a contentType to the REST server. Depending upon the REST service you are using, this option may not be required or may need modification.

Updating Records

To add the ability to update records, add elements to your HTML5 page that accept input from the user and create a function that sends the updated record to the REST server.

The figure below shows the Oracle JET Common Model Sample application configured to allow updates to the department name. When the user moves the focus over a department name, a tooltip appears that prompts the user to click to edit. department name, a tooltip prompts the user to click to edit. If the user clicks the department name, a dialog appears that enables the user to change the name. The user can type in a new department name and click Change to update the record or Cancel to keep the existing department name.

To add the ability to update records to the application's ViewModel and HTML5 page:

1. Add elements to the application's main page that identifies updatable elements and enables the user to perform an action to update them.

The highlighted code in the example below adds the ojDialog component to the page and provides the prompt to the user to click to edit the page.

<div id="mainContent" class="oj-md-12 oj-col page-padding" style="display: none;">
<div class="demo-page-content-area page-padding">
<table id="table"
summary="Demo Table"
data-bind="ojComponent:{component:'ojTable',
data: datasource,
selectionMode: {row: 'none', column:'none'},
columns: [
{headerText: 'Department Id', field: 'DepartmentId', id: 'column2', sortable: 'enabled'},
{headerText: 'Department Name', field: 'DepartmentName', id: 'column3', sortable: 'enabled'},
{headerText: 'Location Id', field: 'LocationId', id: 'column3'},
{headerText: 'Manager Id', field: 'ManagerId', id: 'column4'}
],
rowTemplate: {template: 'row_tmpl'}}">
</table>
</div>
<div id="editDialog" title="Change Department Name"
data-bind="ojComponent:{component: 'ojDialog', initialVisibility: 'hide', resizeBehavior: 'none', dragAffordance: 'title-bar', modality: 'modeless'}">
<form class="oj-form " data-bind="submit: updateDeptName">
<div class="oj-dialog-header oj-helper-clearfix" aria-labelledby="dialog-title-id">
<div>
<span id="infoIcon" class="oj-icon oj-message-info-icon" style="float:left;"></span>
<span id="dialog-title-id" class="oj-dialog-title">Change Department Name</span>
<a href="#"><span  title="click to close dialog"  role="img" class="oj-clickable-icon oj-fwk-icon oj-fwk-icon-cross" style="float:right;" data-bind="click: function(){$('#editDialog').ojDialog('close');}"></span></a>
</div>
</div>
<div class="oj-dialog-body">
<div class="oj-md-odd-cols-4">
<label for="newName" class="oj-label oj-label-inline">Department Name</label>
<input id="newName" type="text" data-bind="ojComponent: {component:'ojInputText', value: currentDeptName()}">
</div>
</div>
<div class="oj-dialog-footer">
<button id="submitBtn" type="submit" data-bind="ojComponent: {component:'ojButton', label: 'Change'}"></button>
<button id="resetBtn" data-bind="ojComponent: {component: 'ojButton', label: 'Cancel'}, click: function(){$('#editDialog').ojDialog('close');}"></button>
</div>
</form>
</div>
</div>
<script type="text/html" id="row_tmpl">
<tr>
<td><span id='deptId' data-bind="text: DepartmentId"></span></td>
<td><div id="deptName" title='Click to edit' data-bind="text: DepartmentName, click: function(data, event){$root.showChangeNameDialog(DepartmentId,data,event)}"></div></td>
<td><div id="locId" data-bind="text: LocationId"></div></td>
<td><div id="mgrId" data-bind="text: ManagerId"></div></td>
</tr>
</script>

The ojDialog component includes the oj-dialog-header, oj-dialog-body, and oj-dialog-footer formatting classes. The oj-dialog-header class is optional and is used in this example to format the Info icon, title, and Close icon.

The oj-dialog-body class formats the dialog body which includes the Department Name label and an ojInputText component to capture the user's input. The footer defines two ojButton components which add the Change and Cancel buttons to the dialog. When the user clicks Change, the updateDepartmentName() function handles the updates to the record.

The original table is also modified to define the rowTemplate property which specifies the row_tmpl template to use for the row display. The template script adds the tooltip (Click to Edit) and calls the showChangeNameDialog() function to display the dialog.

The updateDepartmentName() and showChangeNameDialog() functions are defined in the next step. For additional information about the ojDialog component, see the ojDialog API documentation.

2. Add code to the ViewModel to update the record.

The highlighted code in the example below shows the updateDepartment() and showChangeNameDialog() functions.

define(['ojs/ojcore', 'knockout', 'ojs/ojmodel'],
function(oj, ko)        {
function viewModel() {
var self = this;
self.serviceURL = 'http://RESTServerIP:Port/stable/rest/Departments';
self.Departments = ko.observableArray([]);
self.currentDeptName = ko.observable('default');
self.workingId = ko.observable('');
self.DeptCol = ko.observable();
self.datasource = ko.observable();
self.fetch = function(successCallBack) {
... contents omitted
};

function parseDept(response){
... contents omitted
}

var Department = oj.Model.extend({
urlRoot: self.serviceURL,
parse: parseDept,
parseSave:parseSaveDept,
idAttribute: 'DepartmentId'
});

var myDept = new Department();

var DeptCollection = oj.Collection.extend({
url: self.serviceURL + "?limit=50",
model: myDept
comparator: 'DepartmentId'
});

self.DeptCol(new DeptCollection());
self.datasource(new oj.CollectionTableDataSource(self.DeptCol()));

self.showChangeNameDialog = function(deptId, data, event) {
var currName = data.DepartmentName;
self.workingId(deptId);
self.currentDeptName(currName);
$('#editDialog').ojDialog('open');
}

self.updateDeptName = function(formData, event) {
var currentId = self.workingId();
var newName = formData.elements[0].value;
if (newName != self.currentDeptName() && newName != '') {
var myCollection = self.DeptCol();
var myModel = myCollection.get(currentId);
myModel.save({'DepartmentName': newName}, {
contentType: 'application/vnd.oracle.adf.resource+json',
success: function(myModel, response, options) {
$('#editDialog').ojDialog('close');
},
error: function(jqXHR, textStatus, errorThrown) {
alert("Update failed with: " + textStatus);
$('#editDialog').ojDialog('close');
}
});
} else {
alert('Department Name is not different or the new name is not valid');
$('#editDialog').ojDialog('close');
}
}

function parseSaveDept(response){
... contents omitted
}

}
return {'deptVM': viewModel};
}
);

The showChangeNameDialog() function stores the selected department detail and opens the dialog with the existing department name shown in the ojInputText field.

The updateDepartment() function calls the oj.Model.save() method to save the current Model object to the data source. The function also defines success and error callbacks to close the dialog upon success or issue an error message if the record was not updated.

Deleting Records

To add the ability to delete records, add elements to your HTML5 page that accept input from the user and create a function that sends the new record for deletion to the REST server.

The figure below shows the Oracle Jet Common Model CRUD application configured to allow record deletion. The user can check one or more departments in the list and click Remove Department to delete the record or records.

To add the ability to delete records to the application's ViewModel and HTML5 page:

1. Add elements to the application's main page that identifies records marked for deletion and enables the user to perform an action to delete them.

The highlighted code in the example below adds the Remove column with a check box to the department list and adds the Remove Department button below the list.

<div id="mainContent" class="oj-md-12 oj-col page-padding" style="display: none;">
<div class="demo-page-content-area page-padding">
<table id="table"
summary="Demo Table"
data-bind="ojComponent:{component:'ojTable',
data: datasource,
selectionMode: {row: 'none', column:'none'},
columns: [
{headerText: 'Remove', id: 'column1', sortable: 'disabled'},
{headerText: 'Department Id', field: 'DepartmentId', id: 'column2', sortable: 'enabled'},
{headerText: 'Department Name', field: 'DepartmentName', id: 'column3', sortable: 'enabled'},
{headerText: 'Location Id', field: 'LocationId', id: 'column3'},
{headerText: 'Manager Id', field: 'ManagerId', id: 'column4'}
],
rowTemplate: {template: 'row_tmpl'}}">
</table>
<br/><br/>
<button id="deleteDept_btn"
data-bind="enable: somethingChecked, click: deleteDepartment">Remove Department
</button>
</div>
</div>

<script type="text/html" id="row_tmpl">
<tr>
<td><input type="checkbox" data-bind="attr: {id: DepartmentId}, click: $root.enableDelete"/></td>
<td><div id='deptId' data-bind="text: DepartmentId"></div></td>
<td><div id="deptName" data-bind="text: DepartmentName"></div></td>
<td><div id="locId" data-bind="text: LocationId"></div></td>
<td><div id="mgrId" data-bind="text: ManagerId"></div></td>
</tr>
</script>

The original table is modified to include the Remove column. The rowTemplate property specifies the row_tmpl template to use for the row display. The template script adds the checkbox input element to the first column and the value of DepartmentId, DepartmentName, and LocationId to the remaining columns.

The button's click action is bound to the deleteDepartment function which is created in the next step.

2. Add code to the ViewModel to delete the record or records submitted by the user.

The highlighted code in the example below shows the deleteDepartment() function. In this example, the function calls the oj.Collection.remove() method which removes the model or models from the data collection. To delete the record from the data source, the function calls the oj.Model.destroy() method.

define(['ojs/ojcore', 'knockout', 'ojs/ojmodel'],
function(oj, ko)         {
function viewModel() {
var self = this;
self.serviceURL = 'http://RESTServerIP:Port/stable/rest/Departments';
self.Departments = ko.observableArray([]);
self.DeptCol = ko.observable();
self.datasource = ko.observable();
self.somethingChecked = ko.observable(false);
self.fetch = function(successCallBack) {
... contents omitted
}

var Department = oj.Model.extend({
urlRoot: self.serviceURL,
idAttribute: 'DepartmentId'
});

var myDept = new Department();

var DeptCollection = oj.Collection.extend({
url: self.serviceURL + "?limit=50",
model: myDept
comparator: 'DepartmentId'
});

self.DeptCol(new DeptCollection());
self.datasource(new oj.CollectionTableDataSource(self.DeptCol()));

self.enableDelete = function() {
if (!$('input[type=checkbox]:checked').length) {
self.somethingChecked(false);
} else {
self.somethingChecked(true);
}
return true;
}

self.deleteDepartment = function(data, event) {
var deptIds = [];
deptIds = self.findDeptIds();
var collection = data.DeptCol();
deptIds.forEach(function(value, index, arr) {
var model = collection.get(parseInt(value));
if (model) {
collection.remove(model);
model.destroy();
}
});
self.enableDelete();
$('#table').ojTable('refresh');
}

self.findDeptIds = function() {
var selectedIdsArray = [];
$("input:checkbox").each(function() {
var $this = $(this);
if ($this.is(":checked")) {
selectedIdsArray.push($this.attr("id"));
}
});
return selectedIdsArray;
}
}
return {'deptVM': viewModel};
}
);

The deleteDepartment() function calls the findDeptIds() function which returns the list of selected departments marked for deletion. The enableDelete() function resets the check box after the department list is deleted.

8 Validating and Converting Input

The Oracle JET framework includes validators and converters on the Oracle JET editable components. Editable components include ojCheckboxSet, ojComboxbox, ojInput*, ojRadioSet, ojSelect, and ojTextArea, and you can use them as is or customize them for validating and converting input in your Oracle JET application.

Topics:

- Typical Workflow for Validating and Converting Input

- About Oracle JET Validators and Converters

- Using Oracle JET Converters

- Using Oracle JET Validators

Typical Workflow for Validating and Converting Input

To validate and convert input in Oracle JET, refer to the typical workflow described in the following table:

Task

Description

More Information

Understand Oracle JET's validation and conversion framework

Understand the validators and converters included in Oracle JET and identify when you might need a custom validator or converter.

About Oracle JET Validators and Converters

Use Oracle JET converters in your application

Use oj.IntlNumberConverter and oj.IntlDateTimeConverter to convert number and date-time inputs to values expected by the view model.

Using Oracle JET Converters

Use a custom converter in your Oracle JET application

How to reference a custom converter in an Oracle JET application.

Using Custom Converters in Oracle JET

Use Oracle JET validators in your application

Use oj.DateTimeRangeValidator, oj.DateRestrictionValidator, oj.LengthValidator, oj.NumberRangeValidator, oj.RegExpValidator, oj.RequiredValidator to validate user input.

Using Oracle JET Validators

Use a custom validator in your Oracle JET application

How to reference a custom validator in an Oracle JET application.

Using Custom Validators in Oracle JET

About Oracle JET Validators and Converters

The Oracle JET framework provides converter classes that convert user input strings into the data type expected by the application and validator classes that enforce a validation rule on those input strings. For example, you can use Oracle JET's oj.IntlDateTimeConverter to convert a user-entered date to a Date object for use by the application's ViewModel and then use oj.DateTimeRangeValidator to validate that input against a specified time range. You can also use converters to convert Date or Number objects to a string suitable for display.

To make it easier to create an Oracle JET converter or validator, the Oracle JET framework provides a factory for each converter and validator. For example, to create an instance of an oj.IntlDateTimeConverter, use oj.IntlDateTimeConverterFactory and call its createConverter() method.

To retrieve the converter or validator factory for a registered type, Oracle JET provides the oj.Validation class which includes methods to register and retrieve converter and validator factories.

If the converters or validators included in the Oracle JET framework are not sufficient for your application, you can create custom converters or validators. Optionally, you can provide a custom factory that implements the contract for a converter using oj.ConverterFactory or a validator using oj.ValidatorFactory and register the converter or validator with the oj.Validation class. The oj.Validation class enables you to access your custom converter or validator using the same mechanisms as you would use with the Oracle JET standard converters and validators.

Topics:

- About Validators

- About Converters

About Validators

All Oracle JET editable components support a value option and provide UI elements that allow the user to enter or choose a value. These components also support other options that page authors can set that instruct the component how it should validate its value.

An editable component may implicitly create a built-in converter and/or built-in validators for its normal functioning when certain options are set.

For example, editable components that support a required option create the required validator implicitly when the option is set to true. Other components like ojInputDate, ojInputDateTime, and ojInputTime create a datetime converter to implement its basic functionality.

Topics

- Oracle JET Validators

- Oracle JET Component Validation Options

- Oracle JET Component Validation Methods

Oracle JET Validators

The following table describes the Oracle JET validators and provides links to the API documentation:

Validator

Description

Link to API

oj.DateTimeRangeValidator

Validates that the input date is between two dates, between two times, or within two date and time ranges

oj.DateTimeRangeValidator

oj.DateRestrictionValidator

Validates that the input date is not a restricted date

oj.DateRestrictionValidator

oj.LengthValidator

Validates that an input string is within a specified length

oj.LengthValidator

oj.NumberRangeValidator

Validates that an input number is within a specified range

oj.NumberRangeValidator

oj.RegExpValidator

Validates that the regular expression matches a specified pattern

oj.RegExpValidator

oj.RequiredValidator

Validates that a required entry exists

oj.RequiredValidator

Oracle JET Component Validation Options

The options that a component supports is part of its API, and the following validation specific options apply to most editable components.

Component Option

HTML5 Attribute

Description

converter

When specified, the converter instance is used over any internal converter the component might create. On components such as ojInputText, you may need to specify this option if the value must be processed to and from a number or a date value.

max

max

When specified on the HTML element or as an option on an Oracle JET component like ojInputDate or ojInputNumber, the component creates an implicit range validator.

min

min

When specified on the HTML element or as an option of an Oracle JET component like ojInputDate or ojInputNumber, the component creates an implicit range validator.

pattern

pattern

When specified on the HTML element or as an option on an Oracle JET component like ojInputText, ojInputPassword, or ojTextarea, the component creates an implicit regExp validator using the pattern specified.

placeholder

placeholder

When specified on the HTML element or as an option on an Oracle JET component, it displays a placeholder in most components.

required

required

When specified on the HTML element or as an option on an Oracle JET component, the component creates an implicit required validator.

validators

When specified, the component uses these validators along with the implicit validators to validate the UI value.

Some editable components do not support specific validation options as they might be irrelevant to its intrinsic functioning. For example, ojRadioset and ojCheckboxset do not support a converter option since there is nothing for the converter to convert. For an exact list of options and how to use them, refer to the Options section in the component's API documentation. For Oracle JET API documentation, see JavaScript API Reference for Oracle�� JavaScript Extension Toolkit (JET). Select the component you're interested in viewing from the API list.

Note:

When the element that the Oracle JET component is initialized from also has HTML5 validation attributes, then these often drive the initial value of the corresponding option on the component if the option is not already present.

Oracle JET Component Validation Methods

Oracle JET editable components support the following methods for validation purposes. For details on how to call this method, its parameters and return values, refer to the component���s API documentation for details.

Component Method

Description

isValid()

Use this method to detect the current validity state of a component. The method returns the boolean true if it's valid and false if it's invalid.

refresh()

Use this method when the DOM the component relies on changes, such as the label associated to the input component.

reset()

Use this method to reset the component's display value to reflect its stored option value.

validate()

Use this method to validate the component using the current display value.

For details on calling a component���s method, parameters, and return values, See the Methods section of the component's API documentation in JavaScript API Reference for Oracle�� JavaScript Extension Toolkit (JET). You can also find detail on how to register a callback for or bind to the event and for information about what triggers the events. Select the component you're interested in viewing from the API list.

About Converters

The Oracle JET converters include date and number converters and are described in the following table.

Converter

Description

Link to API

oj.IntlDateTimeConverter

Converts a string to a Date or a Date to a string

oj.IntlDateTimeConverter

oj.IntlNumberConverter

Converts a string to a number or formats a number or Number object value to a string

oj.IntlNumberConverter

Note:
Oracle JET does not support input and output of a date-time value in a time zone other than the local time. As a result, the Oracle JET framework can���t parse the ISO string returned by such JavaScript functions as toISOString().

Using Oracle JET Converters

The Oracle JET date-time and number converters, oj.IntlDateTimeConverter and oj.IntlNumberConverter, extend the oj.Converter object which defines a basic contract for converter implementations.

The converter API is based on the ECMAScript Internationalization API specification (ECMA-402 Edition 1.0) and uses the Unicode Common Locale Data Repository (CLDR) for its locale data. Both converters are initialized through their constructors, which accept options defined by the API specification. For additional information about the ECMA-402 API specification, see http://www.ecma-international.org/ecma-402/1.0. For information about the Unicode CLDR, see http://cldr.unicode.org.

The Oracle JET implementation extends the ECMA-402 specification by introducing additional options, including an option for user-defined patterns. For the list of additional options, see the oj.IntlDateTimeConverter and oj.IntlNumberConverter API documentation.

For examples that illustrate the converters in action, see the Converters section in the Oracle JET Cookbook.

Note:

The bundles that hold the locale symbols and data used by the Oracle JET converters are downloaded automatically based on the locale set on the page when using RequireJS and the ojs/ojvalidation module. If your application does not use RequireJS, the locale data will not be downloaded automatically.

You can use the converters with an Oracle JET component or instantiate and use them directly on the page.

Topics:

- Using Oracle JET Converters with Oracle JET Components

- Understanding Oracle JET Converters Lenient Parsing

- Using Custom Converters in Oracle JET

- Using Oracle JET Converters Without Oracle JET Components

Using Oracle JET Converters with Oracle JET Components

Oracle JET components that accept user input, such as ojInputDate, already include an implicit converter that is used when parsing user input. However, you can also specify an explicit converter on the component which will be used instead when converting data from the model for display on the page and vice versa.

For example, the following code sample shows a portion of a form containing an ojInputDate component that uses the default converter supplied by the component implicitly. The highlighted code shows the binding for the ojInputDate component.

<div id="builtin-example">
... contents omitted
<div class="oj-row">
<div class="oj-col">
<label for="date1">default</label>
</div>
<div class="oj-col">
<input id="date1" type="text" name="date1"
title="Enter a date in your preferred format, and we will attempt to figure it out."
data-bind="ojComponent:{component: 'ojInputDate' value: date,
datePicker: {changeMonth: 'none', changeYear: 'none'}}"/>
</div>
</div>
... contents omitted
</div>

The script to create the view model for this example is shown below.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'ojs/ojdatetimepicker'],
function(oj, ko, $)
{
function MemberViewModel()
{
var self = this;
self.date = ko.observable();
};

$(document).ready(
function()
{
ko.applyBindings(new MemberViewModel(), document.getElementById('builtin-example'));
}
);
});

When the user runs the page, the ojInputDate component displays an input field with the expected date format. In this example, the component also displays a hint when the user clicks in the input field. If the user inputs data that is not in the expected format, the built-in converter displays an error message with the expected format.

The error that the converter throws when there are errors during parsing or formatting operations is represented by the oj.ConverterError object, and the error message is represented by the oj.Message object. The messages that Oracle JET converters use are resources that are defined in the translation bundle included with Oracle JET. For more information about messaging in Oracle JET, see Working with User Assistance.

You can also specify the converter directly on the component's converter property, if it exists. The code excerpt below defines another ojInputDate component on the sample form and specifies the oj.IntlDateTimeConverter converter with options that will convert the user's input to a numeric year, long month, and numeric day according to the conventions of the locale set on the page. The options parameter is an object literal that contains the ECMA-402 options as name-value pairs.

<div class="oj-col">
<input id="date2" type="text" name="date2"
title="Enter a date in your preferred format, and we will attempt to figure it out"
data-bind="ojComponent:{component:'ojInputDate', value: date,
datePicker: {changeMonth: 'none', changeYear: 'none'},
converter: {type:'datetime', options: {year: 'numeric', month: 'long', day: 'numeric'}}}"/>
</div>

When the user runs the page in the en-us locale, the ojInputDate component displays an input field that expects the user's input date to be in the mmmm d, yyyy format. The converter will accept alternate input if it makes sense, such as 12/15/22 (MM/dd/yy), and perform the conversion, but will throw an error if it cannot parse the input. For details about Oracle JET converters and lenient parsing support, see Understanding Oracle JET Converters Lenient Parsing.

Parsing of narrow era, weekday, or month name is not supported because of ambiguity in choosing the right value. For example, if you initialize the date time converter with options {weekday: 'narrow', month: 'narrow', day: 'numeric', year: 'numeric'}, then for the en-US locale, the converter will format the date representing May 06, 2014 as T, M 6, 2014, where T represents Tuesday. If the user inputs T, M 6, 2014, the converter can't determine whether the user meant Thursday, March 6, 2014 or Tuesday, May 6, 2014. Therefore, Oracle JET expects that user inputs be provided in either their short or long forms, such as Sat, March 02, 2013.

For additional detail about the oj.IntlDateTimeConverter and oj.IntlNumberConverter component options, see oj.IntlDateTimeConverter and oj.IntlNumberConverter.

Understanding Oracle JET Converters Lenient Parsing

The Oracle JET converters support lenient number and date parsing when the user input does not exactly match the expected pattern. The parser does the lenient parsing based on the leniency rules for the specific converter.

oj.IntlDateTimeConverter provides parser leniency when converting user input to a date and enables the user to:

- Input any character as a separator irrespective of the separator specified in the associated pattern. For example, if the expected date pattern is set to y-M-d, the date converter will accept the following values as valid: 2013-11-16, 2013/11-16, and 2013aaa11xxx16. Similarly, if the expected time pattern is set to mm:ss:SS:, the converter will accept the following values as valid: 11.24.376.

- Specify a 4-digit year in any position relative to day and month. For example, both 11-2013-16 and 16-11-2013 are valid input values.

- Swap month and day positions, as long as the date value is greater than 12 when working with the Gregorian calendar. For example, if the user enters 2013-16-11 when y-M-d is expected, the converter will autocorrect the date to 2013-11-16. However, if both date and month are less or equal to 12, no assumptions are made about the day or month, and the converter parses the value against the exact pattern.

- Enter weekday and month names or mix short and long names anywhere in the string. For example, if the expected pattern is E, MMM, d, y, the user can enter any of the following dates:

Tue, Nov 26 2013
Nov, Tue 2013 26
2013 Tue 26 Nov

- Omit weekdays. For example, if the expected pattern is E, MMM d, y, then the user can enter Nov 26, 2013, and the converter autocorrects the date to Tuesday, Nov 26, 2013. Invalid weekdays are not supported. For instance, the converter will throw an exception if the user enters Wednesday, Nov 26, 2013.

oj.IntlNumberConverter supports parser leniency as follows:

- If the input does not match the expected pattern, Oracle JET attempts to locate a number pattern within the input string. For instance, if the pattern is #,##0.0, then the input string abc-123.45de will be parsed as -123.45.

- For the currency style, the currency symbol can be omitted. Also, the negative sign can be used instead of a negative prefix and suffix. As an example, if the pattern option is specified as "\u00a4#,##0.00;(\u00a4#,##0.00)", then ($123), (123), and -123 will be parsed as -123.

- When the style is percent, the percent sign can be omitted. For example, 5% and 5 will both be parsed as 0.05.

Using Custom Converters in Oracle JET

You can create custom converters in Oracle JET by extending oj.Converter or by duck typing it. You can also create a custom converter factory to register the converter with Oracle JET and make it easier to instantiate the converter.

Custom converters can be used with Oracle JET components, provided they don't violate the integrity of the component. As with the built-in Oracle JET converters, you can also use them directly on the page.

The figure below shows an example of a custom converter used to convert the current date to a relative term. The Schedule For column uses a RelativeDateTimeConverter to convert the date that the page is run in the en-US locale to display Today, Tomorrow, and the following date.

To create and use a custom converter in Oracle JET:

1. Define the custom converter.

The code sample below shows a portion of the RelativeDateTimeConverter definition. The converter wraps the Oracle JET IntlDateTimeConverter by providing a specialized format() method that turns dates close to the current date into relative terms for display. For example, in the en-US locale, the relative terms will display Today, Yesterday, and Tomorrow. If a relative notation for the date value does not exist, then the date is formatted using the regular Oracle JET format() method supported by the Oracle JET IntlDateTimeConverter.

function RelativeDateTimeConverter(options) {
this.Init(options);
};

RelativeDateTimeConverter._DEFAULT_RELATIVE_DATETIME_CONVERTER_OPTIONS =
{
'formatUsing' : "displayName",
'dateField' : "relativeField"
};

// Subclass from oj.Object
oj.Object.createSubclass(RelativeDateTimeConverter, oj.Converter, "RelativeDateTimeConverter");

// Initializes converter instance with the set options
RelativeDateTimeConverter.prototype.Init = function(options)
{
RelativeDateTimeConverter.superclass.Init.call(this);
this._options = options;
var cf = oj.Validation.converterFactory(oj.ConverterFactory.CONVERTER_TYPE_DATETIME);
this._wrappedConverter = cf.createConverter(options);
};

// Returns the options set on the converter instanceRelativeDateTimeConverter.prototype.getOptions = function()
{
return this._options;
};

// Does not support parsing
RelativeDateTimeConverter.prototype.parse = function(value)
{
return null;
};

// Formats a value using the relative format options. Returns the formatted
// value and a title that is the actual date, if formatted value is a relative date.
RelativeDateTimeConverter.prototype.format = function(value)
{  var formatted, base;
formatted = this._getWrapped().formatRelative(value, this._getRelativeOptions());
base = this.formatRegular(value);
if (formatted &amp;&amp; typeof formatted === "string")
{
formatted = formatted.replace(/(\w)(\w*)/g, function (_, i, r) {
return i.toUpperCase() + (r !== null ? r : "");
});
}
return {value: formatted || base, title: formatted ? base : ""}
};
// formats using the base datetime converterRelativeDateTimeConverter.prototype.formatRegular = function(value)
{
// value does not have a relative display; use regular date
return this._getWrapped().format(value);
};

// Returns a hint
RelativeDateTimeConverter.prototype.getHint = function ()
{
return "";
};

RelativeDateTimeConverter.prototype._getWrapped = function ()
{
return this._wrappedConverter;
};

RelativeDateTimeConverter.prototype._getRelativeOptions = function ()
{  var i, options = this._options, relativeOptions = {};
if (options &amp;&amp; options["relativeField"])
{
relativeOptions['formatUsing'] = "displayName";
relativeOptions['dateField'] = options["relativeField"];
}

else
{    relativeOptions = RelativeDateTimeConverter._DEFAULT_RELATIVE_DATETIME_CONVERTER_OPTIONS;
}

return relativeOptions;
};

The custom converter relies on the IntlDateTimeConverter converter's formatRelative() method. For additional detail about the IntlDateTimeConverter converter's supported methods, see the oj.IntlDateTimeConverter API documentation.

2. Optionally, create a converter factory for the custom converter that supports a createConverter() method, meeting the contract defined by oj.ConverterFactory.

The following code sample shows a simple converter factory for the RelativeDateTimeConverter. The code also registers the factory with Oracle JET as a new relativeDate type using the oj.Validation module.

/**
* A converter factory for "relativeDate" that supports custom
* formatting of normal and relative date times.
*/
RelativeDateTimeConverterFactory = (function () {
/**
* Private function that takes regular and relative options.
*
* @param {Object} options
* @return {Object}
* @private
*/
function _createRelativeDateTimeConverter(options)
{
return new RelativeDateTimeConverter(options);
}

return {
'createConverter': function (options) {
return _createRelativeDateTimeConverter(options);
}
};
}());

/** Register the  factory with JET */
oj.Validation.converterFactory("relativeDate", // factory name
RelativeDateTimeConverterFactory);

3. Add code to your application that uses the custom converter.

The code sample below shows how you could add code to your script to use the custom converter.

var rdtcf = oj.Validation.converterFactory("relativeDate");
var rdOptions = {relativeField: 'day', year: "numeric", month: "numeric", day: "numeric"};
var rdConverter = rdtcf.createConverter(rdOptions);

4. Add the Oracle JET component or components that will use the custom converter to your page.

For the code sample that creates the ojTable component and displays the Schedule For column in relative dates, see Converters (Custom).

Using Oracle JET Converters Without Oracle JET Components

If you want to use a converter without binding it to an Oracle JET component, create the converter using oj.Validation.converterFactory.createConverter().

The Oracle JET Cookbook includes a complete example that shows how you can use the built-in number and date time converters directly in your pages without binding them to an Oracle JET component at Converters (Built-in Examples). In the image below, the salary is a number formatted as currency, and the start date is an ISO string formatted as a date.

The sample code below shows a portion of the viewModel that defines a salaryConverter to format a number as currency and a dateConverter that formats the start date using the date format style and medium date format.

// for salary fields
var salOptions = {style: 'currency', currency: 'USD'};
var salaryConverter =
oj.Validation.converterFactory("number").createConverter(salOptions);
self.amySalary = ko.observable(salaryConverter.format(125475.00));
self.garySalary = ko.observable(salaryConverter.format(110325.25));

// for date fields
var dateOptions = {formatStyle: 'date', dateFormat: 'medium'};
var dateConverter =
oj.Validation.converterFactory("datetime").createConverter(dateOptions);
self.amyStartDate = ko.observable(dateConverter.format("2014-01-02"));
self.garyStartDate = ko.observable(dateConverter.format("2009-07-25"));

The code sample below shows the portion of the markup that sets the display output to the formatted values contained in amySalary, amyStartDate, garySalary, garyStartDate.

<td>
<div class="oj-panel oj-panel-alt4 demo-panel-customizations">
<h3 class="oj-header-border">Amy Flanagan</h3>
<img src="images/Amy.png" alt="Amy">
<p>Product Manager</p>
<span style="white-space:nowrap;"><b>Salary</b>:
<span data-bind="text: amySalary"></span></span>
<br/>
<span style="white-space:nowrap;"><b>Joined</b>:
<span data-bind="text: amyStartDate"></span></span>
<br/>
</div>
</td>
<td>
<div class="oj-panel oj-panel-alt2 demo-panel-customizations">
<h3 class="oj-header-border">Gary Fontaine</h3>
<img src="images/Gary.png" alt="Gary">
<p>Sales Associate</p>
<span style="white-space:nowrap;"><b>Salary</b>:
<span data-bind="text: garySalary"></span></span>
<br/>
<span style="white-space:nowrap;"><b>Joined</b>:
<span data-bind="text: garyStartDate"></span></span>
<br/>
</div>
</td>

Using Oracle JET Validators

Oracle JET validators provide a set of properties that allow callers to customize the validator instance. The properties are documented as part of the validators��� API. Unlike converters where only one instance of a converter can be set on a component, page authors can associate one or more validators with a component. When a user interacts with the component to change its value, the validators associated with the component are run in order.

When the value violates a validation rule, the value option is not populated, and the validator highlights the component with an error.

You can use the validators with an Oracle JET component or instantiate and use them directly on the page.

Topics:

- Using Oracle JET Validators with Oracle JET components

- Using Custom Validators in Oracle JET

- Using Oracle JET Validators Without an Oracle JET Component

Using Oracle JET Validators with Oracle JET components

Oracle JET editable components, such as ojInputText and ojInputDate, set up validators both implicitly, based on certain options they support such as required, min, max, and so on, and explicitly by providing a means to set up one or more validators using the component's validators option. As with the Oracle JET converters, the validators property can be specified either using JSON array notation or can be an array of actual validator instances.

For example, the following code sample shows a portion of a form containing an ojInputDate component that uses the default validator supplied by the component implicitly. The highlighted code shows the HTML5 attribute set on the input element and the binding for the ojInputDate component. When the ojInputDate component reads the min attribute, it creates the implicit oj.DateTimeRangeValidator.

<div id="builtin-example" class="oj-form oj-md-odd-cols-4 oj-md-labels-inline">
<div class="oj-row">
<div class="oj-col">
<label for="dateTimeRange1">'min' attribute and 'max' option</label>
</div>
<div class="oj-col">
<input id="dateTimeRange1" type="date" name="dateTimeRange1"
min="2000-01-01T00:00:00.000"
title="enter a date that falls in the current millenium and not greater than today's date."
data-bind="ojComponent:{component:'ojInputDate', max: todayIsoDate, value: dateValue1}"/>
</div>
</div>

The script to create the view model for this example is shown below.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'ojs/ojinputnumber', 'ojs/ojinputtext', 'ojs/ojdatetimepicker'],
function(oj, ko, $)
{
function DemoViewModel()
{
var self = this;
self.dateValue1 = ko.observable();
self.todayIsoDate =
ko.observable(oj.IntlConverterUtils.dateToLocalIso(new Date()));
};

$(document).ready(
function()
{
ko.applyBindings(new DemoViewModel(), document.getElementById('builtin-example'));
}
);
});

When the user runs the page, the ojInputDate component displays an input field with the expected date format. When the user clicks on the field, the validator hint provided by the implicitly created oj.DateTimeRangeValidator, along with the title attribute set on the element, are shown in the note window. If the user inputs data that is not within the expected range, the built-in validator displays an error message with the expected range.

The error thrown by the Oracle JET validator when validation fails is represented by the oj.ValidatorError object, and the error message is represented by the oj.Message object. The messages and hints that Oracle JET validators use when they throw an error are resources that are defined in the translation bundle included with Oracle JET. For more information about messaging in Oracle JET, see Working with User Assistance.

You can also specify the validator directly on the component's validators property, if it exists. The code sample below adds another ojInputDate component to the sample form and specifies the oj.DateTimeRangeValidator validator (dateTimeRange) in the validators property with options that set the valid minimum and maximum dates and a hint that displays when the user sets the focus in the field.

<div class="oj-row">
<div class="oj-col">
<label for="dateTimeRange2">'dateTimeRange' type in 'validators' option</label>
</div>
<div class="oj-col">
<input id="dateTimeRange2" type="date" name="dateTimeRange2"
title="enter a date in your preferred format and we will attempt to figure it out"
data-bind="ojComponent:{component:'ojInputDate', value: dateValue2,
validators: [{type: 'dateTimeRange', options: {
max: todayIsoDate,
min: milleniumStartIsoDate,
hint: {'inRange': 'Enter a date that falls in the current millennium.'}}}]}"/>
</div>
</div>

The highlighted code below shows the additions to the viewModel.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'ojs/ojinputnumber', 'ojs/ojinputtext', 'ojs/ojdatetimepicker'],
function(oj, ko, $)
{
function DemoViewModel()
{
var self = this;
self.dateValue1 = ko.observable();
self.dateValue2 = ko.observable();
self.todayIsoDate =
ko.observable(oj.IntlConverterUtils.dateToLocalIso(new Date()));
self.milleniumStartIsoDate =
ko.observable(oj.IntlConverterUtils.dateToLocalIso(new Date(2000, 00, 01)));
};

$(document).ready(
function()
{
ko.applyBindings(new DemoViewModel(), document.getElementById('builtin-example'));
}
);
});

When the user runs the page for the en-US locale, the ojInputDate component displays an input field that expects the user's input date to be between 01/01/00 and the current date. When entering a date value into the field, the date converter will accept alternate input as long as it can parse it unambiguously. This offers end users a great deal of leniency when entering date values.

For example, typing 1-2-3 will convert to a Date that falls on the 2nd day of January, 2003. If the Date value also happens to fall in the expected Date range set in the validator, then the value is accepted. If validation fails, the component will display an error.

The options that each validator accepts are specified in JavaScript API Reference for Oracle�� JavaScript Extension Toolkit (JET).

The Oracle JET Cookbook contains the complete example used in this section as well as examples that show the built-in validators for date restrictions, length, number range, regular expression, and required fields. For details, see Validators.

For more information about Oracle JET component validation, see Understanding How Validation and Messaging Works in Oracle JET Editable Components.

Using Custom Validators in Oracle JET

You can create custom validators in Oracle JET by extending oj.Validator or by duck typing it. You can also create a custom validator factory to register the validator with Oracle JET and make it easier to instantiate the validator by name.

For example, the following code creates an instance of customValidator.

oj.Validation.validatorFactory('customValidator').createValidator();

Custom validators can be used with Oracle JET components, provided they don't violate the integrity of the component. As with the built-in Oracle JET validators, you can also use them directly on the page.

The figure below shows an example of a custom validator used to validate password entries. If the user's password doesn't match, the validator displays an error message.

To create and use a custom validator in Oracle JET:

1. Define the custom validator.

The highlighted code in the sample below shows the definition for the equalToPassword custom validator used in the figure above. The validator duck types the oj.Validator contract. Because the validator provides the methods expected of a validator, the Oracle JET framework accepts it.

function DemoViewModel ()
{
var self = this;
self.password = ko.observable();
self.passwordRepeat = ko.observable();

// When password observable changes, validate the Confirm Password component
// if it holds a non-empty value.
self.password.subscribe (function (newValue)
{
var $cPassword = $("#cpassword"), cpUIVal = $cPassword.val();
if (newValue && cpUIVal)
{
$cPassword.ojInputPassword("validate");
}
});

// A validator associated to the Confirm Password field, that compares that
// the value in the password observable matches the value entered in the
// Confirm Password field.

self.equalToPassword = {

validate: function(value)
{
var compareTo = self.password.peek();
if (!value && !compareTo)
return true;
else if (value !== compareTo)
{
// Passwords must match!
throw new Error(bundle['app']['validator-equalTo']['summary']);
}
return true;
}
};
};
ko.applyBindings(new DemoViewModel(), document.getElementById('custom-validator-example'));

2. Optionally, create a validator factory for the custom validator that supports a createValidator() method, meeting the contract defined by oj.ValidatorFactory.

The following code sample shows a simple validator factory for the equalToPassword validator. The code also registers the factory with Oracle JET as a new equalToPassword type using the oj.Validation module.

/**
* A validator factory for "equalTo" that validates two input values are equal.
*
* @return {{createValidator: function((Object|null)): (Object|null)}}
* @class
* @public
*/
equalToPasswordValidatorFactory = (function () {
/**
* Private function that takes regular and relative options.
*
* @param {Object} options
* @return {Object}
* @private
*/
function _createEqualToPasswordValidator(options)
{
return new equalToPasswordValidator (options);
}

return {
'createValidator': function (options) {
return _createEqualToPasswordValidator (options);
}
};
}());

/** Register the  factory with JET */
oj.Validation.validatorFactory("equalToPassword", // factory name
equalToPasswordValidatorFactory);

3. Add code to your application that uses the custom validator.

The code sample below shows how you could add code to your page to use the custom validator. In this example, both input fields are defined as ojInputPassword components. The first ojInputPassword component uses oj.RegExpValidator to validate that the user has input a password that meets the application's password requirements. The second ojInputPassword component uses the equalToPassword validator to verify that the password in the second field is equal to the password entered in the first field.

<div id="custom-validator-example" class="oj-form oj-md-odd-cols-4 oj-md-labels-inline">
<div class="oj-row">
<div class="oj-col">
<label for="password">Password</label>
</div>
<div class="oj-col">

<input id="password" type="password" name="password" required
title="Enter at least 6 characters including a number, one uppercase and lowercase letter"
data-bind="ojComponent: {component: 'ojInputPassword', value: password,
invalidComponentTracker: invalidComponents,
validators: [{type: 'regExp', options : {pattern: '(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{6,}',
label: 'Password', messageSummary : '\'{label}\' too Weak',
messageDetail: 'You must enter a password that meets our minimum
security requirements.'}}]}"/>
<div class="oj-row">
<div class="oj-col">
<label for="cpassword">Confirm Password</label>
</div>
<div class="oj-col">
<input id="cpassword" type="password" name="cpassword"
data-bind="ojComponent: {component: 'ojInputPassword', instance: passwordRepeat,
validators: [equalToPassword]}"/>
</div>
</div>
</div>

For the complete code sample used in this section, see Validators (Custom).

Using Oracle JET Validators Without an Oracle JET Component

If you want to use the validator without binding it to an Oracle JET component, create the validator using the oj.Validation.validatorFactory.createValidator() method.

For example, the following code creates the number range validator:

oj.Validation.validatorFactory(oj.ValidatorFactory.VALIDATOR_TYPE_NUMBERRANGE).createValidator();

9 Working with User Assistance

The Oracle JET user assistance framework includes support for user assistance on the editable components in the form of help, hints, and messaging that you can customize as needed for your application. Editable components include ojCheckboxSet, ojComboxbox, ojInput*, ojRadioSet, ojSelect, ojSwitch, and ojTextArea.

Topics:

- Typical Workflow for Working with User Assistance

- Understanding Oracle JET's Messaging APIs on Editable Components

- Understanding How Validation and Messaging Works in Oracle JET Editable Components

- Using Oracle JET Messaging

- Configuring an Editable Component's Help Option

- Configuring an Editable Component's Title Option

- Controlling the Display of Hints, Title, and Messages

- Applying Form Validation Best Practices

Typical Workflow for Working with User Assistance

To add user assistance to your Oracle JET application, refer to the typical workflow described in the following table:

Task

Description

More Information

Identify Oracle JET's user assistance capabilities on editable components

Identify the editable components and their messaging APIs.

Understanding Oracle JET's Messaging APIs on Editable Components

Understand Oracle JET editable component validation and messaging process

Understand the normal, deferred, and mixed validation processes and the messaging associated with each.

Understanding How Validation and Messaging Works in Oracle JET Editable Components

Use Oracle JET validation and messaging on editable components

Learn how to track the validity of a group of editable components and configure an Oracle JET application to notify editable components of business validation failures and to receive notification of an editable component's events and messages.

Using Oracle JET Messaging

Configure the help option on editable components

Add a help icon to your component that includes a URL for additional information or add explanatory text that appears when the user hovers over the input component's label.

Configuring an Editable Component's Help Option

Configure the title option on editable components

Configure the title option to add advisory information to an input field that appears when the field has focus.

Configuring an Editable Component's Title Option

Control the display of hints, titles, and messages

Use the editable component's displayOptions option to control the placement and display of converter and validator hints, messaging, and title options.

Controlling the Display of Hints, Title, and Messages

Apply best practices to form validation.

Use an Oracle JET component's invalidComponentTracker binding attribute to implement best practices for form validation.

Applying Form Validation Best Practices

Understanding Oracle JET's Messaging APIs on Editable Components

The Oracle JET framework provides a messaging API to support messaging on Oracle JET editable components.

Editable components include the following:

- ojCheckboxSet

- ojCombobox

- ojInputDate

- ojInputDateTime

- ojInputNumber

- ojInputPassword

- ojInputText

- ojInputTime

- ojRadioSet

- ojSelect

- ojSwitch

- ojTextArea

Topics:

- Oracle JET Editable Component Messaging Options

- Oracle JET Component Messaging Methods

- Oracle JET Component Messaging Binding Attributes

- oj.InvalidComponentTracker

For a description of the editable components, see Working with Text Input Components. The Oracle JET Cookbook also includes examples for working with each component at: Form Controls.

Oracle JET Editable Component Messaging Options

The following options impact messaging on editable components.

Component Option

HTML5 Attribute

Description

converter

Default converter hint displayed as placeholder text when a placeholder option or HTML5 attribute is not already set.

displayOptions

JSON object literal that specifies the location where the component should display auxiliary content such as messages, converterHint, validatorHint, and title in relation to itself. Refer to the component's API documentation for details.

help

Help message displayed on the input label when the user hovers over the label or the Help icon. No formatted text is available for the message.

The help definition attribute's value appears when you hover with a mouse, and the attribute's value is read by a screen reader. It does not appear when you set focus, so it is not touch or keyboard accessible. Therefore, do not set the help definition text to something that is required to be able to use the page. The default value is null.

messagesCustom

List of messages that the application provides when it encounters business validation errors or messages of other severity type.

messagesHidden

List of messages currently hidden on component. These are added by the component when it runs deferred validation. This option is read-only, and you cannot set or change it directly.

messagesShown

List of messages currently shown on the component. These include messages generated both by the component and ones provided by the application using the messagesCustom option. This option is read-only, and you cannot set or change it directly.

placeholder

placeholder

The placeholder text to set on the element.

title

title

Displays text in a note window that displays when the user sets focus on the input field. You can format the text string using standard HTML formatting tags.

translations

Object containing all translated resources relevant to the component and all its superclasses. Use sub-options to modify the component's translated resources.

validators

List of validators used by component when performing validation. Validator hints are displayed in a note window by default.

See the Options section of the component's API documentation in JavaScript API Reference for Oracle�� JavaScript Extension Toolkit (JET) for additional details about its messaging options. Select the component you're interested in viewing from the API list.

Note:

When the Oracle JET component is initialized on a component that also has HTML5 validation attributes, then these often drive the initial value of the corresponding option on the component if the value is not already set.

Oracle JET Component Messaging Methods

Editable value components support the following method for messaging purposes.

Component Event

Description

showMessages

Moves all deferred messages that are in the messagesHidden option to the messagesShown option. When the user sets focus on the component, the deferred messages will display in the note window.

See the Methods section of the component's API documentation in the JavaScript API Reference for Oracle�� JavaScript Extension Toolkit (JET) for details on how to call the method, its parameters, and return value. Select the component you're interested in viewing from the list.

Oracle JET Component Messaging Binding Attributes

Editable value components support the following binding attribute for messaging purposes.

Binding Attribute

Description

invalidComponentTracker

Tracks the validity of the Oracle JET component. This attribute is available on all Oracle JET editable component when you use the oj.Component binding. When you bind this option to a Knockout observable, an instance of an oj.InvalidComponentTracker object is set on the observable.

For additional detail about the oj.InvalidComponentTracker object, see oj.InvalidComponentTracker.

Note:

The invalidComponentTracker binding attribute depends upon the ojs/ojknockout-validation module, and you must add the module to your RequireJS bootstrap file. For additional information about the ojs/ojknockout-validation module, see Oracle JET Module Organization. For details about using RequireJS in your application, see Using RequireJS in an Oracle JET Application.

See the Binding Attributes section of the component's API documentation in the JavaScript API Reference for Oracle�� JavaScript Extension Toolkit (JET). Select the component you're interested in viewing from the API list.

oj.InvalidComponentTracker

oj.InvalidComponentTracker is a helper object that tracks the validity of a group of components and provides useful properties and methods that allow a page author to enforce validation best practices in Oracle JET applications.

Applications can use this object to:

- Determine whether there are invalid components in the group that are currently showing messages using the invalidShown property.

- Determine whether there are invalid components that have deferred messages, such as messages that are currently hidden in the group, using the invalidHidden property.

- Set focus on the first invalid component showing in the group using the focusOnFirstInvalid() method.

- Show deferred messages on all tracked components using the showMessages() method.

oj.InvalidComponentTracker updates its state every time one of the editable components it tracks triggers an optionChange event for messagesHidden or messagesShown options. When the messagesCustom option is updated, the messagesShown option is automatically updated to reflect the change, and an optionChange event is also triggered for the messagesShown option.

For details about the oj.InvalidComponentTracker object's fields and methods, see oj.InvalidComponentTracker. For information about using oj.InvalidComponentTracker in your Oracle JET application, see Using a Component's invalidComponentTracker Binding Attribute.

Understanding How Validation and Messaging Works in Oracle JET Editable Components

The actions performed on an Oracle JET component, the options set on it, and the methods called on it, all instruct the component on how it should validate the value and what content it should show as part of its messaging.

Editable components always perform either normal or deferred validation in some situations. In other situations, the editable component decides to perform either normal or deferred validation based on the component's state. Understanding the normal and deferred validation process may be helpful for determining what message options to set on your components.

- Normal Validation: During normal validation, the component clears all messages options (messagesCustom, messagesShown, and messagesHidden), parses the UI value, and performs validation. Validation errors are reported to the user immediately. If there are no validation errors, the value option is updated, and the value is formatted and pushed to the display.
The editable component always runs normal validation when:

- The user interacts with an editable component and changes its value in the UI.

- The application calls validate() on the component.

Note:

When the application changes certain options, the component might decide to run normal validation depending on its current state. See Mixed Validation below for additional detail.

- Deferred Validation: Uses the required validator to validate the component's value. The required validator is the only validator that participates in deferred validation. During deferred validation all messages options are cleared unless specified otherwise. If the value fails deferred validation, validation errors are pushed to the messagesHidden option and not shown to the user immediately.
The editable component always runs deferred validation when:

- A component is created. None of the messages options are cleared.

- The application calls the reset() method on the component.

- The application changes the value option on the component programmatically.

Note:

When the application changes certain options programmatically, the component might decide to run deferred validation depending on its current state. See Mixed Validation below for additional detail.

- Mixed Validation: Runs when the following options are changed or methods are called by the application. Either deferred or normal validation is run based on the component's current state, and any validation errors are either hidden or shown to the user. Mixed validation runs when:

- converter option changes

- disabled option changes

- readOnly options change

- required option changes

- validators option changes.

- refresh() method is called

Topics:

- Understanding How an Oracle JET Editable Component Performs Normal Validation

- Understanding How an Oracle JET Editable Component Performs Deferred Validation

The Oracle JET Cookbook includes additional examples that show normal and deferred validation at Validators (Component). For additional information about the validators and converters included with Oracle JET, see Validating and Converting Input.

Understanding How an Oracle JET Editable Component Performs Normal Validation

An Oracle JET editable component runs normal validation when the user changes the value in the UI or when the application calls the component's validate() method. In both cases, error messages are displayed immediately.

Topics:

- Normal Validation Process When User Changes Value of an Editable Component

- Normal Validation Process When Validate() is Called on Editable Component

Normal Validation Process When User Changes Value of an Editable Component

When a user changes an editable value:

1. All messagesCustom, messagesHidden, and messagesShown messages are cleared. An optionChange event is triggered if applicable and if the change in value is obvious.

2. If a converter is set on the component, the UI value is parsed. If there is a parse error, then processing jumps to step 5.

3. If one or more validators are set on the component:

a. The parsed (converted) value is validated in sequence using the specified validators, with the implicit required validator being the first to run if present. The value that is passed to the implicit required validator is trimmed of white space.

b. If the validator throws an error, the error is remembered, and the next validator runs if it exists.
After all validators complete, if there are one or more errors, processing jumps to step 5.

4. If all validations pass:

a. The parsed value is written to the component's value option, and an optionChange event is triggered for the value option.

b. The new value is formatted for display using the converter again and displayed on the component.

Note:

If the component's value option happens to be bound to a Knockout observable, then the value is written to the observable as well.

5. If one or more errors occurred in an earlier step:

a. The component's value option is not changed.

b. The component's messagesShown option is updated, and an optionChange event is triggered for the messagesShown option.

c. Errors are displayed on the component. The user can also view the details of the error by setting focus on the component. By default, this will open a notewindow.

Note:

If the component's value option is bound to a Knockout observable, then the value is written to the observable array as well. In addition, if the page author has set the invalidComponentTracker binding attribute, then the array associated to this attribute is updated.

6. When the user fixes the error, the validation process begins again.

Normal Validation Process When Validate() is Called on Editable Component

The validate() method validates the component's current display value using the converter and all validators registered on the component and updates the value option if validation passes.

For details about the validate() method, see validate()

Understanding How an Oracle JET Editable Component Performs Deferred Validation

An Oracle JET editable component runs deferred validation when the component is created, when its value or required option is changed programmatically, or when the component's reset() method is called. This section provides additional detail about the deferred validation process when an Oracle JET editable component is created and when the value option is changed programmatically.

Topics:

- Deferred Validation Process When an Oracle JET Editable Component is Created

- Deferred Validation Process When value Option is Changed Programmatically

You can also find additional detail in the JavaScript API Reference for Oracle�� JavaScript Extension Toolkit (JET). Select the component you���re interested in from the navigation list.

Deferred Validation Process When an Oracle JET Editable Component is Created

When a editable component is created, as one of the last steps, it runs deferred validation on the component's initialized value.

1. The required validator is run, and a validation error raised if the value is empty or null.

2. If a validation error is raised, the component updates the messagesHidden option which triggers the optionChange event.

- isValid() method returns false.

- No messaging themes are applied on the component nor does it show the error message in the note window because the validation error message is deferred.

Note:

Page authors can call showMessages() at any time to reveal deferred messages.

Deferred Validation Process When value Option is Changed Programmatically

An Oracle JET editable component's value option can change programmatically if:

- The page has code that changes the component's value using the component's option() method, or

- The page author refreshes the ViewModel observable with a new server value.

In both cases, the component will update itself to show the new value as follows:

1. All messages options are cleared on the editable component and optionChange events triggered if applicable.

2. An optionChange event is triggered for the value option if applicable.

3. If a converter option is set on the component, the value option is retrieved and formatted before it's displayed. If there is a format error, then processing jumps to step 5. Otherwise the formatted value is displayed on the component.

4. Deferred validators are run on the new value. Any validation errors raised are communicated to the messaging framework, and the messagesHidden option updated, but the errors themselves are not shown to the user.

5. If there was a formatting error, the validation error message is processed and the component's messagesShown option updated. Formatting errors are shown right away.

Note:

Page authors should ensure that the value you set is the expected type as defined by the component's API and that the value can be formatted without any errors for display.

Using Oracle JET Messaging

You can use the Oracle JET messaging framework to notify an Oracle JET application of a component's messages and validity as well as notify an Oracle JET component of a business validation failure.

Topics:

- Tracking Validity of a Group of Editable Components Using Knockout

- Notifying an Oracle JET Application of a Component's Messages and Validity

- Notifying an Oracle JET Editable Component of Business Validation Errors

Tracking Validity of a Group of Editable Components Using Knockout

You can track the validity of a group of editable components by using the invalidComponentTracker binding attribute. This attribute is automatically available on all editable components.

In the markup below, username and password components bind to the same Knockout observable, tracker, allowing for validation to be tracked as a group.

<div id="example">
<input id="username" type="text" autocomplete="off" name="username" required
data-bind="ojComponent: {component: 'ojInputText', value: userName,
validators: [{type: 'regExp', options: {pattern: '[a-zA-Z0-9]{3,}',
'messageDetail': 'You must enter at least 3 letters or numbers'}}],
invalidComponentTracker: tracker}">

<input id="password" type="password" name="password" required
data-bind="ojComponent: {component: 'ojInputPassword', value: password,
validators: [{type: 'regExp', options : {pattern: '(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{6,}',
label: 'Password',
messageSummary : '\'{label}\' too Weak',
messageDetail: 'You must enter a password that meets our security requirements.'}}],
invalidComponentTracker: tracker}"/>

<button data-bind="ojComponent: {component: 'ojButton', label: 'Create',
disabled: shouldDisableCreate()}></button>
</div>

The example also uses a Create button whose disabled option is bound to the shouldDisableCreate() method so that it is disabled on a validation error.

The code that defines the MemberViewModel(), which includes the definition for the tracker observable, is shown below.

function MemberViewModel()
{
var self = this;
self.tracker = ko.observable();

// USERNAME
self.userName = ko.observable();
self.password = ko.observable();

self.shouldDisableCreate = function()
{
// see below
};
}
ko.applybindings(new MemberViewModel(), document.getElementById("example");

The shouldDisableCreate() function uses the invalidShown property, exposed on the tracker object, to enable the button conditionally on the page.

/**
* Determines when the Create button will be enabled.
* - if there are invalid components, currently showing messages, return true.
* - if we have invalid components, that deferred showing messages, end-user doesn't know
*   these have errors so return false.
* - if there are no invalid components return false.
*/
self.shouldDisableCreate = function()
{
var trackerObj = ko.utils.unwrapObservable(self.tracker),
hasInvalidComponents = ko.utils.unwrapObservable(trackerObj["invalidShown"]);
return  hasInvalidComponents;
};

Note:

The invalidComponentTracker attribute depends upon the ojs/ojknockout-validation module, and you must add the module to your RequireJS bootstrap file. For additional information about the ojs/ojknockout-validation module, see Oracle JET Module Organization. For details about using RequireJS in your application, see Using RequireJS in an Oracle JET Application.

For an example showing the invalidComponentTracker used for cross-field validation, see Cross-Field Validation. For information about using invalidComponentTracker for form validation, see Applying Form Validation Best Practices.

Notifying an Oracle JET Application of a Component's Messages and Validity

You can notify your Oracle JET application of an Oracle JET component's messages and validity using an event listener or the invalidComponentTracker binding attribute.

Topics:

- Using the optionChange Event

- Using a Component's invalidComponentTracker Binding Attribute

Using the optionChange Event

When there are errors during conversion or validation, the component updates the messagesShown or messagesHidden messages option and triggers an optionChange event. You can register an event listener or callback to be notified of a component's validity.

The following code sample shows how you could add a callback to an ojInputText component for the optionChange event. The callback will log a message to the console showing the previous and current values for the messagesShown and messagesHidden options.

<input id="username"
data-bind="ojComponent: {component: 'ojInputText', 'value': 'abc',
'optionChange' : function(event, ui) {usernameMessagesChange( event, ui);}}"/>

<script>
usernameMessagesChange = function(event, ui)
{
if (ui.option && (ui.option === "messagesShown" || ui.option === "messagesHidden"))
window.console.log("option '"+ ui.option +"' changed from "+ ui.previousValue +" to "+ ui.value);
};
</script>

Using a Component's invalidComponentTracker Binding Attribute

When this attribute is set on the component, the Oracle JET binding framework registers a custom listener for the optionChange event. This enables the oj.InvalidComponentTracker object to update its state for the components it tracks when their messages options change.

Page authors can use the properties exposed on the tracker object to be notified of changes. For details, see Tracking Validity of a Group of Editable Components Using Knockout.

Notifying an Oracle JET Editable Component of Business Validation Errors

You can notify Oracle JET editable components of business validation errors using the messagesCustom option and the showMessages() method.

Topics:

- Using the messagesCustom Option

- Using the showMessages() Method on Editable Components

Using the messagesCustom Option

Your application can use this option to notify the Oracle JET framework components of new or updated messages. These could be a result of business validation that originates in the viewModel layer or on the server.

A common business validation is to perform cross field validation to compare the values in one observable against another.

In the example below, an instance of a cross-field custom validator is associated with the emailAddress observable, ensuring that its value is non-empty when the user chooses Email as their contact preference.

For the complete example and code used to create the custom validator, see Cross-Field Validation. The demo uses a custom validator to validate an observable value against another. When an error occurs, the code updates the messagesCustom option.

Using the showMessages() Method on Editable Components

Use this method to instruct the component to show its deferred messages. When this method is called, the Oracle JET editable component automatically moves all deferred messages in the messagesHidden option to the messagesShown option. This causes the component to display the deferred messages to the user.

The oj.InvalidComponentTracker object uses this method to show deferred messages. For an example, see App Level Validation.

Configuring an Editable Component's Help Option

You can configure an editable component's help option to display descriptive text, display a help icon that includes a link to a URL for additional information, or display both the help text and help icon.

The help option includes two sub-options that control the help definition text and help icon:

- definition: Contains the help definition text that displays when the user does one of the following:

- hovers over the label or help icon

- tabs into the help icon with the keyboard

- presses and holds the help icon on a mobile device

- source: Contains the URL to be used in the help icon's link

The following image shows three ojInputText components configured to use the help option. The top component is configured with both a definition and source help sub-option, and the image shows the text and clickable pointer that displays when the user hovers over the label and help icon. In the middle image, the ojInputText component includes a help icon that links to a URL when the user selects it. In the bottom image, the ojInputText displays the custom help text when the user hovers over the label or help icon. In this example, the icon is not clickable but just displays custom text.

To configure an editable component's help option:

1. Add the editable component to your page.

If you need help, see Adding an Oracle JET Component to Your Page.

2. In the markup, add the help option and definition or source sub-option.

The markup for the ojInputText components is shown below. Each ojInputText component uses the ojComponent binding to define the component and set the help sub-options. In this example, the user will be directed to http://www.oracle.com after clicking Help.

<div id="form-container" class="oj-form">
<h3 class="oj-header-border">Help Definition and Source</h3>
<label id="ltext10" for="text10">'help' option with 'source' and 'definition'</label>
<input id="text10" type="text" name="text10"
data-bind="ojComponent:{
component: 'ojInputText',
value: text,
help: {
definition: 'custom help text',
source: 'http://www.oracle.com'}}"/>

<label id="ltext11" for="text11">'help' option with 'source'</label>
<input id="text11" type="text" name="text11"
data-bind="ojComponent:{
component:'ojInputText',
value: text,
help: {
source: 'http://www.oracle.com'}}"/>

<label id="ltext12" for="text12">'help' option with 'definition'</label>
<input id="text12" type="text" name="text12"
data-bind="ojComponent:{
component:'ojInputText',
value: text,
help: {
definition: 'custom help text'}}"/>
</div>

3. In your application's script, set the component's value option to a Knockout observable, and apply the bindings.

In this example, each ojInputText component's value option is defined as text which is set to a Knockout observable in the following script.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'ojs/ojinputtext'],
function(oj, ko, $)
{
function MemberViewModel()
{
var self = this;
self.text = ko.observable();
};

$(document).ready(
function()
{
ko.applyBindings(new MemberViewModel(), document.getElementById('form-container'));
}
);
});

See the Oracle JET Cookbook at Help and Title for the complete example to configure the help option on the ojInputText component.

Configuring an Editable Component's Title Option

You can configure an editable component's title option to display a note window with advisory text (often called a tooltip) when the input component has focus.

The following image shows three ojInputText components configured to display text when the user sets focus in the input field. In the top example, the title definition is set on the HTML input element directly. In the middle example, the title definition is defined as an option for the ojInputText component. In the bottom example, the title definition is also defined as an option for the ojInputText component, with HTML formatting added to the advisory text.

Both methods work if you don't care about the formatting of the advisory text. However, the HTML title element doesn't support text formatting, and you must use the component's title option or another mechanism if you want to format the text in the note window.

To configure an editable component's title option:

1. Add the editable component to your page.

If you need help, see Adding an Oracle JET Component to Your Page.

2. In the markup, add the title option to the component's definition or directly to the HTML input element.

The following code sample shows the markup for defining the three ojInputText components. The samples also define regular expression validators to ensure that the user enters at least three letters or numbers.

<div id="form-container" class="oj-form">
<h3 class="oj-header-border">Title</h3>
<label for="text20">input with 'title' attribute</label>
<input id="text20" type="text" autocomplete="off"
required name="text20"
title="Enter at least 3 alphanumeric characters"
data-bind="ojComponent: {
component: 'ojInputText',
value: text,
validators: [{
type: 'regExp',
options: {
pattern: '[a-zA-Z0-9]{3,}',
messageDetail: 'You must enter at least 3 letters or numbers'}}]}">

<label for="text21">input with 'title' option</label>
<input id="text21" type="text" autocomplete="off" required name="text21"
data-bind="ojComponent: {
component: 'ojInputText',
value: text,
title: 'Enter at least 3 alphanumeric characters',
validators: [{
type: 'regExp',
options: {
pattern: '[a-zA-Z0-9]{3,}',
messageDetail: 'You must enter at least 3 letters or numbers'}}]}">

<label for="text22">input with formatted text in 'title' option</label>
<input id="text22" type="text" autocomplete="off" required name="text22"
data-bind="ojComponent: {
component: 'ojInputText',
value: text,
title: '<html>enter <span style=\'color:red\'>at least 3 alphanumeric</span> characters</html>',
validators: [{
type: 'regExp',
options: {
pattern: '[a-zA-Z0-9]{3,}',
messageDetail: 'You must enter at least 3 letters or numbers'}}]}">
</div>

3. In your application script, set the component's value to a Knockout observable.

In this example, each ojInputText component's value option is defined as text which is set to a Knockout observable in the following script.

require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'ojs/ojinputtext'],
function(oj, ko, $)
{
function MemberViewModel()
{
var self = this;
self.text = ko.observable();
};

$(document).ready(
function()
{
ko.applyBindings(new MemberViewModel(), document.getElementById('form-container'));
}
);
});

For the complete example, see Help and Title in the Oracle JET Cookbook. For additional detail about the ojInputText component, see the ojInputText API documentation.

For additional information about the regular expression validator, see About Oracle JET Validators and Converters.

Controlling the Display of Hints, Title, and Messages

Use the displayOptions component option to control the placement and visibility of converter and validator hints, messages, and title.

The following image shows the default placement and visibility of help, converter and validator hints, messages, and title. This example uses the ojInputDate component, but the behavior is the same on all editable components where it makes sense:

- help: Displays in a note window on hover

- validator hint: Displays in a note window on focus

- converter hint: Used as the input field's placeholder or displays in a note window if the placeholder option is defined.

- messages: Displays inline on error

- title: Displays in a note window on focus

The code sample below shows the markup for the ojInputDate component used in this example. The example includes definitions for title, help, validator hints, and custom messages on validation failure.

<div id="form-container" class="oj-form">

<h3 class="oj-header-border">Default Display of Messages, Hints, Title</h3>
<label for="date10">input date</label>
<input id="date10" type="text" size="30"
required name="date10"
title="Enter a date in your preferred format and we will attempt to figure it out"
data-bind="ojComponent:{
component:'ojInputDate',
value: birthdate,
converter: longDateConverter,
help: {definition: 'custom help text'},
validators: [{
type: 'datetimeRange',
options: {
min: oj.IntlConverterUtils.dateToLocalIso(new Date(1930, 00, 01)),
max: oj.IntlConverterUtils.dateToLocalIso(new Date(1995, 11,30)),
hint: {inRange: 'Validator hint: datetimeRange: January 1, 1930 - November 30, 1995 years'},
messageSummary:{
rangeOverflow: 'messageSummary: rangeOverflow: Date later than max.',
rangeUnderflow: 'messageSummary: rangeUnderflow:Date earlier than min.'},
messageDetail:{
rangeOverflow: 'messageDetail: rangeOverflow: The value \'{value}\' is not in the expected range; it is too high.',
rangeUnderflow: 'messageDetail: rangeUnderflow: The value \'{value}\' is not in the expected range; it is too low.'}}}],
translations: {'required' : {
hint: 'Validator hint: required: You must enter a valid date',
messageSummary: 'messageSummary: custom summary: \'{label}\' Required',
messageDetail: 'messageDetail: custom detail: A value is required for this field'}}}"/>
</div>

Using the displayOptions component option in your markup, you can change the default behavior of the title, hints, and messaging options of a single editable component on your page. To control the behavior of all editable components on the page, you can use the oj.Component.setDefaultOptions() method in your application script to set displayOptions.

displayOptions allows you to change the default behavior as follows:

- title: Set to none to turn off the title display.

- converterHint: Set to none to turn off the display or set to notewindow to change the default placement from placeholder text to a note window.

- validatorHint: Set to none to turn off the display.

- messages: Set to none to turn off the display or set to notewindow to change the default placement from inline to a note window.

To change the default display and location of title, hints, and messaging options:

1. Add the editable component to your page.

If you need help, see Adding an Oracle JET Component to Your Page.

2. To change the default display and location for an individual editable component, add the displayOptions option to your component definition and set it as needed.

For example, to turn off the display of hints and title and to display messages in a note window, add the highlighted markup to your component definition:

data-bind="ojComponent:{
component:'ojInputDate',
value: birthdate,
converter: longDateConverter,
displayOptions:
{converterHint: 'none', validatorHint: 'none', title: 'none', messages: 'notewindow'},
... contents omitted
}"

3. To change the default display and location for all editable components in your application, add the oj.Component.setDefaultOptions() method to your application's script and specify the desired displayOptions.

For example, to turn off the display of hints and title and to display messages in a note window, add the ojComponent.setDefaultOptions() method with the arguments shown below.

oj.Components.setDefaultOptions({
'editableValue':
{
'displayOptions':
{
'converterHint': ['none'],
'validatorHint': ['none'],
'messages': ['notewindow'],
'title': ['none']
}
}});

The Oracle JET cookbook contains the complete code for this example at Help, Hints, and Messaging. You can also find additional examples that illustrate help, hints, messaging, and title configuration.

Applying Form Validation Best Practices

The Oracle JET framework provides methods on the oj.InvalidComponentTracker object that you can use to implement Oracle's recommended best practices for form validation.

The Oracle JET Cookbook includes a complete example that illustrates how you can implement the oj.InvalidComponentTracker object for form validation. For details, see Form Validation (Complete Example).

To apply best practices to form validation:

1. If there are invalid components showing on the page, disable any button that might submit input to the server.

To configure this behavior, bind the button component's disabled option to the invalidShown property of the oj.InvalidComponentTracker object.

self.shouldDisableCreate = function()
{
var trackerObj = ko.utils.unwrapObservable(self.tracker),
hasInvalidComponents = trackerObj ? trackerObj["invalidShown"] : false;
return  hasInvalidComponents;
};

If there are invalid components currently showing messages, the method returns true, and the button is disabled. If there are deferred errors or no visible errors, this method returns false, and the button is enabled.

For example in the Cookbook demo, the Create button's disabled option is bound to a method that uses the invalidShown property as described above. If the user tabs off a field with invalid data, the component displays an error, and the Create button is disabled.

After the user corrects the error by entering a valid value, such as abc, the error is cleared on the field, and the Create button enabled again.

2. When the user clicks Create , the application should display deferred messages on all tracked components.

To display the deferred messages, use the oj.InvalidComponentTracker object's showMessages() method.

trackerObj.showMessages();

If deferred messages are shown, the Create button will be disabled automatically.

After the user corrects all errors, the Create button will be automatically enabled again.

3. When the user clicks Create again, since there are no more deferred messages, the application can now perform business validation on the data.

In this example, business validation refers to cross-field validation, such as verifying that the email exists when the user selects email as the preferred contact.

Any errors generated are set on the component's messagesCustom option and are automatically shown to the user. The Create button will be disabled again until the user corrects all errors.

4. When the user clicks Create again, the application can now perform more business validation or submit the form data to the server.

The server could return with validation errors or changed values on one or more components. If there are validation errors, you can update the component's messagesCustom option. If there are updated values, update the component's value option.

For additional detail about the oj.InvalidComponentTracker object and the invalidComponentTracker binding attribute, see Using a Component's invalidComponentTracker Binding Attribute.

10 Developing Accessible Applications

The Oracle JET framework and Oracle JET components have built-in accessibility features for persons with disabilities. You can use these features to create accessible Oracle JET application pages.

Topics:

- Typical Workflow for Developing Accessible Oracle JET Applications

- Oracle JET and Accessibility

- Using the Accessibility Features of Oracle JET Components

- Creating Accessible Oracle JET Pages

Typical Workflow for Developing Accessible Oracle JET Applications

To develop accessible Oracle JET applications, refer to the typical workflow described in the following table:

Task

Description

More Information

Identify accessibility features included with Oracle JET

Identify the accessibility features included in the Oracle JET framework and Oracle JET components.

Oracle JET and Accessibility

Create accessible Oracle JET components

Identify tasks needed for specific components to ensure accessibility.

Using the Accessibility Features of Oracle JET Components

Create accessible Oracle JET pages

Identify tasks needed at the page level to ensure accessible Oracle JET pages.

Creating Accessible Oracle JET Pages

Oracle JET and Accessibility

Oracle JET components have built-in accessibility support that conforms with the Web Content Accessibility Guidelines version 2.0 at the AA level (WCAG 2.0 AA), developed by the World Wide Web Consortium (W3C).

Accessibility involves making your application usable for persons with disabilities such as low vision or blindness, deafness, or other physical limitations. This means, for example, creating applications that can be:

- Used without a mouse (keyboard only).

- Used with assistive technologies such as screen readers and screen magnifiers.

- Used without reliance on sound, color, animation, or timing.

Oracle JET components provide support for:

- Keyboard and touch navigation
Oracle JET components follow the Web Accessibility Initiative - Accessible Rich Internet Applications (WAI-ARIA) authoring practices. The API documentation for each Oracle JET component lists its keyboard and touch end user information when applicable, including a few deviations from the WAI-ARIA guidelines.

- Zoom
Oracle JET supports browser zooming up to 200%. For example, on the Firefox browser, you can choose View -> Zoom -> Zoom In.

- Screen reader
Oracle JET supports screen readers by generating content that complies with WAI-ARIA standards, and no special mode is needed.

- Oracle JET component roles and names
Each Oracle JET component has an appropriate role, such as button, link, and so on, and each component supports an associated name (label), if applicable.

- Sufficient color contrast
Oracle JET provides the Alta theme which is designed to provide a luminosity contrast ratio of at least 4.5:1.

Oracle documents the degree of conformance of each product with the applicable accessibility standards using the Voluntary Product Accessibility Template (VPAT). You should review the appropriate VPAT for the version of Oracle JET that you are using for important information including known exceptions and defects, if any.

While Oracle JET is capable of rendering an application that conforms to WCAG 2.0 AA to the degree indicated by the VPAT, it is the responsibility of the application designer and developer to understand the applicable accessibility standards fully, use JET appropriately, and perform accessibility testing with disabled users and assistive technology.

Using the Accessibility Features of Oracle JET Components

Oracle JET components are designed to generate content that conforms to the WCAG 2.0 AA standards. In most cases, you don't need to do anything to add accessibility to the Oracle JET component since it's built into the component. However, there are some components where you may need to supply a label or other property.

For these components, the component's API documentation contains an Accessibility section that provides the information you need to ensure the component's accessibility.

Note:

Some Oracle products have run-time accessibility modes that render content optimized for certain types of users, such as users of screen readers. For the most part, Oracle JET renders all accessibility-related content all of the time. There is only a mode for users that rely on the operating system's high contrast mode, which is described in Creating Accessible Oracle JET Pages.

Oracle JET components that provide keyboard and touch navigation list the keystroke and gesture end user information in their API documentation. Since the navigation is built into the component, you do not need to do anything to configure it.

You can access an individual Oracle JET component's accessibility features and requirements in the JavaScript API Reference for Oracle�� JavaScript Extension Toolkit (JET). Select the component you're interested in from the list on the left. You can also find the list of supported keystrokes and gestures for each Oracle JET component that supports keystrokes and gestures in the Oracle�� JavaScript Extension Toolkit (JET) Keyboard and Touch Reference.

Creating Accessible Oracle JET Pages

Content generated by Oracle JET is designed to conform to the WCAG 2.0 AA standards. However, many standards are not under the complete control of Oracle JET, such as overall UI consistency, the use of color, the quality of on-screen text and instructions, and so on.

A complete product development plan that addresses accessibility should include proper UI design, coding, and testing with an array of tools, assistive technology, and disabled users.

Note:

In most cases, end-user documentation for your application must describe information about accessibility, such as example keystrokes needed to operate certain components.

Topics:

- Configuring WAI-ARIA Landmarks

- Configuring High Contrast Mode

- Hiding Screen Reader Content

Configuring WAI-ARIA Landmarks

WAI-ARIA landmarks provide navigational information to assistive technology users. Landmark roles identify the purpose of a page region and allow the user to navigate directly to a desired region. Without landmarks, assistive technology users must use the TAB key to navigate through a page.

The Oracle JET team recommends the use of WAI-ARIA landmarks to ensure page accessibility and provides examples you can use in the Oracle JET QuickStart template collection. The following figure shows the run-time view of the Oracle JET QuickStart Basic application. In this example, the page is organized into regions compatible with WAI-ARIA landmark regions, including regions for the banner, navigation, main, and complementary landmarks.

The highlighted code in the following example shows landmarks for the Oracle JET QuickStart Basic application. Each landmark is placed on the HTML element that defines the landmark region: header for the banner landmark region, and div for the navigation, main, and complementary regions.

<!DOCTYPE html>
<html lang="en-us" class='demo-sticky-footer-layout'>
<head>
<title>Oracle JET QuickStart - Basic</title>    ... contents omitted
</head>
<body class="demo-appheader-offcanvas-pushwrapper">
<div id="globalBody" style="display: none">
<!-- Header section contains the Global Branding, Global Navigation, and
Application Navigation code. Template is located in
/templates/header.tmpl.html -->
<header id="headerWrapper" role="banner"
data-bind="ojModule: { name: 'header'}"></header>

<!-- This is where your main page content will be loaded -->
<div id="mainContainer">
<div class="oj-row">
<div class="oj-xl-3 oj-lg-3 oj-md-12 oj-col"> <!-- demo-coldrop-A -->
<div role="navigation" class="demo-page-content-area">
<!--  This section is usually used for Navigation.
If its purpose is changed, the "role" attribute should be
changed as well to meet accessibility guidelines-->
<div id="navigationContent" data-bind="ojModule: { viewName:
'navContent'}">
</div>
</div>
</div>
<div class="oj-xl-6 oj-lg-9 oj-md-12 oj-col"> <!-- demo-coldrop-B -->
<div role="main" class="demo-page-content-area">
<!-- Unlike the Navigation and Complementary sections, this ojModule
binding is using "name" instead of "viewName". This tells the
binding to look for and load the JavaScript module of the same
name before loading the view template file -->
<div id="mainContent" data-bind="ojModule: { name: setMainContent}">
</div>
</div>
</div>
<div class="oj-xl-3 oj-lg-12 oj-md-12 oj-col"> <!-- demo-coldrop-C -->
<div role="complementary" class="demo-page-content-area">
<div id="complementaryContent" data-bind="ojModule: { viewName:
'compContent'}">
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

For information about downloading the Oracle JET QuickStart templates, see Downloading Oracle JET with a QuickStart Template. For details about working with the Oracle JET QuickStart templates, see Using the Oracle JET QuickStart Templates.

For additional information about WAI-ARIA landmark roles, see http://www.w3.org/WAI/PF/aria/roles#landmark_roles.

Configuring High Contrast Mode

High contrast mode is for people who require a very high level of contrast in order to distinguish components on the page. Operating systems such as Microsoft Windows and MacOS provide methods for users to run in high contrast mode.

The graphic below shows the effect of changing to high contrast mode on Oracle JET icon font images.

Oracle JET provides the oj-hicontrast class that you can use to configure high contrast mode in your application.

Topics:

- Understanding Color and Background Image Limitations in High Contrast Mode

- Adding High Contrast Mode to Your Oracle JET Application

- Adding High Contrast Images or Icon Fonts

- Testing High Contrast Mode

Understanding Color and Background Image Limitations in High Contrast Mode

There are color and background image limitations in high contrast mode that your application may need to work around.

In high contrast mode the colors in the CSS may be ignored or overridden, including background, border, and text colors. Therefore, in high contrast mode you may need to find an alternative way to show state. For example, you might need to add or change the border to show that something is selected.

Also, your application may need to show alternate high contrast images that work on dark or light background color. Some operating systems, like Microsoft Windows 7, offer multiple display profiles for high contrast mode, including a black-on-white and white-on-black mode.

Finally, on Windows, background images don't appear in high contrast mode. Therefore, you cannot use background images to communicate anything informative. You can use a background image to make something look nice, but don't use it to communicate information like the status of a process or whether something is required.

Adding High Contrast Mode to Your Oracle JET Application

In most cases, you do not need to do anything to enable high contrast mode in your Oracle JET application. If you're using RequireJS to load Oracle JET component modules, Oracle JET will load a script that attempts to detect if a user is running in high contrast mode. If the script succeeds at detection, it will place the oj-hicontrast class on the body element.

There is a serious limitation to this method, however. There is no standard way to detect high contrast mode, and we can't guarantee that the script works in all cases on all browsers. For example, on Windows, the script does detect high contrast mode on Internet Explorer 8 and Firefox on Windows, but it does not detect high contrast mode on Chrome.

To be guaranteed that the .oj-hicontrast styles are applied, add a user preference setting for high contrast to your application and configure the application to add the oj-hicontrast class to the body element when the preference is set.

When the class is added, the .oj-hicontrast CSS styles are applied to the page where defined. The code below shows an excerpt from the Alta CSS which changes the outline-width to 3 on the ojButton component when the button has focus.

.oj-hicontrast .oj-button.oj-focus {
outline-width: 3px; }

Note:

For disabled content, JET supports an accessible luminosity contrast ratio, as specified in WCAG 2.0 - Section 1.4.3 Contrast (Minimum), in the themes that are accessible. For more information on which Oracle JET themes are accessible, see CSS Files Included With Oracle JET.

Section 1.4.3 says that text or images of text that are part of an inactive user interface component have no contrast requirement. Because disabled content may not meet the minimum contrast ratio required of enabled content, it cannot be used to convey meaningful information. For example, a checkbox may still appear checked in disabled mode, but since the colors may not pass contrast ratio, you cannot rely on all users being able to see that it's checked. If the information is needed to interact with the page correctly, you must convey it using a different method, for example as plain text.

Adding High Contrast Images or Icon Fonts

To support high contrast image files, Oracle JET provides Sass mixins that you can use to generate the correct CSS in high contrast mode to:

- Use an alternate image.

- Use images without using background images.

The Oracle JET cookbook provides examples that you can use at: CSS Images.

You can also use icon fonts instead of image files to support high contrast mode. The limitation is that icon fonts use a single color. Since these icons are text, they will be guaranteed to contrast against the background color on systems that ignore colors in the CSS. However, if you use color to show state (for example, changing an icon to blue when selected), the colors may be ignored in high contrast modes. You may need to find an alternative like setting a border instead. The Oracle JET cookbook provides icon font demos at: Icon Fonts.

Testing High Contrast Mode

The recommended way to test high contrast mode in Oracle JET applications is to set high contrast mode at the operating system level on a Microsoft Windows platform. The Windows platform is recommended because Windows turns off background colors and images in high contrast mode. Also, the Google Chrome browser does not remove background images in high contrast mode, and unless this is the only browser you plan to support, you should test high contrast with Microsoft Internet Explorer or Firefox.

To turn high contrast mode on and off in Microsoft Windows, use the following key combination: Left Alt+Left Shift+PrtScn. You may need to refresh your browser to see the new mode.

Hiding Screen Reader Content

Sometimes you want to have some text on the page that is read to the screen reader user, but the sighted user doesn't see. Oracle JET provides the oj-helper-hidden-accessible class that you can use to hide content.

You can find the .oj-helper-hidden-accessible style defaults in the Oracle JET CSS file. For the Alta theme, the CSS file is: css/libs/oj/v1.1.2/alta/oj-alta.css. For additional information about theming and Oracle JET, see Theming Applications.

11 Internationalizing and Localizing Applications

Oracle JET supports internationalization and globalization of Oracle JET applications. Configure your Oracle JET application so that the application can be used in a variety of locales and international user environments.

Topics:

- Typical Workflow for Internationalizing and Localizing Oracle JET Applications

- About Internationalizing and Localizing Oracle JET Applications

- Internationalizing and Localizing Oracle JET Applications

- Working with Oracle JET Translation Bundles

Typical Workflow for Internationalizing and Localizing Oracle JET Applications

To add internationalization and localization to your Oracle JET application, refer to the typical workflow described in the following table:

Task

Description

More Information

Understand internationalization and localization support in Oracle JET

Understand internationalization and localization support and how it applies to Oracle JET applications.

About Internationalizing and Localizing Oracle JET Applications

Internationalize and localize an Oracle JET application

Use Oracle JET's internationalization features to add internationalization support to an Oracle JET application.

Internationalizing and Localizing Oracle JET Applications

Add translations to an Oracle JET application

Merge your translations into the Oracle JET translation bundle.

Working with Oracle JET Translation Bundles

About Internationalizing and Localizing Oracle JET Applications

Internationalization (I18N) is the process of designing software so that it can be adapted to various languages and regions easily, cost effectively, and, in particular, without engineering changes to the software. Localization (L10N) is the use of locale-specific language and constructs at run time. Oracle has adopted the industry standards for I18N and L10N such as World Wide Web Consortium (W3C) recommendations, Unicode technologies, and Internet Engineering Task Force (IETF) specifications to enable support for the various languages, writing systems, and regional conventions of the world.

Languages and locales are identified with a standard language tag and processed as defined in BCP 47.

The Oracle JET framework includes Oracle National Language Support (NLS) translation support for the languages listed in the following table.

Language

Language Tag

Language

Language Tag

Arabic

ar

Korean

ko

Brazilian Portuguese

pt

Norwegian

no

Canadian French

fr-CA

Polish

pl

Czech

cs

Portuguese

pt-PT

Danish

da

Romania

ro

Dutch

nl

Russian

ru

Finnish

fi

Simplified Chinese

zh-Hans

French

fr

Slovak

sk

German

de

Spanish

es

Greek

el

Swedish

sv

Hebrew

he

Thai

th

Hungarian

hu

Traditional Chinese

zh-Hant

Italian

it

Turkish

tr

Japanese

ja

Oracle JET translations are stored in a resource bundle. You can add your own translations to the bundles. For additional information see Adding Translation Bundles to Oracle JET.

The Oracle JET framework also includes formatting support for over 160 locales. Oracle JET locale elements are based upon the Unicode Common Locale Data Repository (CLDR) and are stored in locale bundles. For additional information about Unicode CLDR, see http://cldr.unicode.org. You can find the supported locale bundles in the Oracle JET distribution:

js/libs/oj/v1.1.2/resources/nls

It is the application's responsibility to determine the locale used on the page. Typically the application determines the locale by calculating it on the server side from the browser locale setting or by using the user locale preference stored in an identity store and the supported translation languages of the application.

Once the locale is determined, your application must communicate this locale to the Oracle JET framework for its locale sensitive operations such as loading resource bundles and formatting date-time data. Oracle JET determines the locale for locale sensitive operations in the following order:

1. Locale specification in the RequireJS configuration.

2. lang attribute of the html tag.

3. navigator.language browser property or navigator.userLanguage Internet Explorer property.

Setting the lang attribute on the html tag is the recommended practice because, in addition to setting the locale for the Oracle JET framework, it sets the locale for all HTML elements as well. The Oracle JET framework automatically loads the translations bundle for the current language and the locale bundle for the locale that was set. If you don't set a locale, the Oracle JET framework will default to the browser property.

Note:

The locale and resource bundles are loaded automatically only when your application uses the RequireJS ojl10n plugin. For information about using RequireJS in your Oracle JET application, see Using RequireJS for Modular Development.

Finally, Oracle JET includes validators and converters that use the locale bundles. When you change the locale on the page, an Oracle JET component has built in support for displaying content in the new locale. For additional information about Oracle JET's validators and converters, see Validating and Converting Input.

Note:

Oracle JET does not support input and output of a date-time value in a time zone other than the local time. As a result, Oracle JET can���t parse the ISO string returned by such JavaScript functions as toISOString().

Internationalizing and Localizing Oracle JET Applications

You can configure your application to use the Oracle JET framework's built-in support for internationalization and localization.

Topics:

- Using the Oracle JET Framework's Internationalization and Localization Support

- Enabling Bidirectional (BiDi) Support in Oracle JET

- Setting the Locale Dynamically

- Working with Currency, Dates, Time, and Numbers

Using the Oracle JET Framework's Internationalization and Localization Support

To use Oracle JET's built-in internationalization and localization support, you can simply specify one of the supported languages or locales on the lang attribute of the html element on your page. For example, the following setting will set the language to the French (France) locale.

<html lang="fr-FR">

If you want to specify the French (Canada) locale, you would specify the following instead:

<html lang="fr-CA">

Tip:
The lang specification isn���t case sensitive. Oracle JET will accept FR-FR, fr-fr, etc., and map it to the correct resource bundle directory.

When you specify the locale in this manner, any Oracle JET component on your page will display in the specified language and use locale constructs appropriate for the locale.

If the locale doesn���t have an associated resource bundle, Oracle JET will load the lesser significant language bundle. If Oracle JET doesn���t have a bundle for the lesser significant language, it will use the default root bundle. For example, if Oracle JET doesn���t have a translation bundle for fr-CA, it will look for the fr resource bundle. If the fr bundle doesn���t exist, Oracle JET will use the default root bundle and display the strings in English.

In the image below, the page is configured with the ojInputDateTime component. The figure shows the effect of changing the lang attribute to fr-FR.

If you type an incorrect value in the ojInputDateTime field, the error text is displayed in the specified language. In this example, the error is displayed in French.

Enabling Bidirectional (BiDi) Support in Oracle JET

If the language you specify uses a right-to-left (RTL) direction instead of the default left-to-right (LTR) direction, such as Arabic and Hebrew, you must specify the dir attribute on the html tag in addition to the lang attribute. The code below shows an example that specifies the Hebrew Israel (he-IL) locale with BiDi support enabled.

<html lang=he-IL dir="rtl">

The image below shows the same ojInputDateTime field that displays if you specify the Hebrew Israel locale and change the dir attribute to rtl.

Once you have enabled BiDi support in your Oracle JET application, you must still ensure that your application displays properly in the desired layout and renders strings as expected.

Note:

JET does not support the setting of the dir attribute on individual HTML elements which would cause a page to show mixed directions. Also, if you programmatically change the dir attribute after the page has been initialized, you must reload the page or refresh each JET component.

Setting the Locale Dynamically

You can configure your application to change the page's locale dynamically by using the oj.Config.setLocale() function:

setLocale(locale, callback)

The image below shows an Oracle JET application configured to display a button that displays a department list when clicked and a date picker. By default, the page is set to the en-US locale. Both the menu prompt and date picker are displayed in English.

The application also includes a button set in the header section which shows the United States of America, France, and Czech Republic flags. When the user clicks one of the flags, the page locale is set to the locale represented by the flag: en-US, fr-FR, or cs-CZ.

Note:

The flags used in this example are for illustrative use only. Using national flags to select a UI language is strongly discouraged because multiple languages are spoken in one country, and a language may be spoken in multiple countries as well. In a real application, you can use clickable text instead that indicates the preferred language to replace the flag icons.

The figure below shows the updated department list after the user clicks the French and Czech Republic flags.

The code that sets the locale in this example uses the oj.Config.setLocale() function call highlighted below. The menu is refreshed to reload the department list for the chosen locale.

// When the country flags are clicked we get a new language to set as the current locale
self.setLang = function(data) {
var newLang = '';
var lang = data.label;
switch (lang){
case '?e��tina':
newLang = 'cs-CZ';
break;
case 'fran��ais':
newLang = 'fr-FR';
break;
default:
newLang = 'en-US';
}
if (newLang !== 'fr-FR') {
if (($('html')[0].lang) !== 'fr-FR' || ($('html')[0].lang) === '') {
oj.Config.setLocale(newLang,
function() {
$('html').attr('lang', newLang);
// In this callback function we can update whatever is needed with the
// new locale. In this example, we reload the menu items.
loadMenu();
}
);
}
else {
window.location.assign('../index.html');
}
}
else {
window.location.assign('fr/index.html');
}
}

When the application changes the locale by calling refresh() on the Oracle JET inputDate component, the page will automatically update to use the new locale and display the date in the new locale. However, you must explicitly define the strings that appear in the menu items and then retrieve those strings using the oj.Translations.getTranslatedString() method.

getTranslatedString(key, var_args)

Note:

Do not use this functionality unless the application itself can switch the UI locale dynamically. Dynamically changing the UI locale often ends up with the UI in mixed languages or locales because the application may have cached data that are locale sensitive.

The code that loads the menu is shown below. The menu items and menu button labels are defined with a call to getTranslatedString(). The refresh() method of both the menu and date component are called after the translations and locale bundles are loaded for the new locale to refresh the display.

function viewModel() {
self = this;

// Setting up knockout observables for the button label and the menu items
self.localeLabel = ko.observable();
self.menuNames = ko.observableArray([]);

// This function adds the pulldown menu to the button when it's clicked.
self.addMenu = function(data, event) {
... contents omitted
}
self.setLang = function(data) {
... contents omitted
}

// This function loads the menu items.
function loadMenu() {
// These two lines are pulling the translated values for the menu items from
// the appropriate resource file in the /resources/nls directory.
self.menuNames(
[
{'itemName': oj.Translations.getTranslatedString('menu1')},
{'itemName': oj.Translations.getTranslatedString('menu2')},
{'itemName': oj.Translations.getTranslatedString('menu3')}
]
);
self.localeLabel(oj.Translations.getTranslatedString('label'));

// Since we've modified the children of the Oracle JET menu component, we need
// to refresh the menu component to get the built-in styling again.
$('#buttonMenu').ojMenu('refresh');

// Since the date component uses elements from the locale bundle,
// we must refresh the date component when the locale changes.
$('#dateInput').ojInputDate('refresh');
}

For information about defining your own translation strings and adding them to the Oracle JET resource bundle, see Adding Translation Bundles to Oracle JET.

When you use this approach to internationalize and localize your application, you must consider every component and element on your page and provide translation strings where needed. If your page includes a large number of translation strings, the page can take a performance hit.

Also, if SEO (Search Engine Optimization) is important for your application, be aware that search engines normally do not run JavaScript and access static text only.

Tip:

To work around issues with performance or SEO, you can add pages to your application that are already translated in the desired language. When you use pages that are already translated, the Knockout bindings are executed only for truly dynamic pieces.

Working with Currency, Dates, Time, and Numbers

When you use the converters included with Oracle JET, dates, times, numbers, and currency are automatically converted based on the locale settings. You can also provide custom converters if the Oracle JET converters are not sufficient for your application. For additional information about Oracle JET converters, see Using Oracle JET Converters. For information about adding custom converters to your application, see Using Custom Converters in Oracle JET.

Working with Oracle JET Translation Bundles

The Oracle JET framework includes a translation bundle that translates strings generated by Oracle JET components into all supported languages. You can add your own translation bundle by merging it with the Oracle JET bundle.

Topics

- About Oracle JET Translation Bundles

- Adding Translation Bundles to Oracle JET

About Oracle JET Translation Bundles

The Oracle JET framework includes a translation bundle that translates strings generated by Oracle JET components into all supported languages. You can add your own translation bundle following the same format used in Oracle JET.

The Oracle JET translation bundle follows a specified format for the content and directory layout but also allows some leniency regarding case and certain characters.

Translation Bundle Location

The RequireJS bootstrap file (usually main.js) contains the location of the Oracle JET translation bundle, which is named ojtranslations.js.

libs/oj/v1.1.2/resources/nls/ojtranslations

Each supported language is contained in a directory under the nls directory. The directory names use the following convention:

- lowercase for the language sub-tag (zh, sr, etc.)

- title case for the script sub-tag (Hant, Latn, etc.)

- uppercase for the region sub-tag (HK, BA, etc.)

The language, script, and region sub-tags are separated by hyphens (-). The following image shows a portion of the directory structure.

Top Level Module

The ojtranslations.js file contains the strings that Oracle JET translates and lists the languages that have translations. This is the top level module or root bundle. In the root bundle, the strings are in English and are the runtime default values when a translation isn���t available for the user���s preferred language.

Translation Bundle Format

The Oracle JET framework expects the top level root bundle and translations to follow a specified format. The root bundle contains the Oracle JET strings with default translations and the list of locales that have translations. // indicates a comment.

define({
// root bundle
root: {
"oj-message":{
fatal:"Fatal",
error:"Error",
warning:"Warning",
info:"Info",
confirmation:"Confirmation",
"compact-type-summary":"{0}: {1}"
},
// ... contents omitted
},

// supported locales.
"fr-CA":1,
ar:1,
ro:1,
"zh-Hant":1,
nl:1,
it:1,
fr:1,
//  ... contents omitted
tr:1,fi:1
});

The strings are defined in nested JSON objects so that each string is referenced by a name with a prefix: oj-message.fatal, oj-message.error, etc.

The language translation resource bundles contain the Oracle JET string definitions with the translated strings. For example, the following code sample shows a portion of the French (Canada) translation resource bundle, contained in nls/fr-CA/ojtranslations.js.

define({
"oj-message":{
fatal:"Fatale",
error:"Erreur",
warning:"Avertissement",
info:"Infos",
confirmation:"Confirmation",
"compact-type-summary":"{0}: {1}"
},
//  ... contents omitted
});

When there is no translation available for the user's dialect, the strings in the base language bundle will be displayed. If there are no translations for the user's preferred language, the root language bundle, English, will be displayed.

Named Message Tokens

Some messages may contain values that aren't known until run time. For example, in the message "User foo was not found in group bar", the foo user and bar group is determined at run time. In this case, you can define {username} and {groupname} as named message tokens as shown in the following code.

"MyUser":"User {username} was not found in group {groupname}."

At run time, the actual values are replaced into the message at the position of the tokens by calling oj.Translations.getTranslatedString() with the key of the message as the first argument and the parameters to be inserted into the translated pattern as the second argument.

var params = {'username': 'foo', 'groupname': 'bar'};
oj.Translations.getTranslatedString("MyKey", params);

Numeric Message Tokens

Alternatively, you can define numeric tokens instead of named tokens. For example, in the message "This item will be available in 5 days", the number 5 is determined at run time. In this case, you can define the message with a message token of {0} as shown in the following code.

"MyKey": "This item will be available in {0} days."

A message can have up to 10 numeric tokens. For example, the message "Sales order {0} has {1} items" contains two numeric tokens. When translated, the tokens can be reordered so that message token {1} appears before message token {0} in the translated string, if required by the target language grammar. The Javascript code that calls getTranslatedString() remains the same no matter how the tokens are reordered in the translated string.

Tip:

Use named tokens instead of numeric tokens to improve readability and reuse.

Escape Characters in Resource Bundle Strings

The dollar sign, curly braces and square brackets require escaping if you want them to show up in the output. Add a dollar sign ($) before the characters as shown in the following table.

Escaped Form

Output

$$

$

${

{

$}

}

$[

[

$]

]

For example, if you want your output to display [Date: {01/02/2015}, Time: {01:02 PM}, Cost: $38.99, Book Name: John's Diary], enter the following in your resource bundle string:

"productDetail": "$[Date: ${01/02/2015$}, Time: ${01:02 PM$}, Cost: $$38.99, Book Name: John's Diary$]"

Adding Translation Bundles to Oracle JET

You can add a translation bundle to Oracle JET by merging your new bundle with the existing Oracle JET translation bundle.

To add translation bundles to Oracle JET:

1. Define the translations.

For example, the following code defines a translation set for a menu containing a button label and three menu items. In this example, the default language is set to English, and the default label and menu items will be displayed in English. The root object in the file is the default resource bundle. The other properties list the supported locales, fr and cs.

define({
"root": {
"label": "Select a department",
"menu1": "Sales",
"menu2": "Human Resources",
"menu3": "Transportation"
},
"fr": true,
"cs": true
});

To add a prefix to the resource names (for example, department.label, department.menu1, and so on), add it to your bundles as shown below.

define({
"root": {
"department": {
"label": "Select a department",
"menu1": "Sales",
"menu2": "Human Resources",
"menu3": "Transportation"
}
}
},
"fr": true,
"cs": true
});

When the locale is set to a French locale, the French translation bundle is loaded. The code below shows the definition for the label and menu items in French.

define({
"label": "S��lectionnez un d��partement",
"menu1": "Ventes",
"menu2": "Ressources humaines",
"menu3": "Transports"
})

You can also provide regional dialects for your base language bundle by just defining what you need for that dialect.

define({
"label": "Canadian French message here"
});

Note:

When there is no translation available for the user's dialect, the strings in the base language bundle will be displayed. In this example, the menu items will be displayed using the French translations. If there are no translations for the user's preferred language, the root language bundle, whatever language it is, will be displayed.

2. Include each definition in a file located in a directory named nls.

For example, the default translation in the previous step is placed in a file named menu.js in the js/resources/nls directory. The French translation is located in a file named menu.js in the js/resources/nls/fr directory.

3. In the application's requireJS bootstrap file (typically main.js), add the bundle to the merge option in the ojL10n definition.

// This section configures the i18n plugin.
// It is merging the Oracle JET built-in translation resources
// with a custom translation file for the menu items used in this example.
// Any resource file added, must be placed under a directory named "nls".
// You can use a path mapping or you can define
// a path that is relative to the location of this main.js file.

config: {
ojL10n: {
merge: {
'ojtranslations/nls/ojtranslations': 'resources/nls/menu'
}
}
}

Note:

Oracle JET supports only one custom bundle to be merged with the default JET translation bundle. If your application has more than one translation bundle, combine them into one and then add the bundle to the merge option.

12 Theming Applications

The Oracle JET framework includes themes that provide styling across an application that you can use or customize as needed. You can also control the CSS content to specify which class or group of classes to include or exclude from your application.

Topics:

- Typical Workflow for Theming an Oracle JET Application

- About Oracle JET and Theming

- Customizing Oracle JET Themes

- Controlling CSS Content

- Understanding Oracle JET Theming For Compatibility

Typical Workflow for Theming an Oracle JET Application

To understand and customize the themes included in Oracle JET, refer to the typical workflow described in the following table:

Task

Description

More Information

Understand the theming features provided with Oracle JET

Identify the themes provided with Oracle JET and understand how Oracle JET uses SCSS to generate CSS.

About Oracle JET and Theming

Customize an Oracle JET application's theme

Add customized SCSS files to an Oracle JET application.

Customizing Oracle JET Themes

Control CSS content

Use variable control and partial imports to control CSS content.

Controlling CSS Content

Understand theming for compatibility

Understand Oracle JET's use of tag selectors, REM (root em), and normalize.js.

Understanding Oracle JET Theming For Compatibility

About Oracle JET and Theming

The Oracle JET framework provides the Alta theme that you can use or customize in your Oracle JET applications, or you can provide our own themes for integration into an Oracle JET application. The Alta theme is based on Oracle Alta UI, a mobile and browser application design system.

The CSS files included with Oracle JET are generated by the Sass preprocessor. The Oracle JET distribution includes the SCSS configuration files used to generate the CSS files which are also included in the Oracle JET distribution.

Topics:

- CSS Files Included With Oracle JET

- DOCTYPE Requirement

- SCSS and Oracle JET

- SCSS Tools

For information about Sass, see http://sass-lang.com. For additional information about Oracle Alta UI, see http://www.oracle.com/webfolder/ux/middleware/alta/index.html.

CSS Files Included With Oracle JET

Oracle JET includes the following generated CSS files for the Alta theme:

- oj-alta.css: Readable version of the CSS for the Alta theme

- oj-alta-min.css: Minified version of the CSS for the Alta theme

- oj-alta-notag.css: Readable version of the CSS generated without tag selectors
For additional details about Oracle JET theming and tag selectors, see Using Tag Selectors or Classes.

- oj-alta-notag-min.css: Minified version of the CSS generated without tag selectors

You can find the Alta CSS files in the css/libs/oj/1.1.0/alta directory.

DOCTYPE Requirement

In order for Oracle JET's theming to work properly, you must include the following line at the top of all HTML5 pages:

<!DOCTYPE html>

If you don't include this line, the CSS in your application may not function as expected. For example, you may notice that some elements aren't properly aligned.

SCSS and Oracle JET

The SCSS files that Oracle JET uses to preprocess the CSS files are included in the Oracle JET distribution. The following table lists the directory structure for the SCSS files.

Directory

Description

alta

Contains files for the Alta theme.

common

Contains files shared by both themes. These files should not be referenced directly for imports.

utilities

Sass mixins and functions used by Oracle JET.

3rdparty

Contains Oracle JET's version of third party files, such as normalize.

Oracle JET follows the Sass underscore naming convention. Files that start with an underscore are called partials and are not compiled independently with Sass. Instead, the partials are imported into an aggregating file. There is one partial file per module, for example, _oj.table.scss, _oj.formcontrol.inputnumber.scss, and so on.

The following table lists the directory structure for the files contained within the alta directory.

Directory

Files

Description

alta/widgets

_oj.alta.formcontrol.inputnumber.scss

_oj.alta.table.scss

etc.

Alta widget partial files

alta

_oj.alta.variables.scss

_oj.alta.settings.scss

_oj.alta.widgets.scss

oj-alta.scss

Contains the SCSS variables

Contains a commented version of the variables file that you can remove the comments from and modify

Imports widget partial files

Generates the oj-alta.css and oj-alta-min.css files

SCSS Tools

Sass supports source maps which can make it easier to work with a large number of partial files, as in Oracle JET. Oracle JET includes source maps for the default and no tag selector versions of the generated CSS for the Alta theme: oj-alta.css.map, and oj-alta-notag.css.map.

For additional information about source maps, see https://developers.google.com/chrome-developer-tools/docs/css-preprocessors.

Customizing Oracle JET Themes

You can use the Oracle JET SCSS files to customize themes. At build time, Oracle JET uses Sass to convert the alta/oj.alta.scss aggregating files to CSS. You can also use Sass to generate your own themes.

Topics:

- Customizing an Oracle JET Theme Using Sass

- Working with Framework Images in an Oracle JET Application

- Understanding Oracle JET Marker Styles

- Controlling Initial Visibility with CSS

- Understanding Right-to-Left Behavior

- Understanding Oracle JET and Browser Degradation

- Printing Oracle JET Pages

Customizing an Oracle JET Theme Using Sass

You can use Sass to customize an Oracle JET theme.

To customize an Oracle JET theme using Sass:

1. Install Sass and Ruby as needed. For details, see http://sass-lang.com/install. Once you have Ruby, type the following command to install Sass:

gem install sass

If you normally use a proxy to connect to the internet, issue the following command instead:

gem install sass --http-proxy proxyurl

2. Create a custom settings file using the naming convention:_filename.scss. You can either:

- Create an empty file and add the variables you need, or

- Copy the theme's settings file to a new file

For example, create an empty file named _myCustomSettings.scss, or copy _oj.alta.settings.scss into a file named _myCustomSettings.scss.

3. In your custom settings file, set variables as needed for your application. If you copied the settings file, remove the comment from the variable before setting it.

For example, to turn off tag selectors, remove the comment from the $allowTagSelectors variable if needed and set it to false.

$allowTagSelectors: false;

For information about Oracle JET's use of tag selectors, see Using Tag Selectors or Classes.

4. Create partial override files to customize your CSS as needed. Be sure to follow the underscore naming convention used by Sass and Oracle JET for your partials.

The example below shows a partial override file named _myCustomProgressBar.scss that overrides the height and width defaults for the Oracle JET ojProgressbar component.

.oj-progressbar {
// override the JET defaults for height and width
height: 20px;
width: 400px;
}

5. Create an aggregating SCSS file and import the partial override files.

The example below shows a custom aggregating file that imports a custom settings file, the Alta files, and the custom overrides.

//IMPORT CUSTOM SETTINGS
@import "myCustomSettings";

//IMPORT THE ALTA FILES
@import "../oj/alta/oj-alta";

//IMPORT CUSTOM FILES (after alta files)
@import
"myCustomProgressBar",
[... etc. all the custom overrides ...];

6. To control what content gets included in your CSS, see Controlling CSS Content.

Working with Framework Images in an Oracle JET Application

Oracle JET uses icon fonts whenever possible to render images provided by the Alta theme. When icon fonts are not possible, Oracle JET uses image files. In either case, framework images support high contrast mode. Oracle JET also provides CSS classes for most framework images.

Topics:

- Image Considerations

- Icon Fonts

- Image Files

For examples of framework images, see Framework Images.

Image Considerations

There are a variety of ways to load icons, such as sprites, data URIs, icon fonts, and so on. Factors to consider when choosing an image strategy include:

- Themable: Can you use CSS to change the image? Can you replace a single image easily?

- High contrast mode: Does the image render properly in high contrast mode for accessibility?

- High resolution support: Does the image look acceptable on high resolution (retina) displays?

- Browser support: Do you require support for all browsers? Some browsers may not support certain image formats, such as SVG.

- Image limitations: Are there limitations that impact your use case? For example, icon fonts are a single color, and small SVG images often do not render well.

- Performance: Is image size a factor? Do you need alternate versions of an image for different resolutions or states such as disabled, enabled, hover, and active?

Icon Fonts

Oracle JET uses icon fonts whenever possible because icon fonts have certain advantages over other formats.

- Themable: You can use style classes to change their color instead of having to replace the image, making them very easy to theme.

- High contrast mode: Icon fonts are optimal for high contrast mode as they are considered text. However, keep in mind that you can't rely on color in high contrast mode, and you may need to indicate state (active, hover, and so on) using another visual indicator. For example, you can add a border or change the icon font's size. For additional information about Oracle JET and high contrast mode, see Configuring High Contrast Mode.

- High resolution: Icon fonts look good on a high resolution (retina) display without providing alternate icons.

- Performance: You can change icon font colors using CSS so alternate icons are not required to indicate state changes. Alternate images are also not required for high resolution displays.

Icon fonts also have disadvantages. It can be difficult to replace a single image, and they only show one color. You can use text shadows to provide some depth to the icon font.

Oracle JET supports two generic classes for setting the icon font colors in the $iconColorDefault, $iconColorHover, $iconColorActive, $iconColorSelected, and $iconColorDisabled variables.

- oj-clickable-icon

- oj-clickable-icon-nocontext

These classes, when used in conjunction with an anchor tag and/or marker classes like oj-default, oj-hover, oj-focus, oj-active, oj-selected, and oj-disabled, will use the $iconColor* variables.

The oj-clickable-icon class is optionally contextual, meaning the anchor or marker style can be on an ancestor as shown in the example below. The example assumes that a JavaScript method is replacing oj-default as needed with oj-hover, oj-focus, oj-active, oj-selected, and oj-disabled.

<div class="oj-default">
<span class="oj-clickable-icon demo-icon-font demo-icon-gear"></span>
</div>
<a href="http://www.oracle.com">
<span class="oj-clickable-icon demo-icon-font demo-icon-gear"></span>
</a>

The oj-clickable-icon-nocontext class is not contextual and must be placed on the same tag as shown in the example below. oj-clickable-icon would also work in this example.

<span class="oj-default oj-clickable-icon-nocontext demo-icon-font demo-icon-gear">
</span>
<a href="http://www.oracle.com"
class="oj-clickable-icon-nocontext demo-icon-font demo-icon-gear">
</a>

For an example that illustrates icon font classes on a link, see Icon Fonts.

Image Files

Oracle JET uses images when icon fonts can't be used. Informational images must appear in high contrast mode for accessibility, as described in Configuring High Contrast Mode.

Oracle JET provides Sass mixins that you can use to create CSS for your own icons. For examples, see CSS Images.

Understanding Oracle JET Marker Styles

Oracle JET provides marker styles that can be used instead of CSS3 and CSS4 pseudo classes. For example, the oj-hover class can be used instead of the :hover pseudo class typically used in CSS3. The advantage of using a marker style is that you can use the same style on any DOM element.

The following table lists the Oracle JET marker styles and their CSS3 and jQuery UI equivalent.

Oracle JET Marker Style

CSS3 Inspiration

jQuery UI Equivalent

Description

Accessibility:

oj-hicontrast

This marker is placed on the body tag by either a script or the application. For details, see Configuring High Contrast Mode.

Component:

oj-component

ui-widget

Marks the root DOM element of a widget.

oj-component-initmode

Mark the init DOM element of a widget. This can be different than the root DOM element if the init node was wrapped by other DOM. For example, in an ojInputNumber component, the init node is an input element, but this is wrapped by other DOM when the component is created.

Link:

oj-visited

:visited

Applied when user visits the link or item.

Input:

oj-disabled

:disabled

oj-enabled

:enabled

ui-state-default

oj-read-only

oj-invalid

oj-warning

oj-required

oj-indeterminate

:indeterminate

User Action:

oj-active

:active

ui-state-active

jQuery UI uses ui-state-active for both active and selected states. Oracle JET provides separate styling markers for active and selected/checked/toggled states so that you can style these states separately.

oj-selected

ui-state-active

See previous explanation.

Used when something is selected, checked, or toggled on.

oj-hover

:hover

ui-state-hover

:hover works on any DOM element but only on the closest DOM element currently hovered over.

:oj-hover can be placed on an element which is an ancestor of the element being hovered over. For example if you're hovered over an icon in a button, oj-hover may be placed on the button tag, which is the ancestor of the tag with the icon.

oj-focus

:focus

ui-state-focus

oj-focus-only

Used when something is focused, but you only want to set the style when oj-selected, oj-hover, oj-active are not set.

oj-default

Used when something is clickable, but you only want to set the style when oj-selected, oj-hover, oj-focus, and oj-active are not set.

For example, the following code will render the text white only when the button is not in a selected, hover, focus, or active state.

.demo-appheader-toolbar .oj-button.oj-default .oj-button-text {
color: white; }

Collapsible:

oj-expanded

Used when something expandable is expanded.

oj-collapsed

Used when something expandable is collapsed, meaning that it's not expanded.

Alignment:

oj-right

oj-center

oj-left

oj-start

oj-end

Indicates the horizontal position, such as the tail of a popup.

oj-top

oj-middle

oj-bottom

Indicates the vertical position, such as the tail of a popup.

Oracle JET also provides the following marker styles that can be used instead of CSS4 pseudo classes.

Oracle JET Marker Style

CSS4 Inspiration

jQuery UI Equivalent

Description

Drag and Drop:

oj-draggable

Used on draggable elements.

oj-drag

Used on element when dragged.

oj-drop

:drop

Applies to all elements that are drop targets during a drag.

oj-active-drop

:drop (active)

Used on element that will receive the item currently being dragged.

oj-valid-drop

:drop (valid)

Used on elements that can receive the item currently being dragged.

oj-invalid-drop

:drop (invalid)

Used on elements that can't receive the item currently being dragged.

Internally, Oracle JET follows these rules for clickable elements:

Oracle JET Marker Style

Used if Widget is Disabled?

oj-enabled or oj-disabled

oj-enabled: no

oj-disabled: yes

oj-selected

Yes

oj-active

No

oj-hover

No

oj-focus

No

oj-focus-only

No

oj-default

No

For additional information about the CSS3 selectors, see http://www.w3.org/TR/css3-selectors/. For more information about the CSS4 selectors, see http://dev.w3.org/csswg/selectors4/.

Controlling Initial Visibility with CSS

You can set an Oracle JET component's CSS visibility property to hidden on the DOM until the component is initialized using the $initialVisibility variable. The component will still occupy space on the page, but the user will not see the component during page load.

// when $initialVisiblity is hidden then visibility: hidden is set on the DOM until the
// component is initialized. This reduces the unstyled DOM seen by the user during page load.
$initialVisibility: hidden !default

In addition to using this variable, you may also want to inline the following CSS into the head section of the first page so that uninitialized DOM is hidden even before the CSS file is downloaded and cached.

<style>
[data-bind*="ojComponent"]:not(.oj-component-initnode) {
visibility: hidden;
}
</style>

For more information about the CSS visibility property, see http://www.w3.org/wiki/CSS/Properties/visibility.

Understanding Right-to-Left Behavior

By default, the same CSS is used for right-to-left and left-to-right behavior, even if you set dir=rtl on the HTML tag. If you prefer to generate one CSS file for each direction, you can set the $textDirection variable to rtl or ltr.

Oracle JET does not support multiple directions on a page. The reason this is not supported is that the proximity of elements in the document tree has no effect on the CSS specificity, so switching directions multiple times in the page may not work the way you might expect. The code sample below shows an example.

<style>
[dir=ltr] .foo {color: blue}
[dir=rtl] .foo {color: red}
</style>
<span dir="rtl">
<span dir="ltr">
<span class="foo">You might think I will be blue because dir=ltr is on,
a closer ancestor than dir=rtl. But css doesn't care
about proximity, so instead I am red
(because [dir=rtl] .foo {color: red} was defined last).
Isn't that surprising?
</span>
</span>
</span>

For additional information about Oracle JET and bidirectional support, see Enabling Bidirectional (BiDi) Support in Oracle JET. For more information about CSS specificity, see https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity.

Understanding Oracle JET and Browser Degradation

Certain browsers that Oracle JET supports may not support CSS properties such as animations, box shadows, and so on. This is considered acceptable as long as it degrades in a reasonable fashion. For example you may not get any animations on that browser, and you will just get a border instead of a box shadow.

On other browsers, for performance reasons, Oracle JET will not render a border radius, box shadow, or gradient, even if the browser supports it. For example, on Internet Explorer, Oracle JET sets the border radius to 0, as shown in the following example.

.oj-button {
border-radius: 2px;
}

.oj-slow-borderradius .oj-button {
border-radius: 0;
}

Internet Explorer has two rendering modes, GPU and software rendering. Performance for these CSS properties can be very slow in software rendering mode, and even GPU rendering has been slow in many cases. Also, Oracle JET has no way to determine which rendering mode is being used. Therefore, in Oracle JET the oj-slow-* classes are used in all supported versions of Internet Explorer.

You can control the behavior of the border radius, gradient, and box shadow by setting the following variables:

- $borderRadiusGeneration

- $gradientGeneration

- $boxShadowGeneration

Valid options for these variables include:

- slowOverride (default): Generate the regular value but also generate overrides for slow browsers to remove the border radius, gradient, and box shadow on slow browsers.

- on: Generate only the regular value. Do not generate overrides.

- off: Do not generate a regular or override value. This setting is useful if you want to design style sheets specifically for Internet Explorer only.

Printing Oracle JET Pages

Oracle JET includes styles that implement responsive printing through print media queries.

In general, printing should look reasonable on most screens. However, you may need to require the end user to turn on background colors and images before printing, which are off by default for most browsers. For example, in the Chrome Print dialog, your end user may need to select the Background colors and images checkbox.

Also, Oracle JET removes some background images in high contrast mode. For more information about high contrast mode and workarounds for displaying images even when background images are disabled, see Configuring High Contrast Mode.

For additional information about responsive classes and printing, see Oracle JET and Responsive Web Design.

Controlling CSS Content

The Oracle JET theming framework provides methods for controlling the partials used in your application.

Topics:

- Using Variables to Control CSS Content

- Using Import Control to Define CSS Content

Using Variables to Control CSS Content

You can use the $includeAllClasses variable in your SCSS settings file to control content for the entire application. By default, the variable is set to true as shown below.

// by default everything is included, but you can also start by setting
// $includeAllClasses to false and then just add in what you want.
$includeAllClasses: true !default;

Some partials also allow you to control their content with a variable near the top of the partial file. For example, the ojButton component has the $includeButtonClasses variable near the top of the _oj.alta.button.scss file.

$includeButtonClasses: $includeAllClasses !default;

To exclude the ojButton style classes, you can set $includeButtonClasses to false as shown below.

$includeButtonClasses: false;

Oracle JET also uses several higher level groupings that let you control the CSS for a logical group of components. The table lists the groups that are available for your use.

Group

SCSS Variable

File Names

Tags (headers, links, and so on)

$includeTagClasses: $includeAllClasses !default;

Files with tag in name, as in:

_oj.alta.tags.typography

Data visualizations (charts, gauges, and so on)

$includeDvtClasses: $includeAllClasses !default;

Files with dvt in name, as in:

_oj.alta.dvt.chart

Form controls (labels, combo box, and so on)

$includeFormControlClasses: $includeAllClasses !default;

Files with formcontrol in name, as in:

_oj.alta.formcontrol.label

You can include or exclude classes and groups as shown in the following examples.

// Example: Exclude the dvt classes
$includeDvtClasses: false;

// Example: Include only the dvt classes, exclude everything else
$includeAllClasses: false;
$includeDvtClasses: true;

// Example: Include the chart and sunburst classes, exclude everything else
$includeAllClasses:      false;
$includeChartClasses:    true;
$includeSunburstClasses: true;

Note:

Some components depend on others. For example, the ojInputNumber uses ojButton internally, so if you include the ojInputNumber classes, you will also get the ojButton classes automatically.

Using Import Control to Define CSS Content

You can use imports in your aggregating SCSS file to control the CSS content as shown in the following custom SCSS file:

@import "../oj/alta/oj.alta.variables";

@import "../oj/3rdparty/normalize/normalize";

// instead of importing all the widgets, just import the widget files you actually want
@import "../oj/alta/widgets/oj.alta.widgetone";
@import "../oj/alta/widgets/oj.alta.widgettwo";

Understanding Oracle JET Theming For Compatibility

There may be cases where you do not want to use aspects of the default theming because it causes compatibility issues. For example, you may be embedding JET components or regions in a page controlled by another technology, such as Oracle ADF. Oracle JET provides several options for controlling use of tag selectors, REM, and normalize.css.

Topics:

- Using Tag Selectors or Classes

- Using REM

- Using Normalize

Using Tag Selectors or Classes

By default, Oracle JET applies styles directly to HTML tag elements such as a, h1, h2, and so on. This feature makes it easier to code a page since you do not have to apply selectors to each occurrence of the element.

The following code shows a portion of a custom SCSS file that defines styles for link and header tags. When the CSS file is generated, the styles will be applied directly to the link and header tags.

/* links */
a {
color: $linkTextColor;
line-height: inherit;
text-decoration: none;
}

a:visited {
color: $linkTextColorVisited;
}

/* headers */
h1, h2, h3, h4 {
color: $headerTextColor;
font-family: inherit;
font-style: normal;
font-weight: $headerFontWeight;
margin: 10px 0;
}

If you do not want to apply styles directly to the tags, you can specify that Oracle JET use classes instead of tag selectors in your custom.scss file:

$allowTagSelectors: false;

// theme import
@import "../oj.alta/oj-alta";

The code below shows the classes that Oracle JET will use for the Alta theme's links and headers when you set $allowTagSelectors to false. To use the class on your page, specify the class in the tag element on your page (<a class=oj-link>).

/* links */
.oj-link {
color: $linkTextColor;
line-height: inherit;
text-decoration: none;
}

.oj-link:visited {
color: $linkTextColorVisited;
}

/* headers */
.oj-header {
color: $headerTextColor;
font-family: inherit;
font-style: normal;
font-weight: $headerFontWeight;
margin: 10px 0;
}

The following table lists the HTML tags with default Oracle JET tag styles and the corresponding Oracle JET class.

HTML Tag

Oracle JET Style Class

html

oj-html

body

oj-body

a

oj-link

h1, h2, h3, h4

oj-header

hr

oj-hr

p

oj-p

ul, ol

oj-ul, oj-ol

If you also do not want to use the Oracle JET tag classes, you can set $includeTagClasses to false in your custom.scss file as shown below.

$includeTagClasses:false;

Using REM

By default, Oracle JET uses REM (root em) for font sizing. This means that a specific font size is set on the root (html) element, and other font sizes are defined relative to that root size. The following example shows the default font sizing for the Alta theme.

// The browser usually uses 16px and the Alta default is 14px.
// Therefore set $rootFontValue to .875em to get 14px;
$rootFontSize:    .875em !default;    // 14px

$fontSize:        1rem !default;    // 14px
$smallFontSize:   .857rem !default;    // 12px when root 14px
$mediumFontSize:  1.143rem !default;    // 16px when root 14px
$largeFontSize:   1.286rem !default;    // 18px when root 14px
$largestFontSize: 1.429rem !default;    // 20px when root 14px

To use REM, the font size must be set on the html element. If you want to use REM but do not want to set a style directly on the html tag, you can reference the oj-html class as described in Using Tag Selectors or Classes.

If you do not want to use REM, you can specify an alternate font size by modifying a custom.scss file to use the units your application requires. The code sample below shows how you could use pixels instead of rems to set font sizes.

// use px instead of rem for fonts
$rootFontSize:    12px;
$fontSize:        $rootFontSize;
$smallFontSize:   $rootFontSize - 1px;
$mediumFontSize:  $rootFontSize + 2px;
$largeFontSize:   $rootFontSize + 4px;
$largestFontSize: $rootFontSize + 6px;

For additional information about REM, see http://snook.ca/archives/html_and_css/font-size-with-rem.

Using Normalize

By default, Oracle JET uses normalize.css to promote consistency when rendering across browsers. If your application also uses normalize.css, add the import in your custom.scss:

@import "../3rdparty/normalize/normalize";

If you do not want to use normalize, you can set the following variable to false in your custom.scss:

$includeNormalize: false;

Alternatively, you can set $allowTagSelectors to false as described in Using Tag Selectors or Classes.

For additional information about normalize.css, see http://necolas.github.io/normalize.css.

13 Securing Applications

The Oracle JET framework follows security best practices for Oracle JET components and provides the oj.OAuth class to help you manage access to users' private data.

Topics:

- Typical Workflow for Securing Oracle JET Applications

- About Securing Oracle JET Applications

- Using oj.OAuth in Your Oracle JET Application

Typical Workflow for Securing Oracle JET Applications

To develop secure Oracle JET applications, refer to the typical workflow described in the following table:

Task

Description

More Information

Understand Oracle JET application security

Identify Oracle JET security features and which tasks you should take to secure your Oracle JET application.

About Securing Oracle JET Applications

Use oj.OAuth

Use Oracle JET oj.OAuth plugin.

Using oj.OAuth in Your Oracle JET Application

About Securing Oracle JET Applications

Oracle JET applications are client-side HTML applications written in JavaScript, and you should follow best practices for securing your Oracle JET applications.

There are a number of Internet resources available that can assist you, including the Open Web Application Security Project (OWASP), Web Application Security Project (WASP), Web Application Security Working Group (WASWG), and various commercial sites.

Topics:

- Oracle JET Components and Security

- Oracle JET Framework Security Features

- Oracle JET Security and Developer Responsibilities

The Oracle JET framework includes components that follow best practices for security and provides the oj.OAuth plugin for providing secure access to a user's private data. However, the application developer is expected to perform tasks that are not included in the Oracle JET framework, such as sanitizing strings.

Oracle JET Components and Security

Oracle JET components follow best practices for security. In particular:

- All JavaScript code is executed in strict mode using the use strict directive.
Strict mode changes warnings about poor syntax, such as using undeclared variables, into actual errors that you must correct. For more information, see http://www.w3schools.com/js/js_strict.asp.

- Oracle JET code does not use inline script elements.
Because browsers can't tell where the inline script originated, the World Wide Web Consortium (W3C) Content Security Policy prohibits the use of inline scripts. For additional information, see https://w3c.github.io/webappsec/specs/content-security-policy.

- Oracle JET code does not generate random numbers.

- Any HTML generated by an Oracle JET component is ether escaped or sanitized.
For information about why this is needed, see https://www.owasp.org/index.php/DOM_based_XSS_Prevention_Cheat_Sheet#Guidelines_for_Developing_Secure_Applications_Utilizing_JavaScript.

Oracle JET Framework Security Features

The Oracle JET API provides the oj.OAuth authorization plugin which supports the OAuth 2.0 open protocol. OAuth standardizes the way desktop and web applications access a user's private data. It provides a mechanism for users to grant access to private data without sharing their private username and password credentials.

OAuth 2.0 defines the following roles:

- Resource owner: An entity that can grant access to a protected resource, such as the end user.

- Client: Application making protected and authorized resource requests on behalf of the resource owner.

- Resource server: Server hosting the protected resources that can accept and respond to protected resource requests using access tokens.

- Authorization server: Server that issues access tokens to the client after it successfully authenticates the resource owner and obtains authorization.

Note:

The authorization server can be the same server as the resource server. In addition, an authorization server can issue access tokens accepted by multiple resource servers.

OAuth 2.0 Request for Comments (RFC) 6749 describes the interaction between the four roles as an abstract flow.

1. The client requests authorization from the resource owner, either directly or through the authorization server.

Note:

The RFC specifies that the authorization server is preferred.

2. The client receives an authorization grant, which is defined as the credential representing the resource owner's authorization.

3. The client requests an access token from the authorization server by authenticating with the server and presenting the authorization grant.

4. The authorization server issues the access token after authenticating the client and validating the authorization grant.

5. The client presents the access token to the resource server and requests the protected resource.

6. The resource server validates the access token and serves the request if validated.

The access token is a unique identifier issued by the server and used by the client to associate authenticated requests with the resource owner whose authorization is requested or has been obtained by the client.

The Oracle JET oj.OAuth plugin provides functions for the following tasks:

- Getting access token credentials if initialized by client credentials.

- Caching access token credentials.

- Creating the header array with bearer token.

For details about using the oj.OAuth plugin, see Using oj.OAuth in Your Oracle JET Application. For additional information about OAuth 2.0, see http://tools.ietf.org/html/rfc6749.

Oracle JET Security and Developer Responsibilities

Oracle JET components follow established security guidelines and ensure that strings provided as options and user input will never be executed as JavaScript to prevent XSS attacks. However, the Oracle JET framework does not include a mechanism for sanitizing strings, and you should consult established guidelines for dealing with XSS attacks in your own code and content.

You can find more information about securing JavaScript applications at https://www.owasp.org/index.php/DOM_based_XSS_Prevention_Cheat_Sheet#Guidelines_for_Developing_Secure_Applications_Utilizing_JavaScript.

Using oj.OAuth in Your Oracle JET Application

You can use the oj.OAuth plugin to manage access to client (end user) private data. The Oracle JET API includes the OAuth class which provides the methods you can use to initialize the oj.OAuth object, verify initialization, and calculate the authorization header based on client credentials or access token.

Topics:

- Initializing oj.OAuth

- Verifying oj.OAuth Initialization

- Obtaining the OAuth Header

- Using oj.OAuth with Oracle JET Common Model

- Integrating oj.OAuth with Oracle Identity Management (iDM) Server

Initializing oj.OAuth

You can create an instance of a specific oj.OAuth object using the oj.OAuth constructor:

new OAuth(header, attributes)

The attributes and header parameters are optional.

Parameter

Type

Description

header

String

MIME Header name. Defaults to Authorization

attributes

Object

Contains client credentials or access/bearer token.

Client credentials contain:

- client_id (required): public client Credentials

- client_secret (required): secret client credentials

- bearer_url (required): URL for token bearer and refresh credentials

- Additional attributes as needed (optional)

Access/bearer tokens contain:

- access_token (required): Bearer token

- Additional attributes as needed (optional)

The code sample below shows three examples for initializing oj.OAuth.

// Initialize oj.OAuth with client credentials
var myOAuth = new oj.OAuth('X-Header', {...Client credentials...});

// Initialize oj.OAuth with token credentials
var myOAuth = new oj.OAuth('X-Header', {...Access/Bearer token...});

// Initialize oj.OAuth manually
var myOAuth = new oj.OAuth();

If you choose to initialize oj.OAuth manually, you can add the client credentials or access/bearer token using methods shown in the following code sample.

// Initializing client credentials manually
myOAuth.setAccessTokenRequest({...Client Credentials ...});
myOAuth.clientCredentialGrant();

// Initializing access bearer token manually
myOAuth.setAccessTokenResponse({...Access Token...});

The OAuth API also includes methods for getting and cleaning the client credentials or access tokens. For additional information, see the oj.OAuth API documentation.

Verifying oj.OAuth Initialization

Use the isInitialized() method to verify that the initialization succeeded.

var initFlag = myOAuth.isInitialized();

Obtaining the OAuth Header

Use the getHeader() method to get the OAuth header. The method calculates the authorization header based on the client credentials or access token.

// Client credentials
var myOAuth = new oj.OAuth('New-Header', {...Client credentials...});
var myHeaders =  myOAuth.getHeader();

// Access token
var myOAuth = new oj.OAuth('New-Header', {...Access/Bearer token...});
var myHeaders =  myOAuth.getHeader();

// Manual initialization, client credentials
var myOAuth = new oj.OAuth();
myOAuth.setAccessTokenRequest({...Client credentials...});
var myHeaders =  myOAuth.getHeader();

// Manual initialization, access token
var myOAuth = new oj.OAuth('New-Header', {...Access/Bearer token...});
var myHeaders =  myOAuth.getHeader();

Using oj.OAuth with Oracle JET Common Model

You can add the oj.OAuth object to your viewModel, either embedded or as an external plugin.

Topics:

- Embedding oj.OAuth in Your Application's ViewModel

- Adding oj.OAuth as a Plugin in Your View Model

For information about Oracle JET's Common Model, see Using the Common Model and Collection API.

Embedding oj.OAuth in Your Application's ViewModel

The code sample below shows how you could embed the oj.OAuth object in your ViewModel. This example initializes oj.OAuth with client credentials.

function viewModel() {
var self = this;
...
self.myOAuth = new oj.OAuth('X-Authorization', {...Client credentials...});

var tweetModel = oj.Model.extend({
...
});
var myTweet = new tweetModel();
...
var tweetCollection = oj.Collection.extend({
model: myTweet,
oauth: self.myOAuth, // using embedded feature
...
});
self.myTweetCol = new tweetCollection();
...
self.myTweetCol.fetch({
success: function(collection, response, options) {
...
},
error: function(jqXHR, textStatus, errorThrown) {
... // process errors
}
});
}

To embed the oj.OAuth object in your ViewModel and initialize it with a bearer/access token:

function viewModel() {
var self = this;
...
self.myOAuth = new oj.OAuth('X-Authorization', {...Access/Bearer token...});

var tweetModel = oj.Model.extend({
...
});
var myTweet = new tweetModel();
...
var tweetCollection = oj.Collection.extend({
model: myTweet,
oauth: self.myOAuth, // using embedded feature
...
});
self.myTweetCol = new tweetCollection();
...
self.myTweetCol.fetch({
success: function(collection, response, options) {
...
},
error: function(jqXHR, textStatus, errorThrown) {
... // process errors or insert new access_token and re-fetch
}
});
}

Adding oj.OAuth as a Plugin in Your View Model

The code sample below shows how you could add the oj.OAuth object as a plugin in your viewModel. This example initializes oj.OAuth with client credentials.

var viewModel() {
var self = this;
...
self.myOAuth = new oj.OAuth('X-Authorization', {...Client credentials...});

var tweetModel = oj.Model.extend({
...
});
var myTweet = new tweetModel();
...
var tweetCollection = oj.Collection.extend({
model: myTweet,
...
});
self.myTweetCol = new tweetCollection();
...
self.preFetch = function() {
var header = self.myOAuth.getHeader();
$.ajaxSetup({
beforeSend: function (xhr){
for(var hdr in header ) {
if(header.hasOwnProperty(hdr))
xhr.setRequestHeader(hdr, header[hdr]);
}
}
}
});
self.myTweetCol.fetch({
success: function(collection, response, options) {
...
},
error: function(jqXHR, textStatus, errorThrown) {
... // process errors
}
});
}
}

Integrating oj.OAuth with Oracle Identity Management (iDM) Server

Oracle iDM servers use a two-legged authorization (Resource Owner Password Credentials Grant). In addition, the iDM servers require that you do the following:

- Keep client credentials on your own proxy server. If you don't have one, you must create one.

- iDM servers use a non standard authorization header and require that Authorization:access_token be used instead of Authorization: Bearer access_token. To supply the custom header, you must rewrite the OAuth header for specific Authorization using the getHeader() method.
The code except below shows an example that adds the oj.OAuth object with a modified header to the application's viewModel.

function viewModel() {
var self = this;
self.bearer = {
access_token: ...,
token_type: "Bearer",
expires_in: ...
...
}
...
self.myOAuth = new oj.OAuth();
// Rewrite oAuth header for specific Authorization
self.myOAuth.getHeader = function() {
var headers = {};
headers['X-Authorization']=self.bearer.access_token;
return headers;
}
var idmModel = oj.Model.extend({     ...  });  var myIDM = new idmModel();  ...  var idmCollection = oj.Collection.extend({     model: myIDM,     oauth: self.myOAuth, // using embedded feature     ...  });  self.myIDMCol = new idmCollection();  ...  self.myIDMCol.fetch({     success: function(collection, response, options) {
...
},
error: function(jqXHR, textStatus, errorThrown) {
... // process errors or insert new access_token and re-fetch
}
});
}

14 Optimizing Performance

Oracle JET applications are client-side HTML5 applications. Most performance optimization recommendations relating to client-side HTML applications also apply to applications developed using the Oracle JET framework or Oracle JET components. In addition, some Oracle JET components have performance recommendations that are specific to the component.

Topics:

- Typical Workflow for Optimizing Performance of Oracle JET Applications

- About Performance and Oracle JET Applications

- Adding Performance Optimization to an Oracle JET Application

Typical Workflow for Optimizing Performance of Oracle JET Applications

To optimize performance of an Oracle JET application, refer to the typical workflow described in the following table:

Task

Description

More Information

Identify general performance optimization goals

Identify performance optimization goals for client-side HTML5 applications.

About Performance and Oracle JET Applications

Apply performance optimization to your Oracle JET application

Take specific steps to optimize performance of your application.

Adding Performance Optimization to an Oracle JET Application

About Performance and Oracle JET Applications

In general, you can optimize an Oracle JET application the same way that you would optimize performance for any client-side HTML5 application.

There are many online resources that provide tips for performance optimization. For example, the Google Developers website describes processes for:

- Optimizing caching

- Minimizing round trip times between the client and the server

- Minimizing the payload size (downloads, responses, and cached pages)

- Minimizing request overhead (upload size)

- Improving browser page layout

- Optimizing performance on mobile devices

Most of these recommendations are up to you to implement, but the Oracle JET framework includes features that can reduce the payload size and the number of trips to retrieve the Oracle JET application's CSS.

Adding Performance Optimization to an Oracle JET Application

The table below shows specific steps that you can take to optimize the performance of your Oracle JET application, with links to additional information as needed. The table also identifies steps that it is up to you as the application developer to implement.

Performance Tip

Details

JavaScript Optimization

Send only the JavaScript code that your application needs.

The Oracle JET framework includes modules that you can load with RequireJS. For additional information, see Using RequireJS for Modular Development.

Send minified/obfuscated JavaScript.

Oracle JET provides minified versions of the Oracle JET library as well as third-party libraries when available. By default, these libraries are specified in the Oracle JET RequireJS bootstrap file included with all Oracle JET distributions.

requirejs.config({
// Path mappings for the logical module names
paths: {
'knockout': 'libs/knockout/knockout-3.3.0',
'jquery': 'libs/jquery/jquery-2.1.3.min',
'jqueryui-amd': 'libs/jquery/jqueryui-amd-1.11.4.min',
'ojs': 'libs/oj/v1.1.2/min',
'ojL10n': 'libs/oj/v1.1.2/ojL10n',
'ojtranslations': 'libs/oj/v1.1.2/resources',
'signals': 'libs/js-signals/signals.min',
'crossroads': 'libs/crossroads/crossroads.min',
'history': 'libs/history/history.iegte8.min',
'text': 'libs/require/text'
'promise': 'libs/es6-promise/promise-1.0.0.min',
'hammerjs': 'libs/hammer/promise-2.0.4.min'
},

For additional information about using the RequireJS bootstrap file in your Oracle JET application, see Using RequireJS to Manage Library, Link, and Script References.

If your application isn't using RequireJS, you can specify the links to the minified libraries in your main application file. For additional information, see Specifying Library, Link, and Script References Without RequireJS.

Minimize the number of trips to retrieve the JavaScript.

Oracle JET doesn't provide support for minimizing the number of trips, but RequireJS has an optimization tool that you can use to combine modules. For additional detail, see r.js.

Use lazy loading for JavaScript not needed on first render.

You can use RequireJS to manage lazy loading. For additional information, see Using RequireJS for Lazy Loading Modules in an Oracle JET Application.

You can also lazy load content that is not needed on first render. For example, you can configure the ojTree component to retrieve child node data only when requested. For an example, see the Lazy Loading (ojTree) Oracle JET Cookbook example.

Compress or zip the payload.

Oracle JET has no control over the server, and this recommendation is up to you to implement. For some additional information and tips, see https://developers.google.com/speed/docs/best-practices/payload#GzipCompression.

Set cache headers.

JET has no control over the server, and this recommendation is up to you to implement. For additional information about cache optimization, see https://developers.google.com/speed/docs/best-practices/caching.

CSS Optimization

Send only the CSS that your application needs.

You can control the CSS content that goes into your application. For additional information, see Controlling CSS Content.

If you're using the Oracle JET grid system, you can also control which responsive classes get included in the CSS. For details, see Controlling the Size and Generation of the CSS.

Send minified/obfuscated CSS.

By default, Oracle JET includes minified CSS. However, if you want to modify the CSS to send only what your application needs, you can use Sass to minimize your output. For additional information, see the :compressed option at: http://sass-lang.com/documentation/file.SASS_REFERENCE.html#output_style.

Minimize number of trips to retrieve the CSS.

You can create styles in partial files which you can then aggregate into a single file using the Sass @import directive. For an example, see Using Import Control to Define CSS Content. For additional information about the Sass @import directive, see http://sass-lang.com/documentation/file.SASS_REFERENCE.html#import.

Oracle JET Component Optimization

Use Oracle JET components only when needed.

Build your page in HTML, and add only the Oracle JET components you need. If your application only needs the component briefly, add it and then remove it as soon as your application no longer need it.

Follow Oracle JET component best practices.

Consult the API documentation for the Oracle JET component. The JavaScript API Reference for Oracle�� JavaScript Extension Toolkit (JET) includes a performance section for a component when applicable.

Limit number of Oracle JET components to 50 per page.

For optimal performance, limit the number of Oracle JET components on your page to 50. In addition, some Oracle JET components impose additional limitations:

- 10 components per page: oj*Gauge, ojInputDate, ojButtonset, ojRadioset, ojCheckboxset, ojPagingControl, and ojAccordion

- 5 components per page: ojTab, and ojToolbar

- 2 components per page: oj*Chart with fewer than 100 data points, ojTable, and ojTree

- 1 component per page: oj*Chart with more than 100 data points and fewer than 1000. If your data contains more than 1000 data points, Oracle JET components may suffer a performance or usability hit.

REST Request Optimization

Limit the number of REST requests to 10 on a page and the number of dependent REST calls to at most 2.

For additional performance tips, see the Google Developers documentation at: https://developers.google.com/speed/docs/best-practices/rules_intro.

15 Testing and Debugging

Test and debug Oracle JET applications using your favorite testing and debugging tools for client-side HTML applications written in JavaScript. The framework also includes the getNodeBySubID() and getSubIdByNode() methods that you can use to access Oracle JET component parts for testing.

Topics:

- Typical Workflow for Testing and Debugging an Oracle JET Application

- Testing Oracle JET Applications

- Debugging Oracle JET Applications

Typical Workflow for Testing and Debugging an Oracle JET Application

To test and debug an Oracle JET application, refer to the typical workflow described in the following table:

Task

Description

More Information

Test Oracle JET applications

Identify testing tools and how to use the getNodeBySubId() method to access Oracle JET internal component parts.

Testing Oracle JET Applications

Debug Oracle JET applications

Identify debugging options for Oracle JET applications

Debugging Oracle JET Applications

Testing Oracle JET Applications

You can use virtually any testing tool that tests client-side HTML applications written in JavaScript. For internal development,

Oracle JET uses the following tools for testing Oracle JET components and applications:

- QUnit: JavaScript unit testing framework capable of testing any generic JavaScript project and used by the jQuery, jQuery UI, and jQuery Mobile projects.
QUnit requires configuration on your test page to include library and CSS references. You must also add the HTML div element to your page. In the example below, the highlighted code shows additions required by QUnit. The actual paths will vary, depending upon where you install QUnit.

<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" href="../../../../code/css/libs/oj/v1.1.2/alta/oj-alta-min.css"></link>
<link rel="stylesheet" href="../../../css/qunit.css">
<script type="text/javascript" src="../../../js/qunit.js"></script>
<script>
QUnit.config.autoload = false;
QUnit.config.autostart = false;
</script>
<script data-main="js/main" src="../../../../code/js/libs/require/require.js"></script>
</head>
<body>
<div id="qunit"></div>
<div id="button1">
<h2> Example Knockout Template (displaying demo icons)</h2>
<h3>Single Button Example </h3>
... contents omitted
</div>
</body>
</html>

For additional information about QUnit, see http://qunitjs.com.

- Selenium WebDriver: Alternative method of testing applications that you do not want to modify for QUnit or that contain multiple HTML pages.
For additional information, see http://docs.seleniumhq.org/projects/webdriver.

To assist you with testing Oracle JET components in your own application, Oracle JET provides the following methods:

- getNodeBySubId(locator): Returns the component DOM node indicated by the locator parameter. For additional information, see Using getNodeBySubId() in Testing.

- getSubIdByNode(node): Returns the subId string for the given child DOM node.
Method can be used by test authors to tie into test script generators that must retrieve a recordable ID from a live DOM component while recording a test. This method is currently supported by only a subset of Oracle JET components, and you should check the Oracle JET component's API to verify support.

Using getNodeBySubId() in Testing

The getNodeBySubId() method provides safe access to an Oracle JET component's internal parts to check values and manipulate components. Most Oracle JET components will consist of one or more internal parts. For example, an Oracle JET table component has table cells that you can access with the getNodeBySubId() method.

To use the getNodeBySubId() method in testing:

1. When you create your component, be sure that you assign it an id selector in the HTML markup.

The code below shows example markup for an ojTable component with the id defined as table.

<table id="table1" summary="Department List"
data-bind="ojComponent: {component: 'ojTable', data: datasource, columnsDefault: {sortable: 'none'}, columns:
[{headerText: 'Department Id', field: 'DepartmentId'},
{headerText: 'Department Name', field: 'DepartmentName'},
{headerText: 'Location Id', field: 'LocationId'},
{headerText: 'Manager Id', field: 'ManagerId'}]}">
</table>

2. Check the component's API documentation for the list of nodes that you can access with the getNodeBySubId(locator) method.

For example, if you know you want to access a table cell in an Oracle JET ojTable component, check the ojTable API documentation for getNodeBySubId() . The documentation indicates that to access a table cell, use oj-table-cell rowIndex: number columnIndex: number.

3. Add the code to access the table cell to your markup.

For example, the following code accesses the first table cell (row 0, column 0) in the Oracle JET table defined in Step 1.

node = $("#table1").ojTable('getNodeBySubId', {subId: 'oj-table-cell', rowIndex: 0, columnIndex: 0});

Debugging Oracle JET Applications

Since Oracle JET applications are client-side HTML5 applications written in JavaScript, you can use your favorite browser's debugging facilities.

You can also use debugging tools such as the one provided by the NetBeans IDE, which will allow you to set break points and watches. For details, see Debugging and Testing JavaScript in an HTML5 Application.

A Troubleshooting

Since Oracle JET applications are client-side JavaScript applications, you can follow the same procedure for troubleshooting your Oracle JET procedure that you would follow for any JavaScript application.

If you're having issues troubleshooting a specific Oracle JET component or framework feature, see Oracle JET Support. Before requesting support, be sure to check the Oracle JET Release Notes.

B Packaging and Deploying

Oracle JET is a collection of HTML, JavaScript, and CSS files that you can deploy to any type of web or application server. There are no unique requirements for packaging and deploying Oracle JET applications.

Deployment methods are quite varied and depend upon the type of server environment your application is designed to run in. However, you should be able to use the same method for deploying Oracle JET applications that you would for any other client interface in your specific environment.

C Oracle JET References

The Oracle and third-party libraries and tools referenced throughout the book are provided in these topics with links to additional information.

Topics:

- Oracle Libraries and Tools

- Third-Party Libraries and Tools

Oracle Libraries and Tools

Use this reference to locate additional information about the Oracle libraries and tools referenced throughout the guide.

Name

Description

Additional Information

NetBeans

Integrated Development Environment (IDE) with support for HTML5 application development

https://netbeans.org

Oracle JDeveloper

IDE with support for Oracle Application Development Framework (ADF) and HTML5 application development

http://www.oracle.com/technetwork/developer-tools/jdev/overview/index.html

Third-Party Libraries and Tools

Use this reference to locate additional information about the third-party libraries and tools referenced throughout the guide.

Name

Description

Additional Information

Crossroads.js

JS library used for routing

http://millermedeiros.github.io/crossroads.js

CSS3 (Cascading Style Sheets)

Used for adding style to Web applications

http://www.w3.org/Style/CSS

es6-promise

Polyfill for ES6-style Promises

https://github.com/jakearchibald/es6-promise

Hammer.js

JS library used for multi-touch gestures

http://hammerjs.github.io/getting-started

HTML5 (Hypertext Markup Language 5)

Core language of the World Wide Web

http://www.w3.org/TR/html5

JavaScript

Scripting language used in client-side applications

https://developer.mozilla.org/en/About_JavaScript

js-signals

JS library used for custom event/messaging system

http://millermedeiros.github.io/js-signals

jQuery

JS library designed for HTML document traversal and manipulation, event handling, animation, and Ajax

http://jquery.com

jQuery UI

JS library built on top of jQuery for UI development. Oracle JET includes the UI Core download only.

http://www.jqueryui.com

Knockout

JS library used for two-way data binding

http://www.knockoutjs.com

QUnit

JavaScript unit testing framework

http://qunitjs.com

RequireJS

JS file and module loader used for managing library references and lazy loading of resources

http://www.requirejs.org

SASS (Syntactically Awesome Style Sheets)

Extends CSS3 and enables you to use variables, nested rules, mixins, and inline imports

http://www.sass-lang.com

Selenium WebDriver

Alternative method of testing applications

http://docs.seleniumhq.org/projects/webdriver

Oracle Legal Notices

Copyright Notice

Copyright © 1994-2015, Oracle and/or its affiliates. All rights reserved.

Trademark Notice

Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.

Intel and Intel Xeon are trademarks or registered trademarks of Intel Corporation. All SPARC trademarks are used under license and are trademarks or registered trademarks of SPARC International, Inc. AMD, Opteron, the AMD logo, and the AMD Opteron logo are trademarks or registered trademarks of Advanced Micro Devices. UNIX is a registered trademark of The Open Group.

License Restrictions Warranty/Consequential Damages Disclaimer

This software and related documentation are provided under a license agreement containing restrictions on use and disclosure and are protected by intellectual property laws. Except as expressly permitted in your license agreement or allowed by law, you may not use, copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform, publish, or display any part, in any form, or by any means. Reverse engineering, disassembly, or decompilation of this software, unless required by law for interoperability, is prohibited.

Warranty Disclaimer

The information contained herein is subject to change without notice and is not warranted to be error-free. If you find any errors, please report them to us in writing.

Restricted Rights Notice

If this is software or related documentation that is delivered to the U.S. Government or anyone licensing it on behalf of the U.S. Government, the following notice is applicable:

U.S. GOVERNMENT END USERS: Oracle programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, delivered to U.S. Government end users are "commercial computer software" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations. As such, use, duplication, disclosure, modification, and adaptation of the programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, shall be subject to license terms and license restrictions applicable to the programs. No other rights are granted to the U.S. Government.

Hazardous Applications Notice

This software or hardware is developed for general use in a variety of information management applications. It is not developed or intended for use in any inherently dangerous applications, including applications that may create a risk of personal injury. If you use this software or hardware in dangerous applications, then you shall be responsible to take all appropriate fail-safe, backup, redundancy, and other measures to ensure its safe use. Oracle Corporation and its affiliates disclaim any liability for any damages caused by use of this software or hardware in dangerous applications.

Third-Party Content, Products, and Services Disclaimer

This software or hardware and documentation may provide access to or information on content, products, and services from third parties. Oracle Corporation and its affiliates are not responsible for and expressly disclaim all warranties of any kind with respect to third-party content, products, and services. Oracle Corporation and its affiliates will not be responsible for any loss, costs, or damages incurred due to your access to or use of third-party content, products, or services.

Alpha and Beta Draft Documentation Notice

If this document is in preproduction status:

This documentation is in preproduction status and is intended for demonstration and preliminary use only. It may not be specific to the hardware on which you are using the software. Oracle Corporation and its affiliates are not responsible for and expressly disclaim all warranties of any kind with respect to this documentation and will not be responsible for any loss, costs, or damages incurred due to the use of this documentation.