Intro

Until recently, web applications were restricted to browsers. Now, they can run on mobile devices (in a webview) and on the desktop (in an HTML5 container). The proliferation of mobile devices, the release of the Chromium Embedded Framework, and the emergence of Electron have all contributed to the widespread use of web technologies outside of a typical web browser.

The ChartIQ library can operate in any of these environments. All of the guidance and tutorials provided by our documentation applies, regardless of whether you're developing your application for browsers, mobile devices or desktop containers. This tutorial will:

  • Introduce you to webviews and containers
  • Discuss issues related to working with webviews/containers.
  • Recommend resources for further reading.

First, let's clear up some terminology.

Webview vs Container

Webview: At the most basic level, a webview is simply a UI-less browser window configured to run in full screen. It's just a frame that delivers web content.

Container: A container is a platform that embeds Chromium into a native shell. The container allows a developer to build native apps without C++ or Java.

Communicating with WebViews and Containers

You will probably need to communicate between your webview and the native code that it's running within. Consider the case where you'd like to put charts into your existing native mobile application. If all that's required is a chart that displays up to date data, the task is simple. But as soon as you introduce UI that alters the chart state, you will need to pass instructions from the native app to the embedded webview; the webview may also need to communicate back to the native application when its state changes. The example below shows how to use a native iOS button to trigger a chart type change inside of a webview:

    -(IBAction)toggleHollowCandle:(id)sender {
    //javascript function in the webview called setChartType
    NSString *func =@"setChartType('hollow_candle');";
    //code below calls the function inside of our webview
    [_webView evaluateJavaScript:func completionHandler:^(id Result, NSError * error) {
            NSLog(@"Error -> %@", error);
        }];
    }

Sidebar: Advantages of Remote Deployment

When designing your application's architecture, you will need to decide how to manage its assets (files). You can either host them on a server, or bundle them with the application itself. While there are valid reasons to bundle your assets with your application, we believe that the pros of remote hosting generally outweigh the cons. Some of the benefits of remote hosting are:

  • Upgrading our library becomes trivial. If the library is packaged with your application, you will need to release a new version before the library license expires. If your users don't upgrade their application, they could be stuck with an expired version of the library. If the library is hosted on your server, you simply need to swap out the files for your users to automatically be upgraded.
  • Because it's so easy to swap out files on a server, the application can be upgraded as frequently as necessary. Shorter release cycles allow for incremental improvement; which in turn leads to less user confusion.

Special considerations when working with webviews/containers

Now that you know what webviews and containers are and how to communicate with them, let's talk about some of the things you need to consider when deploying an application inside of one.

ChartIQ Licensing for native apps

Trial versions of the ChartIQ library are mobile ready and will run on any mobile OS even if bundled with the application itself. So will the production versions when hosted remotely on a server. If you are planning on bundling the production version with your application, please let us know so we can send you a suitable package. The standard domain locked library will not work in this case. See 'Sidebar: Advantages of Remote Deployment' for details on these 2 approaches.

iOS Quirks

iOS WebViews do not automatically follow relative paths. You'll need to ensure that your files can be found by iOS. For more information about relative paths in iOS apps, see this tutorial.

Debugging

You won't have a dev console immediately available. Debugging code running in webviews and containers requires special considering. For more information on remote debugging, check out our debugging tutorial.

Synchronous and asynchronous code

JavaScript is an asynchronous language. This means that it only has a single thread of execution and handles concurrency through events. In contrast, native languages such as Objective-C and Java are synchronous. They handle concurrency using threads. Improper implementation of native <--> JavaScript communication can result in bugs or UI problems.

There are infrequently any problems with native code that calls a JavaScript function. The JavaScript will finish executing and return control back to the native application. More consideration is necessary when JavaScript calls out to a native method. The JavaScript code, and thus the WebView, will be hung until the native code responds. Therefore it is essential that native code that handles JS requests returns immediately. Generally this means that the native code which makes network requests should spin up a new thread, keeping track of the JavaScript context and returning the data at a later point.

Here is sample code for creating a native to JS bridge:

// This will save context so that the native application can return data to JavaScript without hanging the user interface
CIQ.asynchronizer=function(cb){
    var unique=STX.uniqueID();
    window[unique]=function(){
        cb.apply(this, arguments);
        delete window[unique];
    };
    return unique;
};

// Fetch some data from the native interface
function fetchData(key, cb){
    var self=this;
    function response(err, json){
        if(err!="") cb(err);
        else{
            cb(json);
        }
    }

      // nativeInterface will depend on the operating system. Your native code should spin up a new thread. The second parameter will contain a "handle" that we will use to return the data via the cb.
    nativeInterface.fetchData(key, CIQ.asynchronizer(response));
};

// When your native code has data, call this JS function.
CIQ.asynchronizerResult=function(unique, err, data){
  window[unique](err, data);
};

Mobile specific library settings

Crosshair offset

By default, the cross-hair location will be slightly offset so a user can see where the cross-hair is instead of having render it right under their finger. This is done because in small devices, especially when displaying small candles the finger will cover a large area,losing track of where they are.

You can adjust the offsets by modifying the following parameters:

Device identification

The following flags are available to identify devices:

Managing sliding and swiping:

Sometimes the chart will be embedded in a larger page that can be swiped up or down. To decide if you want the chart to respond to the swiping or let the page manage it, see the following settings:

performance

Resources

Recommended Webviews/Containers

iOS provides two webviews - UIWebView, and WKWebView. WKWebView is based on WebKit, the same rendering engine that powers Safari and Chromium. We recommend using WKWebView because it includes just in time (JIT) compiling and therefore performs much better than the older UIWebView. For building Android applications we strongly recommend using the Intel crosswalk SDK. Crosswalk automatically bundles the latest Chromium build which improves performance on Android devices prior to version 4.4.