Skip navigation
1 2 3 Previous Next

Oracle JET

41 posts

If you’ve ever struggled to remember the syntax of the Oracle JET tooling commands, help is at hand!

 

The Oracle JET command line tooling has been significantly enhanced with the release of the ojet-cli module that provides a consistent, easy-to-use command line interface (CLI) for scaffolding, building, serving and managing JET apps.

 

This CLI has been released together with JET 3.1.0, but is not yet documented in the JET documentation while we ask you to install it, use it and provide feedback on it.

 

Installation

 

The ojet-cli open source module is fully supported by the Oracle JET team and can be installed as follows:

 

[sudo] npm –g install ojet-cli

 

Usage

 

Once installed, the ojet CLI makes use of the installed Oracle JET Yeoman generators and Grunt tasks, as well as the Cordova CLI.

 

The syntax is:

 

ojet <task> [scope] [parameters] [options]

 

The available tasks are:

 

add ........................... Adds platforms, plugins, themes and more to a JET app
build ......................... Builds a JET app
create ........................ Creates a new JET app
help .......................... Displays command line help
list .......................... Lists platforms and plugins within a JET app
remove ........................ Removes platforms and plugins from a JET app
restore ....................... Restores a JET app
serve ......................... Serves a JET app to an emulator, device or the browser

Examples

 

Scaffold a new web app with:

 

ojet create MyApp --template=navdrawer

 

Scaffold a new hybrid mobile app with:

 

ojet create MyApp --hybrid --platform ios --template navbar --appid com.mycompany.MyApp

 

Build and serve the app with:

 

ojet serve ios --device

 

Add platforms and Cordova plugins with:

 

ojet add platform android 
ojet add plugin cordova-plugin-camera

 

Help

 

You can get help at a high level, or for specific commands, by invoking commands such as the following:

 

ojet help
ojet help remove
ojet help remove plugin

 

Give it a go!

 

We encourage you to install and play with the new ojet-cli module and provide your feedback via the Oracle JET Community.  And we hope it makes your life easier when creating Oracle JET web and hybrid mobile apps.

We are proud to announce the 15th on-schedule release of Oracle JavaScript Extension Toolkit (JET).

 

JET v3.1.0 is a minor release and is primarily a bug fix release, however there are new features related to ojDiagram, ojDialog, ojCheckboxset, ojRadioset and BusyContext.

 

Please read the Release Notes for this release to see all aspects about the release that may be relevant for updates and new development.

 

This release does not contain any library version or API changes per our support policy for minor releases, and should be drop-in compatible when updating from 3.0.0 and 3.1.0.

 

Happy coding!

While SVG is supported in all modern browsers, I'm often asked for help in converting JET's SVG visualizations to other image formats to support use cases like emailable dashboards. We can do this easily in JavaScript with just a few steps:

  1. Convert the SVG element to an SVG data uri
  2. Set the SVG data uri on an HTML img element
  3. Draw the HTML img element to canvas, which supports an API to return a PNG data uri

 

We do this in the sample below, which starts with an SVG element containing a single blue rectangle (1st from the left). We convert this SVG to a data uri and display it in an HTML img (2nd rectangle), draw this HTML img to canvas (3rd rectangle), and finally retrieve the PNG data uri and set it on another image tag (4th rectangle) to verify that it worked correctly.

svgToPng.png

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8"/>
  </head>
  <body>
    <!-- The SVG image that will be converted -->
    <svg id='sample' xmlns='http://www.w3.org/2000/svg' width='100' height='100'>
      <rect width='100' height='100' fill='#267db3'/>
        <rect width='1' height='1' fill='#ff0000'/>
    </svg>
    
    <!-- An img element for testing the SVG data uri -->
    <img id="imageWithSvgDataUri" width="100" height="100"></img>
    
    <!-- A canvas element for converting SVG to PNG data URI -->
    <canvas id="canvas" width="100" height="100"></canvas>
    
    <!-- An img element for testing the PNG data uri -->
    <img id="result" width="100" height="100"></img>
    
    <script type="text/javascript">
      // Get the SVG string and create the svg data uri
      var svg = document.getElementById('sample');
      var svgString = (new XMLSerializer()).serializeToString(svg);
      var svgDataUri = 'data:image/svg+xml;utf8,' + svgString;
      
      // For firefox, escape # characters to create valid data uri.
      svgDataUri = svgDataUri.replace(/#/g, '%23');
    
      // Set the SVG data uri on an img tag to make sure it's correct
      var image = document.getElementById('imageWithSvgDataUri');
      image.setAttribute('src', svgDataUri);
      
      // Draw the SVG to canvas and call toDataURL to convert to PNG data uri. The
      // image must be loaded prior to being drawn to canvas, which may be done
      // asynchronously by the browser.
      image.onload = function () {
        var canvas = document.getElementById('canvas');
        var ctx = canvas.getContext('2d');
        ctx.drawImage(image, 0, 0);
        var pngDataUri = canvas.toDataURL();
        
        var resultImage = document.getElementById('result');
        resultImage.setAttribute('src', pngDataUri);
      };
    </script>
  </body>
</html>

 

Some caveats of this approach:

  • As with any PNG image, it's important to know that the resulting visualization will no longer look good when scaled.
  • External references in the SVG, such as to style classes, remote downloaded fonts, or images may not be display in the resulting PNG. This is due to browser security limitations that require the image to be self contained.

By default, the series in a stacked chart will be stacked together if they have the same type (bar, line, or area) and belong to the same y-axis (y1 or y2). This makes sense for most data sets, but there are cases where more precise control is needed. To support this, the JET charts support the series[].stackCategory attribute, which will create new stacks for series with different stackCategory values.

 

This is useful in combination charts, where one might want to stack the bar series, but not the lines:

chartCombinationStacking.png

Here's the series array for this chart:

var series = [
  {name : "Cloud Sales", type: 'bar', items : [110, 210, 250, 355]},
  {name : "On Premise Sales", type: 'bar', items : [40, 35, 40, 25]},
  {name : "Cloud Win Rate", assignedToY2: 'on', type: 'line', stackCategory: "Cloud Win Rate", items : [78, 80, 85, 90]},
  {name : "On Premise Win Rate", assignedToY2: 'on', type: 'line', stackCategory: "On Premise Win Rate", items : [90,  76, 60, 65]}
];

 

This feature can also be used to provide different perspectives on the data. In our stack categories demo, we show a chart with sales across products in different regions. By using stacking and stack categories, a chart showing the sales of products in individual regions can be updated to show total sales or total sales by region:

 

chartStackCategory.gif

 

The stack categories demo also leverages associated views highlighting and custom legend sections. To learn more about these features, see:

Associated Views: Cross Component Interactivity for Data Visualizations

How to Create Colorful Bar Charts

Performance is a critical aspect of mobile app development and the embedded platform web view is a significant contributing factor to the performance of any hybrid mobile app.

 

Since late 2015, hybrid app developers targeting iOS have been able to include the Apache Cordova team’s cordova-plugin-wkwebview-engine plugin in order to benefit from the much-improved performance of WKWebView over the default UIWebView.

 

A tradeoff using WKWebView is that it blocks XHR requests that attempt to load resources from the application bundle using the file:// protocol. Notably, this constraint breaks use of the RequireJS text plugin for loading application resources such as templates.

 

The reason for this is that even though the Cordova application's starting page is loaded from the device file system, WKWebView treats XHR requests to file:// URLs as cross origin requests.  Since there is no way to specify the Access-Control-Allow-Origin response header for these requests, these cross origin requests fail.

 

To resolve this issue, the Oracle JavaScript Extension Toolkit (JET) team has developed the cordova-plugin-wkwebview-file-xhr plugin. This plugin intercepts XHR GET requests to the local application bundle, routing them through the native layer. As a security measure, the plugin verifies that the standardized path of the target URL is within the "www" folder of the application’s main bundle.

 

While the cordova-plugin-wkwebview-file-xhr plugin allows the application's local resources to be loaded via file:// XHR requests, there is another XHR-related CORS issue that application developers might face when using WKWebView, which is not addressed by this plugin.  Since the application's starting page is loaded from the device's file system, all XHR requests to remote endpoints are considered cross origin.  For such requests, WKWebView specifies "null" as the value of the Origin header, however many endpoints are configured to disallow requests from the null origin.

 

If your REST endpoints are open or accepting of null origins, the cordova-plugin-wkwebview-file-xhr Cordova plugin makes it possible for you to benefit from the higher performance of the WKWebView in your Cordova-based hybrid mobile applications on iOS.

EMM (Enterprise Mobility Management) is the technology of managing mobile devices, wireless networks, and other mobile computing services in a business context.

 

EMM servers allow administrators to configure mobile apps via a web console and apply the configuration to the app on every managed device as part of the app installation process.  This configuration typically consists of generic name-value pairs defined by the app developer, such as URI, port numbers, tenant ids or skin configurations.

 

Android & iOS support this functionality natively, but retrieving app configuration data and being alerted when it has changed is just as important for Cordova-based hybrid mobile apps.

 

To make this possible, the Oracle JavaScript Extension Toolkit (JET) team has developed the cordova-plugin-emm-app-config plugin.  This plugin allows the app developer to retrieve the app configuration data at any point in the app lifecycle, including when the app configuration has been changed on the EMM server.

 

This plugin is not limited to Oracle JET apps.  Make use of this plugin to enable your Cordova-based hybrid mobile app to retrieve app configuration data and to be alerted when this data has changed.

 

For more information on implementing various EMM features, including managed app configuration, refer to the AppConfig Community.

Sunburst and Treemap Drilling

sunburstDrill3loop.gifTreemapDrill3Loop.gif

The sunburst and treemap components often display deep hierarchies of data, so we've introduced built in drilling. To better understand how drilling works, let's analyze how we could use drilling to visualize United States election data.

Suppose that the application is trying to provide detailed information about voter demographics in each congressional district. If the visualization were to display all the data upfront it would be almost impossible to know how middle income voters in Massachusetts's 7th congressional district voted as that information could be 7 levels down the hierarchy. Instead, with the new attributes we've introduced, the treemap or sunburst can be configured such that the user can easily access this information with just a few drill down actions. On initial render the visualization could be configured to only display Regions and States. The user would then click on Massachusetts to drill in for more information about the state and the application would listen for the beforeDrill event and fetch data for Massachusetts. Once the visualization renders with Massachusetts specific information the user can continue to drill down to the district level and income level voter data. When the user has analyzed the data point they can easily navigate back up the hierarchy using the breadcrumbs displayed at the top of the visualization.

 

To learn more about the specific attributes and to see a working demo please follow the links provided below. The sunburst demo uses a data model which is loaded upfront, while the treemap demo shows how to dynamically append data as the user drills down.

 

Sunburst Demo: http://www.oracle.com/webfolder/technetwork/jet/jetCookbook.html?component=sunburst&demo=drill

Treemap Demo: http://www.oracle.com/webfolder/technetwork/jet/jetCookbook.html?component=treemap&demo=drill

 

 

Sunburst Expand/Collapse

SunburstExpand3Loop.gif

Sunburst Expand/Collapse is a useful feature we've added that allows users to explore individual data nodes a few layers down the hierarchy without overcrowding the sunburst with the entire data set. This is very useful for highlighting particular branches of interest when initially rendering data as well as exploring data lower down the hierarchy while still displaying the full ancestry. Useful features include the ability to display buttons on all nodes or a subset of nodes when hovering, fired events associated with expanding or collapsing nodes, and an array of node ids that represent the currently expanded nodes. Similarly to drilling, we recommend that for large data sets the developer load the data dynamically as nodes are expanded by the user. Below is a code sample which shows how to to enable expand/collapse.

 

<div id='sunburst-container'>
    <div id="sunburst" data-bind="ojComponent: {
            component: 'ojSunburst',  
            animationOnDisplay: 'auto',
            animationOnDataChange:'auto',
            beforeExpand: loadAdditionalData,
            expanded: expandedNodes,
            nodeDefaults: {showDisclosure: 'on'},
            nodes: nodeValues
        }" 
        style="max-width:650px;width:100%; height:650px;">
    </div>
</div>

 

Full Demo: http://www.oracle.com/webfolder/technetwork/jet/jetCookbook.html?component=sunburst&demo=expand

Treemap Node Conent

treemapNodeContent.png

Starting in JET 3.0.0, leaf nodes are customizable using a JavaScript callback function or a Knockout template that specifies HTML DOM elements for each node. This allows a developer to place any desired content within the nodes. If using a Knockout template, specify the template name using the nodeContent.template attribute. Otherwise, pass a function to the nodeContent.renderer. By default, the custom div will intercept any mouse or touch events allowing for interactive content in each node. In order to disable this behavior and retain the treemap default interactivity set the CSS pointer-events property to 'none'.

 

Here's an example of a template used for rendering custom content:

    <div id="treemap" data-bind="ojComponent: {
            component: 'ojTreemap',
            animationOnDisplay: 'auto',
            animationOnDataChange: 'auto',
            nodes: nodeValues,
            nodeContent: {template: 'nodeTemplate'}                     
        }" 
        style="min-width:300px;height:450px;">
    </div>
    <script type="text/html" id="nodeTemplate">
      <div data-bind="style: {
            position: 'absolute',
            display:'flex',
            justifyContent:'center',
            width: bounds.width + 'px',
            height: bounds.height+ 'px',
            top: bounds.y + 'px',
            left: bounds.x + 'px',
            pointerEvents: 'none'}">
        <div style="align-self:center;height:88px;text-align:center">      
          <div data-bind="style: {
              backgroundImage: 'url(\'images/' + id + '.png\')',
              marginLeft:'auto',
              marginRight:'auto',
              backgroundSize: 'cover',
              borderRadius: '20%',
              width: '50px',
              height: '50px'}"/>
          <div data-bind="text: data.title, style:{fontSize:'12px',fontStyle:'italic;fontWeight:bold'}"/>
       </div>
      </div>
  </script>

 

Demo: http://www.oracle.com/webfolder/technetwork/jet/jetCookbook.html?component=treemap&demo=nodeContent

 

Sunburst Root Node Content

 

sunburstRootContent.png

The root node area is now customizable similarly to the center of donut charts and circular status meter gauges. Use the rootNodeContent.renderer or rootNodeContent.template attribute to specify a callback function or KO template for the root node.

 

Demo: http://www.oracle.com/webfolder/technetwork/jet/jetCookbook.html?component=sunburst&demo=rootNodeContent

 

Labeling changes

Treemap node labels will now wrap by default instead of being displayed in a single line. In order to disable label wrapping, the white-space property on nodeDefaults.labelStyle or nodes[].labelStyle can be set to "nowrap" instead of the default "normal" value.

 

In addition, we've added the nodeDefaults.labelMinLength attribute to both sunburst and treemap which defines the minimum number of visible characters needed in order to render a truncated label. If this minimum is not met when calculating the truncated label then the label is not displayed. The default value of this variable is 1 character.

I'm often asked about why a chart or visualization hasn't rendered and setting aside obvious issues like a bug or javascript error, the most common cause is that the chart was rendered when it doesn't have access to browser measurements via APIs like SVG's getBBox. These measurements are primarily needed on text to determine how much space to leave for a legend or axis (shown below in red):

 

chartMeasurement.png

The problem arises because these measurements are not available when:

  • The element or one of its ancestors is set to display:none
  • The element is part of a detached DOM tree

 

This can occur if a section of the page is initially hidden, or if the DOM is being created programmatically and happens to be attached after creation. In both cases, the chart will detect that it doesn't have access to measurement, and skip the render until it does. To resolve this, JET exposes APIs on the oj.Components class that the application must call to notify about subtree changes:

 

The application should call the applicable API with the DOM node for the modified subtree, and JET will notify any affected components in response. Once notified, the chart will confirm it has access to measurement and finally render the expected result.

Last week saw the release of version 3.0.0 of the Oracle Java Extension Toolkit (JET).  This is a major release of the toolkit, containing significant updates to JET components, cookbook, tooling and themes, along with updates to 3rd party libraries.

 

Please refer to the Release Notes for detailed information about the changes and how they may affect you.

 

Please refer to the Migration Guide and note the reference to the Developer Guide for steps required when migrating your Oracle JET application to v3.0.0 if you are using Oracle JET tooling.

 

And for a bit of inspiration, take a look at the new Success Stories section of the oraclejet.org website.

In a previous post, we described how to create a layout for the Diagram component.  In this post, we'll focus specifically on how to control the initial position and zoom level of the Diagram.

 

By default, the Diagram content will be zoomed to fit and placed at the component center. This is done to allow users to see the Diagram as a whole. However, in some cases you might want to display the Diagram using a specific zoom level or pan the Diagram to a position to emphasize one of the nodes. You should be able to achieve this by calling setViewport() method in your layout. The setViewport() method is available on DvtDiagramLayoutContext object that is passed to the layout. The method expects an object with x, y, w, h properties that describes the visible viewport in layout coordinates.

 

Here is how it works. Let's assume that you have only one 50x50 px node that is positioned by the layout at (0,0) and the following component binding:

 

<div data-bind="ojComponent: {
     component: 'ojDiagram',
     minZoom:.5,
     maxZoom:2,
     panning:'auto',
     zooming:'auto',
     data: data}">
</div>

 

In this case the component can be zoomed out to 50% and zoomed in up to 200%. If you don't set a viewport in the layout, by default the Diagram content will be positioned at the center and zoomed to fit (zoomed at max in this case).

3_ViewportNull.PNG

 

If you want to set the initial display to 100% at (0,0), set viewport to the component size using the code below.

In this case, you can also use the getComponentSize() method. The method returns an object with x, y, w, h properties where x, y are always 0 and w, h represent the component's rendered width and height.

var compSize = layoutContext.getComponentSize();
layoutContext.setViewport(compSize);

3_Viewport100per.PNG

If you want to set the initial display to 200% at (0,0), set the viewport to half of the component size (this smaller viewport will then be zoomed in to fill the Diagram canvas):

layoutContext.setViewport({x:0, y:0, w:.5*compSize.w, h:.5*compSize.h});

3_Viewport200per.PNG

If you want to set the initial display to 50% at (0,0), set the viewport to twice the size of the component size (this larger viewport will then be zoomed out to fill the Diagram canvas):

layoutContext.setViewport({x:0, y:0, w:2*compSize.w, h:2*compSize.h});

3_Viewport50per.PNG

If you want to set the initial display to 50% and center it, set the viewport to twice the size of the component size and adjust x, y for the viewport.

// the diagram has a single node at (0,0) with the size 50x50
// the center of diagram content is 25, 25
var centerX = 25, centerY = 25;
var viewportWidth = 2*compSize.w, viewportHeight = 2*compSize.h;
layoutContext.setViewport({x: centerX - .5 * viewportWidth, y: centerY - .5 * viewportHeight, w: viewportWidth, h:viewportHeight});

3_Viewport50perCenter.PNG

 

As you see, you can calculate the viewport size, using this formula:

// Z is the zoom factor that you want to get on the initial display
viewportWidth = compSize.w / Z;
viewportHeight = compSize.h / Z;
// then adjust x, y to the desired position

And finally, if a user interaction changed the component viewport and you wish to preserve the viewport on Diagram refresh, take a look at the getCurrentViewport() method. The method will return the current, most recent viewport to the caller. You might use it in the following way:

 

if (layoutContext.getCurrentViewport() ) {
  layoutContext.setViewport( layoutContext.getCurrentViewport());
}

 

Once you are familiar with the above methods, you should be able to control the Diagram viewport the way you need. See additional information for the methods in JET JSDoc.

If you are using Oracle JET to develop hybrid mobile apps and recently updated to Cordova CLI v6.4.0, you may have noticed that your custom app icons and splash screens are not being included in your app when deployed to Android devices.

 

This is a known issue with Cordova Android v6.0.0 that has been addressed in the recent v6.1.0 release.  To upgrade to this version, follow these steps:

 

  1. Change directory to the 'hybrid' folder within your app source code:
    cd hybrid
  2. Save your plugins:
    cordova plugin save
  3. Upgrade Cordova Android:
    cordova platform update android@latest

 

Rebuild and redeploy your app to an Android device using the JET grunt tasks or your own build scripts and you should see your custom app icon and splash screen as expected.

 

Did you realize that you could use JET to develop enterprise mobile apps?

 

Oracle JET is a toolkit for developing client-side applications using web technologies, so how is it possible to use JET to develop a mobile app?

 

This is made possible through JET's integration with Apache Cordova.

 

In this post, I’ll describe some of what we’ve added to JET to enable you to use Oracle JET for mobile app development.

 

But first, I’ll start with an introduction to Apache Cordova.

 

What is Apache Cordova?

 

Apache Cordova is an open-source platform that allows you to use standard web technologies (HTML5, JavaScript and CSS) for cross-platform mobile app development.

 

That means you can develop one app, using one technology stack and a single code base, for deployment to Android, iOS and Windows mobile devices.

 

A mobile app built using Cordova is a native mobile app that can be published to app stores and installed onto mobile devices. The application contains an embedded Cordova-enabled WebView, which is essentially a headless browser, and your code runs in the WebView.  Cordova also provides a JavaScript interface to native device APIs, via plugins.  There are 1000s of plugins to choose from and a plugin registry that you can search.

 

This type of app is called a hybrid mobile app, because it is a hybrid between a native mobile app and web technology.

 

 

How does JET support hybrid mobile app development?

 

Utilizing the Apache Cordova command-line interface, Oracle JET tooling enables you to scaffold, build and serve JET hybrid mobile apps in exactly the same way as you would a JET web app.

 

The Oracle JET Yeoman generator has a hybrid sub-generator for scaffolding a hybrid app and supports Android, iOS and Windows platform options, along with the web platform.

 

The four JET starter templates are provided in both web and hybrid versions, which are optimized for web apps and hybrid mobile apps, respectively.

Together, this allows you to scaffold a hybrid mobile as follows:

 

yo oraclejet:hybrid MyMobileApp --platforms=ios,android --template=navdrawer:hybrid

 

The Oracle JET Grunt tasks also support Android, iOS, Windows and web platform options so you can build and serve hybrid mobile apps to your desired platform. The 'grunt serve' task also supports deployment to different destinations, such as emulator, browser or device.  The following command line gives an example:

 

grunt serve --platform=ios --destination=emulator 

 

Live reload is supported when your hybrid mobile app is deployed to a browser or emulator. This means you can modify your app’s source code and see the changes update in the deployed app instantaneously, saving you a long redeployment cycle.

 

Can I develop a web app and hybrid mobile app with the same code base?

 

Yes!

 

Oracle JET tooling enables you to take a “mobile first” approach to your web app design, based on a mobile-optimized template, then use the same source code to create your installable mobile app.  This is achieved by first scaffolding and developing a mobile web app with a hybrid starter template, then adding a hybrid target:

 

yo oraclejet MyApp --template=navdrawer:hybrid yo oraclejet:add-hybrid --platforms=ios,android

 

The scaffolded project contains separate src, src-web and src-hybrid folders, so that you can override any file within your source code to provide different web or hybrid functionality, as desired.

 

What does a JET hybrid mobile app look like?

 

Along with Oracle’s Alta theme for web apps, JET also supports Oracle’s Alta mobile themes for Android, iOS and Windows, which closely match the native look & feel on each supported mobile platform.

 

 

The Oracle JET Cookbook enables you to view JET components and patterns in each of the available themes and sized for different form factors, such as phone, tablet or desktop.

 

Should you wish to develop your own custom theme and use this instead, the JET tooling facilitates this via SASS:

 

yo oraclejet:add-sass yo oraceljet:add-theme --theme=MyTheme grunt serve --platform=ios --theme=MyTheme

Is there a sample app that shows me how to do all this?

 

Yes!

 

The Oracle JET development team has provided a sample app called FixItFast that was developed specifically to demonstrate how to develop a JET hybrid mobile app.  It also demonstrates a number of mobile UX patterns and shows how to communicate with an Oracle Mobile Cloud Service (MCS) mobile backend.

 

jetmobile_fixitfast.png

 

You can find a live demo of the FixItFast web app here and instructions for how to scaffold, configure, build and serve it as a web or hybrid mobile app here.

 

Where can I learn more about mobile app development with JET?

 

You can find videos about Oracle JET, including mobile app development, on the Oracle JET YouTube channel.

 

In addition, the Oracle Mobile Product Management team have published a number of articles in Dzone, describing how to start out with the Oracle JET tooling for web and hybrid mobile development:

 

 

Following soon will be videos on how to integrate the Oracle Mobile Cloud Service JavaScript and Cordova SDKs into Oracle JET, watch this blog for an update!

 

In conclusion

 

Oracle JET supports hybrid mobile app development via enhanced tooling that supports the Android, iOS and Windows 10 mobile platforms, mobile-optimized starter templates, mobile-specific UI themes and mobile-specific patterns presented in the JET cookbook.

 

For more information about hybrid mobile app development with Oracle JET, refer to the Oracle JET Developers Guide.

Pangus Ho-Oracle

Chart Drag & Drop

Posted by Pangus Ho-Oracle Aug 30, 2016

Drag and drop is a new ojChart feature that was introduced in JET 2.0.2. In addition to dragging between charts, this feature also supports dragging to and from other components. Similar to the other JET components, it is built using the HTML5 drag and drop.

chartDnD.gif

ojChart supports dragging of data items (i.e. bars, bubbles, etc.), series objects (i.e. legend items), and group objects (i.e. categorical axis labels). To set up a chart as a drag source, you only need to set the dataTypes attribute of either items, series, or groups option inside dnd.drag. The dataTypes are the MIME types to use for the data context JSON in the dataTransfer object. The chart objects (items, series, or groups) with the dataTypes specified will automatically become draggable.

 

HTML:

<div id="bubbleChart1" data-bind="ojComponent: {
    component: 'ojChart',
    type: 'bubble',
    series: bubbleSeries,
    groups: bubbleGroups,
    dnd: {
      drag: {
        items: {
          dataTypes: ['text/bubblechart']
        }
      }
    }
}">
</div>

 

The chart will automatically populate the dataTransfer object with the data context JSON of the dragged items using dataTransfer.setData() method. You can retrieve the JSON using dataTransfer.getData() method. Here's an example of how the data context JSON may look like for a bubble chart item:

[
  {
    id: 'Series 1; Group B'    
    series: 'Series 1',
    group: 'Group B',
    x: 40,
    y: 24,
    z: 12,
    seriesData: {...},
    groupData: [...],
    data: {...}
  } 
]

 

ojChart also supports dropping onto its plot area, legend, and axes. To set up a chart as a drop target, you only need to specify the drop callback and the dataTypes for either plotArea, legend, xAxis, or yAxis option inside dnd.drop. If the dataTypes in the dataTransfer matches the specified dataTypes in chart option, then the chart will accept the drop.

 

HTML:

<div id="bubbleChart2" data-bind="ojComponent: {
    component: 'ojChart',
    type: 'bubble',
    series: bubbleSeries,
    groups: bubbleGroups,
    dnd: {
      drop: {
        plotArea: {
          dataTypes: ['text/bubblechart'],
          drop: dropCallback
        }
      }
    }
}">
</div>

 

JS:

this.dropCallback = function (event, ui) {
  var data = event.dataTransfer.getData("text/bubblechart");
  if (data) {
    var dataContext = JSON.parse(data)[0];

    // Update the chart to react to the drop
    ...
  }
};

 

In the future releases of JET, we will also expose the drag and drop features for other data visualization components.

 

For more information and demos, please visit the following JET Cookbook pages:

 

For complete API documentation, please visit the JET JSDoc.

JET 2.1.0 is a major release of JET framework that contains over 140 new features and over 900 bug fixes.

 

Some of the largest new features are:

  • The first public release of the new Composite Component Architecture
  • Timezone support has now been added to converters and all JET UI Components that work with date/time
  • In-line editing is available in both ojTable and ojDataGrid
  • ListView now supports drag and drop as well as card layout in addition to the existing list layout

 

On the Mobile feature side there have been significant enhancements to the command line tooling:

  • Addition of SASS support
  • New starter templates for mobile and web
  • Refactoring of the command line tooling for easier maintence and expansion

 

More details on the new features are provided below, as well as in the release notes.

 

Composite Components

JET now exposes composite components which are reusable pieces of UI that can be embedded as a custom HTML element and can be composed of other composites, JET components, HTML, JavaScript, or CSS. See the composite documentation and demos for more information.

ccaDemo.gif

List View

JET ListView now supports reordering items within ListView as well as drag and drop with other JET components.

 

Menu

JET Menu now supports Sheet Menus. In all built-in themes, Menu launches as a sheet menu for small screen sizes, and as the existing "dropDown" style of menu for larger screen sizes. This behavior can vary by theme and by instance. See the new openOptions.display option and $menuDropDownThresholdWidth SASS variable for details.

 

Data Grid

JET Data Grid now supports in cell editing for data body cells. New options for editMode have been added to enable this feature.

Data Grid now also supports row and column "end headers" or "footers". This functionality can now be used to create visualizations such as a Trellis example below.

trellis1.png

 

New Data Visualization Features in JET 2.1.0

 

New Component: Gantt

The gantt component displays the start and finish dates of a set of tasks.

gantt.png

 

New Component: Time Axis

The timeline and gantt time axis has been introduced as a standalone component for use in tables and grids.

 

New Chart Type: Box Plot

The box plot displays distributions of data values through their quartiles, extents, and outliers.

boxPlot.png

 

New Chart Type: Pyramid Chart

Similar to an inverted funnel chart, the pyramid chart is used for visualizing parts of a whole. It is especially useful when the triangular shape helps to reinforce the relationship of the underlying data.

pyramid.png

 

Custom Fills and Strokes

Custom fills and strokes are now supported on diagram, gauge, nBox, picto chart, spark chart, sunburst, tag cloud, thematic map, and treemap. First introduced on chart in the 2.0.2 release, these components now support style and className options corresponding to thestyle and styleClass DOM attributes. These attributes override any other styling set through the component options, enabling the use of custom gradients, patterns, filters, and other SVG style properties.

 

Diagram Containers

Diagram now supports containers, allowing nodes (including other containers) to be contained within other nodes. Containers can be expanded and collapsed at runtime.

diagramContainers.png

 

Thematic Map Links

Thematic map now supports the display of links between locations. Often used to show airline routes or other data with origin and destination locations, the links can be styled and customized with start and end markers.

thematicMapLinks.png

Treemap Visual Design Updates

The treemap visual design has been updated to match the modern look of the other visualizations by replacing the node bevels with single pixel white gaps. This update also improves rendering performance of the treemap, since the gaps can be rendered without the additional shapes needed by the bevels.

treemapModern1.png

Other Enhancements

  • Chart axis titles will be automatically wrapped if they exceed the available space.
  • The oj.DiagramUtils.getLayout function can be used in many cases to simplify Diagram layout. Applications can now pass layout information through a javaScript object which will be used by this function to create the layout function that is required by the diagram.
  • Timeline events can now be rendered from top to bottom in addition to the existing behavior of bottom to top.
  • Performance has been improved for bubble charts, categorical axis charts, scatter charts, stacked charts, and treemap.

 

More information and best practices for using data visualization components can be found in JET Data Visualizations FAQ.