Customization Rules

Developers should NEVER modify library files except the provided HTML sample templates and images. Instead, to modify default functionality you should create separate files that overwrite the default settings, functions and CSS classes. Your can see this being done on the provided sample templates.

These files should then be loaded AFTER the required library files have been loaded so your adjustments take precedence over the default code.

This will allow for straight forward library upgrades without needing to merge any of your changes back into the new library files. Simply replace the files with the new package and your overwrites will continue to supersede the default functionality. Just keep in mind that as the library changes, you may need to also slightly modify your overwrites as indicated by the release notes.

Customization Basics

The color and style of most chart elements is managed by CSS. See CSS Used by the Chart for more information.

Menus and dialogs (the chart "UI") are completely under your control. You can modify the HTML and CSS styling as much as is desired simply by editing the templates that are provided in the SDK.

Customizing Studies

The Study Library is used to initialize all rendering. This is where you would override colors or even the entire rendering function (see CIQ.Studies#studyLibrary).

The output section defines the colors and other artifacts for the rendering of the study.

The Using and Customizing Studies tutorial has more detail on how to define and work with studies.

Here are some examples:

"W MFI": {
    "seriesFN": function(stx, sd, quotes){ return CIQ.Studies.displayMFI(stx, sd, quotes); },        // change rendering function here
    "calculateFN": function(stx, sd){ return CIQ.Studies.calculateMFI(stx, sd); },
    "inputs": {},
    "outputs": {"Green":"#8bc176", "Fade":"#ab611f", "Fake":"#5f7cb8", "Squat":"#ffd0cf"}            // change colors here
},
"ATR Bands": {
    "overlay": true,
    "seriesFN": function(stx, sd, quotes){ return CIQ.Studies.displayChannel(stx, sd, quotes); },    // change rendering function here
    "calculateFN": function(stx, sd){ return CIQ.Studies.calculateATRBands(stx, sd); },
    "inputs": {"Period":5, "Shift": 3, "Field":"field", "Channel Fill":true},
    "outputs": {"ATR Bands Top":"auto", "ATR Bands Bottom":"auto", "ATR Bands Channel":"auto"}        // change colors here
}

More details can be found in the Study Tutorial

Watermarking the Chart

There are different ways to do this:

1- You can create a CSS styled div in your chartContainer to overlay semi-transparent text on the chart. Then you would have the newChart callback function change the innerHTML content with the new symbol name as it changes and a new chart is rendered. This is straight forward and simple to implement. The disadvantage is that if you export the chart, since this is just an HTML element, it will not be part of the picture.

2- We do have a watermark function, you can use that as well:

see CIQ.ChartEngine#watermark

The watermark will have to be redrawn on every frame of the animation loop, or it will disappear. You can do this with an API injection:

Example:

CIQ.ChartEngine.prototype.prepend("draw",function(){ 
    // set the color and font
    stxx.setStyle("stx_watermark","font-size","100px");
    stxx.setStyle("stx_watermark","color","red");

   stxx.watermark("chart",{h:"center",v:"middle",text:stxx.chart.symbol}); 

   // restore the color and font
    stxx.setStyle("stx_watermark","font-size","16px");
    stxx.setStyle("stx_watermark","color","rgba(0,0,0,0.5)");
});

The advantage of the watermark over the div is that it is written on the canvas, so if you were exporting the chart, your watermark will be part of the 'picture'. The disadvantage is that it needs to be redrawn on every frame.

Remember that the CSS style (style stx_watermark) is the same to all watermarks; so be careful since we use this all over for error messages. Mainly on study panels

Customizing Chart Behavior

If you are looking to change default behavior of the chart, rather than look and feel, you can find all configurable settings for the main chart object and associated x and y axis rendering in the following classes:

Feel free to override them as needed to permanently change the defaults, programmatically change on the fly within your code, or send them in as arguments when constructing a new chart for a more dynamic approach.

When sending in a 'config' argument, any field or object within the config will be added to the CIQ.ChartEngine object itself or override defaults.

If you wanted to create a new candle chart with corsshairs enabled on initial load, you can do something like this:

var stxx=new CIQ.ChartEngine({container:$$("chartContainerSilver"), layout:{crosshair:true, chartType:"candle"}});

This overrides stxx.layout.crosshair with a value of true and stxx.layout.chartType with a value of "candle".

Or if you wanted to change the shape of the y axis price labels, you can choose from the following: "roundRectArrow", "semiRoundRect", "roundRect","tickedRect","rect","noop" as follows:

var stxx=new CIQ.ChartEngine({container:$$$(".chartContainer"), yaxisLabelStyle:"rect", layout:{"candleWidth": 16, "crosshair":true}});

Or you can use the following syntax if you want to change it dynamically after the chart object has been created:

var stxx=new CIQ.ChartEngine({container: $$("chartContainer")});
// do other things here...
stxx.yaxisLabelStyle="roundRectArrow";

For additional axis manipulations see Custom X-axis and Gridlines and axis labels.

Popular UI customizations

Disabling Zooming and Panning

Right after your new CIQ.ChartEngine() declaration put the following lines:

stxx.allowZoom=false;
stxx.allowScroll=false;

See CIQ.ChartEngine#allowZoom and CIQ.ChartEngine#allowScroll for more details.

You may also want to remove the zoom-in and zoom-out buttons by modifying the CSS as follows:

In stx-chart.css add display: none; to the following style:

#chartSize { /* Chart size container */
    display: none;
}

Alternatively, you can also disable and re-enable the zoom controls dynamically by using the following code; preferably in the newChart() callback function:

     if(stxx.controls.chartControls /* && put your condition for enabling/disabling here*/){
        stxx.controls.chartControls.style.display="block";        // use this line to enable the controls
        stxx.controls.chartControls.style.display="none";        // use this line to disable the controls
    }

If all you want to do is to remove the touch and mouse zooming and panning but allow the zoom buttons to work, use the API injections outlined in the 'Disabling/enabling touch and mouse events' on the Popular API Injections tutorial.

Tip: You may override controls like "zoom", "home" and "more" if you wish to provide your own navigational components. Place your own divs with the same id tags into the chart div container. The chart will use those instead of making its own. Or, simply modify the css to change the look of the existing components. Finally, to hide any of these objects, set the corresponding entry to null in the stx object before creating a chart. The complete list of these objects is outlined in CIQ.ChartEngine.htmlControls.

Decimal place precision

The default is to set display precision to the maximum that is found in the data set. This can be overridden however by setting stxx.chart.yAxis.decimalPlaces=<your value>. Note that by default, the current price label will continue to display the higher level of precision. To limit the price label set stxx.chart.yAxis.maxDecimalPlaces=<your value>.

Overriding default y-axis rendering

The y-axis rendering can take in a function to override the default formatting. This function will be called before rendering each tag on the y-axis.

For example, you may want to display prices in fractions instead of decimals. You would set it up as flows in the newChart callback:

stxx.chart.panel.yAxis.priceFormatter=function(stx, pannel, price){
    var convertedPrice;
    // add our logic here to convert 'price' to 'convertedPrice'
      return convertedPrice; 
}

to remove it you would do this:

stxx.chart.panel.yAxis.priceFormatter=null;

Advanced customization -- API injections

Many modules can be overwritten with an API injection if necessary (append/prepend). We can assist you in creating the necessary code injections if you find there are things you want to change beyond what is made available trough the configurable settings.

The charting engine is essentially an animation engine. When a user scrolls or pans a chart, it is redrawn at animation speeds, providing the appearance of a smoothly moving chart in much the same way that a video game does. CIQ.ChartEngine#draw is the rendering function that is called to animate the chart and therefore the most common method for extending chart functionality is to extend the draw() function itself. This can be done easily with the Injection API (see below for more details on the Injection API).

There are two ways to visually extend the draw() function:

  1. By drawing on the canvas
  2. By displaying HTML components

For instance, as a developer you may wish to display an arrow somewhere on the screen. This could be accomplished either by physically drawing an arrow using the canvas, or by creating an HTML arrow object and superimposing it on the canvas. The choice of which technique to use depends on your "use case". Drawing on the canvas takes more programming effort, but if you are sharing charts then you must use this approach because HTML elements will not render on a shared chart image. However, complex interactive graphics are easier to create as plain HTML and so might be the better approach for complex interfaces. For example, Trade From Chart is primarily implemented using HTML elements that are superimposed on the chart.

Your first step to customization is to append your own code to the end of the draw() function. You can do this with the following statement:

CIQ.ChartEngine.prototype.append("draw", function(){

  // my custom code here

});

This code will now get called whenever the chart is redrawn (possibly hundreds of times per second if the user is scrolling the chart).

You can do anything you want in this code, such as custom drawing. Logically, placing customized drawings or objects on the chart requires finding the appropriate positioning along the x and y axis in pixels. The charting engine however provides functions that allow you to determine the physical X and Y coordinates given dates and prices using functions such as CIQ.ChartEngine#pixelFromPrice and CIQ.ChartEngine#pixelFromDate.

The charting display is subdivided into panels. Each study is drawn in a panel. The chart itself is also a panel. Each panel has its own y-axis. The stx.panels object contains all of the panels on the chart. Drawing on the chart panel is the simplest and most common task. You can get the chart panel easily:

CIQ.ChartEngine.prototype.append("draw", function(){
  var panel=this.chart.panel; // "this" is your stxx object
});

Once you have access to a panel you can determine the X and Y coordinates on the canvas given a price and date (or dateTime:

CIQ.ChartEngine.prototype.append("draw", function(){
  var panel=this.chart.panel;
  var dt=yyyymmddhhss(myDate);
  var x=this.pixelFromDate(dt, panel.chart);
  var y=this.pixelFromPrice(myPrice, panel);
});

Note that pixelFromPrice() can take a value rather than a price if you are dealing with a study panel (for instance a stochastics panel would require a value between 1 and 100)

Now you might want to draw using HTML5 canvas commands:

CIQ.ChartEngine.prototype.append("draw", function(){

  var panel=this.chart.panel;
  var dt=yyyymmddhhss(myDate);
  var x=this.pixelFromDate(dt, panel.chart);
  var y=this.pixelFromPrice(myPrice, panel);

  this.chart.context.fillRect(x,y,x+10,y+10);

});

Placement of HTML objects depends on how they are created. If objects are added to the chart container then positioning is quite simple:

// in your html page

var myHTMLObject=document.createElement("DIV");
myHTMLObject.style.position="absolute";
stxx.chart.container.appendChild(myHTMLObject);

CIQ.ChartEngine.prototype.append("draw", function(){

  var panel=this.chart.panel;
  var dt=yyyymmddhhss(myDate);
  var x=this.pixelFromDate(dt, panel.chart);
  var y=this.pixelFromPrice(myPrice, panel);

  myHTMLObject.style.left=x+"px";
  myHTMLObject.style.top=y+"px";

});

If objects are absolutely positioned at the document level you can use CIQ.ChartEngine#resolveX and CIQ.ChartEngine#resolveY to convert to absolute screen coordinates

// in your html page

var myHTMLObject=document.createElement("DIV");

myHTMLObject.style.position="absolute";
document.body.appendChild(myHTMLObject);

CIQ.ChartEngine.prototype.append("draw", function(){

  var panel=this.chart.panel;
  var dt=yyyymmddhhss(myDate);
  var x=this.pixelFromDate(dt, panel.chart);
  var y=this.pixelFromPrice(myPrice, panel);

  myHTMLObject.style.left=this.resolveX(x)+"px";
  myHTMLObject.style.top=this.resolveY(y)+"px";

});

Management of HTML objects is up to you as the developer so you'll need to build logic into your draw() extension to determine when to display or not display the objects.

You can use panel.top, panel.bottom, chart.left and chart.right to determine the boundaries of a panel.

It is also possible to work with "bars". A bar is a candle location on the screen. The number of ticks displayed on the screen is chart.maxTicks.

For instance if you wanted to draw a line between bars 5 and 10 on the screen:

CIQ.ChartEngine.prototype.append("draw", function(){

  var panel=this.chart.panel;
  var x0=this.pixelFromBar(5);
  var x1=this.pixelFromBar(10);

// draw line between x0 and x1

});

Note: If using transformations (such comparison charts that transform a price to a percentage) then pixelFromPrice() will return a Y value based on the transformation. For instance, to get the Y location of a closing price in a comparison chart you would use pixelFromPrice(someBar.Close). Whereas if you wanted to get the pixel for the Y axis location of 10% you would use pixelFromTransformedValue(10). If no transformation is in effect then the two functions are equivalent.

More details can be found in the Injection API Tutorial

Where do I put my injection code?

It is recommended to put the API injections on the main HTML file you have customized to render the chart or a separate js file. Never in any of the library files. In this way, when a new release is available, you won't have to worry about merging you customized code into the core library files.

Anywhere within the tags will work.

Here is an example of what your code may look like:

<!doctype html>
<html>
<head>
</head>
<body onLoad="displayChart()">
<script>

// API injection 
CIQ.ChartEngine.prototype.prepend("someFunction", function(){
    // injection code here;
});

// Declare a CIQ.ChartEngine object. This is the main object for drawing charts
var stxx=new CIQ.ChartEngine({container:$$("chartContainer"), layout:{"candleWidth": 16, "crosshair":true}});

// more js here

</script>
</body>
</html>

Can I disable the inertia (animated) scroll and zoom effects ?

By default, the chart will use a rolling effect to continue to scroll or zoom the cart as you swipe or pinch it; depending on your gesture velocity. The faster you gesture, the more it will continue to 'roll' and decrementally slow down until it comes to a full stop. If you want to disable this rolling effect, add this to your project right after you call new stxChart():

// stops zooming animation
stxx.animations.zoom=new CIQ.EaseMachine(Math.easeOutCubic,1);
// stops scrolling animation 
stxx.swipeRelease=function(){};