# FlexChart 101

This page shows how to get started with Wijmo's FlexChart control.

## Getting Started

Steps for getting started with the FlexChart in JavaScript applications:

1. Add references to Wijmo.
2. Add markup to serve as the FlexChart's host.
3. Initialize the FlexChart via JavaScript and its itemSource property.
4. Create one or more data series, and add each to the FlexChart's series collection.
5. (Optional) Add some CSS to customize the chart's appearance.

<!DOCTYPE html> <html> <head> <link rel="stylesheet" type="text/css" href="css/bootstrap.css"/> <link rel="stylesheet" type="text/css" href="css/wijmo.css" /> <link href="css/app.css" rel="stylesheet" type="text/css" /> <script src="scripts/wijmo.js" type="text/javascript"></script> <script src="scripts/wijmo.input.js" type="text/javascript"></script> <script src="scripts/wijmo.chart.js" type="text/javascript"></script> <script src="scripts/app.js" type="text/javascript"></script> </head> <body> <!-- this is the FlexChart --> <div id="gettingStartChart"></div> </body> </html>
// create FlexChart var gettingStartedChart = new wijmo.chart.FlexChart('#gettingStartedChart'); // initialize FlexChart's properties gettingStartedChart.initialize({ itemsSource: appData, bindingX: 'country', series: [ { name: 'Sales', binding: 'sales' }, { name: 'Expenses', binding: 'expenses' }, { name: 'Downloads', binding: 'downloads' } ] });
.wj-flexchart { background-color: white; box-shadow: 4px 4px 10px 0px rgba(50, 50, 50, 0.75); height: 400px; margin-bottom: 12px; padding: 8px; }

#### Result (live):

## Chart Types

The FlexChart control has the following three properties, which allow you to customize the chart type:

1. chartType: Selects the default chart type to be used for all the series. Individual series may override this.
2. stacking: Determines whether series are plotted independently, stacked, or stacked so their sum is 100%.
3. rotated: Flips the X and Y axes so X becomes vertical and Y horizontal.

The example below allows you to see what happens when you change these properties:

<div id="chartTypes"></div> <select id="typeMenu"> <option value="0" selected="selected">Column</option> <option value="1">Bar</option> <option value="2">Scatter</option> <option value="3">Line</option> <option value="4">LineSymbols</option> <option value="5">Area</option> <option value="9">Spline</option> <option value="10">SplineSymbols</option> <option value="11">SplineArea</option> </select> <select id="stackingMenu"> <option value="0" selected="selected">None</option> <option value="1">Stacked</option> <option value="2">Stacked 100%</option> </select> <select id="rotatedMenu"> <option value="false" selected="selected">False</option> <option value="true">True</option> </select>
// create FlexChart and Menus var chartTypes = new wijmo.chart.FlexChart('#chartTypes'), typeMenu = new wijmo.input.Menu('#typeMenu'), stackingMenu = new wijmo.input.Menu('#stackingMenu'), rotatedMenu = new wijmo.input.Menu('#rotatedMenu'); // initialize FlexChart's properties chartTypes.initialize({ itemsSource: appData, bindingX: 'country', series: [ { name: 'Sales', binding: 'sales' }, { name: 'Expenses', binding: 'expenses' }, { name: 'Downloads', binding: 'downloads' } ] }); // update the menus' headers updateMenuHeader(typeMenu, 'Chart Type'); updateMenuHeader(stackingMenu, 'Stacking'); updateMenuHeader(rotatedMenu, 'Rotated'); typeMenu.selectedIndexChanged.addHandler(function () { if (typeMenu.selectedValue) { // update FlexChart's chartType chartTypes.chartType = parseInt(typeMenu.selectedValue); // update menu header updateMenuHeader(typeMenu, 'Chart Type'); } }); stackingMenu.selectedIndexChanged.addHandler(function () { if (stackingMenu.selectedValue) { // update FlexChart's stacking property chartTypes.stacking = parseInt(stackingMenu.selectedValue); // update menu header updateMenuHeader(stackingMenu, 'Stacking'); } }); rotatedMenu.selectedIndexChanged.addHandler(function () { if (rotatedMenu.selectedValue) { // specify if chart should be rotated or not chartTypes.rotated = rotatedMenu.selectedValue === 'true'; // update menu header updateMenuHeader(rotatedMenu, 'Rotated'); } }); // helper function for Menu headers function updateMenuHeader(menu, prefix) { menu.header = '<b>' + prefix + '</b>: ' + menu.text; }

#### Result (live):

## Range Bar/Column

The example below shows how to create and a range bar/column chart:

<div id="rangebarChart"></div> <select id="rangebarTypeMenu"> <option value="0" selected="selected">Column</option> <option value="1">Bar</option> </select> <select id="rangebarDataTypeMenu"> <option value="num1,num2" selected="selected">Number</option> <option value="date1,date2">Date</option> </select>
// create FlexChart and Menus var rangebarChart = new wijmo.chart.FlexChart('#rangebarChart'), rangebarTypeMenu = new wijmo.input.Menu('#rangebarTypeMenu'), rangebarDataTypeMenu = new wijmo.input.Menu('#rangebarDataTypeMenu'); // initialize FlexChart's properties rangebarChart.initialize({ itemsSource: rangeData, bindingX: 'country', series: [{ binding: rangebarDataTypeMenu.selectedValue }], tooltip: { content: function (ht) { var str = ht.x + ': <br/>'; var dataTypes = rangebarDataTypeMenu.selectedValue.split(','); var min = Math.min(ht.item[dataTypes[0]], ht.item[dataTypes[1]]); var max = Math.max(ht.item[dataTypes[0]], ht.item[dataTypes[1]]); if (wijmo.isDate(ht.item[dataTypes[0]])) { str += (new Date(min)).toLocaleDateString() + ' - ' + (new Date(max)).toLocaleDateString(); } else { str += Math.round(min) + ' - ' + Math.round(max); } return str; } } }); // update the menus' headers updateMenuHeader(rangebarTypeMenu, 'Chart Type'); updateMenuHeader(rangebarDataTypeMenu, 'Data Type'); rangebarTypeMenu.selectedIndexChanged.addHandler(function () { if (rangebarTypeMenu.selectedValue) { // update FlexChart's chartType rangebarChart.chartType = parseInt(rangebarTypeMenu.selectedValue); // update menu header updateMenuHeader(rangebarTypeMenu, 'Chart Type'); } }); rangebarDataTypeMenu.selectedIndexChanged.addHandler(function () { if (rangebarDataTypeMenu.selectedValue) { // update FlexChart's stacking property var val = rangebarDataTypeMenu.selectedValue; rangebarChart.series[0].binding = val; // update menu header updateMenuHeader(rangebarDataTypeMenu, 'Data Type'); } }); // helper function for Menu headers function updateMenuHeader(menu, prefix) { menu.header = '' + prefix + ': ' + menu.text; }

#### Result (live):

## Funnel Charts

The example below shows how to create and customize a Funnel Chart:

<div id="funnelChart"></div> <dl class="dl-horizontal"> <dt>Neck Width</dt> <dd> <div id="funnelNeckWidth"></div> </dd> </dl> <dl class="dl-horizontal"> <dt>Neck Height</dt> <dd> <div id="funnelNeckHeight"></div> </dd> </dl> <dl class="dl-horizontal"> <dt></dt> <dd> <select id="funnelType"> <option value="default" selected="selected">Default</option> <option value="rectangle">Rectangle</option> </select> </dd> </dl>
// create FlexChart and Menus var funnelChart = new wijmo.chart.FlexChart('#funnelChart'), neckWidth = new wijmo.input.InputNumber('#funnelNeckWidth'), funnelType = new wijmo.input.Menu('#funnelType'), neckHeight = new wijmo.input.InputNumber('#funnelNeckHeight'); // initialize FlexChart's properties funnelChart.initialize({ itemsSource: funnelData, chartType: wijmo.chart.ChartType.Funnel, bindingX: 'country', series: [ { name: 'Sales', binding: 'sales' } ], dataLabel: { content: '{y}' }, options: { funnel: { neckWidth: 0.2, neckHeight: 0.2, type: 'default' } } }); // neckWidth - initialize InputNumber's properties neckWidth.min = 0; neckWidth.max = 1; neckWidth.step = 0.1; neckWidth.valueChanged.addHandler(function (sender) { if (sender.value < sender.min || sender.value > sender.max) { return; } funnelChart.options.funnel.neckWidth = sender.value; funnelChart.refresh(true); }); neckWidth.value = 0.2; // neckHeight - initialize InputNumber's properties neckHeight.min = 0; neckHeight.max = 1; neckHeight.step = 0.1; neckHeight.valueChanged.addHandler(function (sender) { if (sender.value < sender.min || sender.value > sender.max) { return; } funnelChart.options.funnel.neckHeight = sender.value; funnelChart.refresh(true); }); neckHeight.value = 0.2; updateMenuHeader(funnelType, 'Funnel Type'); funnelType.selectedIndexChanged.addHandler(function () { if (funnelType.selectedValue) { funnelChart.options.funnel.type = funnelType.selectedValue; updateMenuHeader(funnelType, 'Funnel Type'); funnelChart.refresh(true); } }); // helper function for Menu headers function updateMenuHeader(menu, prefix) { menu.header = '' + prefix + ': ' + menu.text; }

#### Result (live):

Neck Width

Neck Height

## Mixed Chart Types

You can use different chart types for each chart series by setting the chartType property on the series itself. This overrides the chart's default chart type.

In the example below, the chart's chartType property is set to Column, but the Downloads series overrides it to use the LineAndSymbol chart type:

<div id="mixedTypesChart"></div>
// create FlexChart var mixedTypesChart = new wijmo.chart.FlexChart('#mixedTypesChart'); // initialize FlexChart's properties mixedTypesChart.initialize({ itemsSource: appData, bindingX: 'country', series: [ { name: 'Sales', binding: 'sales' }, { name: 'Expenses', binding: 'expenses' }, { name: 'Downloads', binding: 'downloads', chartType: wijmo.chart.ChartType.LineSymbols } ] });

#### Result (live):

## Legend and Titles

Use legend's properties to customize the appearance of the chart legend, and header, footer, and axis title properties to add titles to your charts.

You can style the legend and titles using CSS. The CSS tab below shows the rules used to customize the appearance of the legend and titles. Notice that these are SVG elements, so you have to use CSS attributes such as "fill" instead of "color."

<div id="chartLegendTitles"></div> <dl class="dl-horizontal"> <dt>Header</dt><dd><input id="headerInput" class="form-control"/></dd> <dt>Footer</dt><dd><input id="footerInput" class="form-control"/></dd> <dt>X-Axis Title</dt><dd><input id="xTitleInput" class="form-control"/></dd> <dt>Y-Axis Title</dt><dd><input id="yTitleInput" class="form-control"/></dd> <dt></dt> <dd> <select id="positionMenu"> <option value="0">None</option> <option value="1">Left</option> <option value="2">Top</option> <option value="3" selected="selected">Right</option> <option value="4">Bottom</option> </select> </dd> </dl>
var chartLegendAndTitles = new wijmo.chart.FlexChart('#chartLegendAndTitles'), positionMenu = new wijmo.input.Menu('#positionMenu'), headerInput = document.getElementById('headerInput'), footerInput = document.getElementById('footerInput'), xTitleInput = document.getElementById('xTitleInput'), yTitleInput = document.getElementById('yTitleInput'); // initialize FlexChart's properties chartLegendAndTitles.initialize({ itemsSource: appData, bindingX: 'country', header: 'Sample Chart', footer: 'copyright (c) ComponentOne', axisX: { title: 'country' }, axisY: { title: 'amount' }, series: [ { name: 'Sales', binding: 'sales' }, { name: 'Expenses', binding: 'expenses' }, { name: 'Downloads', binding: 'downloads' } ] }); // sync the input's value with FlexChart's header headerInput.value = chartLegendAndTitles.header; // update the FlexChart's header headerInput.addEventListener('input', function () { chartLegendAndTitles.header = this.value; }); // sync the input's value with FlexChart's footer footerInput.value = chartLegendAndTitles.footer; // update the FlexChart's footer footerInput.addEventListener('input', function () { chartLegendAndTitles.footer = this.value; }); // sync the input's value with FlexChart's X-Axis title xTitleInput.value = chartLegendAndTitles.axisX.title; // update the FlexChart's X-Axis title xTitleInput.addEventListener('input', function () { chartLegendAndTitles.axisX.title = this.value; }); // sync the input's value with FlexChart's Y-Axis title yTitleInput.value = chartLegendAndTitles.axisY.title; // update the FlexChart's Y-Axis title yTitleInput.addEventListener('input', function () { chartLegendAndTitles.axisY.title = this.value; }); // update menu's header updatePositionMenuHeader(); positionMenu.selectedIndexChanged.addHandler(function () { if (positionMenu.selectedValue) { // update the FlexChart legend's position chartLegendAndTitles.legend.position = parseInt(positionMenu.selectedValue); // update menu's header updatePositionMenuHeader(); } }); function updatePositionMenuHeader() { positionMenu.header = '<b>Legend:</b> ' + positionMenu.text; }
.wj-flexchart .wj-title { font-weight: bold; } .wj-flexchart .wj-header .wj-title { fill: #80044d; font-size: 18pt; } .wj-flexchart .wj-footer .wj-title { fill: #80044d; } .wj-flexchart .wj-axis-x .wj-title, .wj-flexchart .wj-axis-y .wj-title { font-style: italic; }

#### Result (live):

Header
Footer
X-Axis Title
Y-Axis Title

## Tooltips

The FlexChart has built-in support for tooltips. By default, the control displays tooltips when the user touches or hovers the mouse on a data point.

The tooltip content is generated using a template, which may contain the following parameters:

- seriesName: The name of the series that contains the chart element.
- pointIndex: The index of the chart element within the series.
- x: The x value of the chart element.
- y: The y value of the chart element.

By default, the tooltip template is set to `<b>{seriesName}</b><br/>{x} {y}`, and you can see how that works in the charts above. In this example, we set the tooltip template to `<b>{seriesName}</b> <img src='resources/{x}.png'/><br/>{y}`, which replaces the country name with the country's flag.

You can disable the chart tooltips by setting the template to an empty string.

<div id="chartTooltip"></div>
// create FlexChart var chartTooltip = new wijmo.chart.FlexChart('#chartTooltip'); // initialize FlexChart's properties chartTooltip.initialize({ itemsSource: appData, bindingX: 'country', tooltip: { content: "<img src='resources/{x}.png' /> <b>{seriesName}</b><br />{y}" }, series: [ { name: 'Sales', binding: 'sales' }, { name: 'Expenses', binding: 'expenses' }, { name: 'Downloads', binding: 'downloads' } ] });

#### Result (live):

## Styling Series

The FlexChart automatically picks colors for each series based on a default palette, which you can override by setting the palette property. But you can also override the default settings by setting the style property of any series to an object that specifies SVG styling attributes, including fill, stroke, strokeThickness, and so on.

The Series.style property is an exception to the general rule that all styling in Wijmo is done through CSS. The exception reflects the fact that many charts have dynamic series, which would be impossible to style in advance. For example, a stock chart may show series selected by the user while running the application.

The chart in this example uses the style and symbolStyle properties to select style attributes for each series:

<div id="chartSeriesStyle"></div>
// create FlexChart and variables for its series var chartSeriesStyle = new wijmo.chart.FlexChart('#chartSeriesStyle'), salesSeries, expensesSeries, downloadsSeries; chartSeriesStyle.itemsSource = appData; chartSeriesStyle.bindingX = 'country'; // initialize "Sales" data series salesSeries = new wijmo.chart.Series(); salesSeries.name = 'Sales'; salesSeries.binding = 'sales'; salesSeries.style = {}; salesSeries.style.fill = 'green'; salesSeries.style.stroke = 'darkgreen'; salesSeries.style.strokeWidth = 1; // initialize "Expenses" data series expensesSeries = new wijmo.chart.Series(); expensesSeries.name = 'Expenses'; expensesSeries.binding = 'expenses'; expensesSeries.style = {}; expensesSeries.style.fill = 'red'; expensesSeries.style.stroke = 'darkred'; expensesSeries.style.strokeWidth = 1; // initialize "Downloads" data series downloadsSeries = new wijmo.chart.Series(); downloadsSeries.name = 'Downloads'; downloadsSeries.binding = 'downloads'; downloadsSeries.chartType = wijmo.chart.ChartType.LineSymbols; downloadsSeries.style = {}; downloadsSeries.symbolStyle = {}; downloadsSeries.style.stroke = 'orange'; downloadsSeries.style.strokeWidth = 5; downloadsSeries.symbolStyle.fill = 'gold'; downloadsSeries.symbolStyle.stroke = 'gold'; // add data series to chart chartSeriesStyle.series.push(salesSeries); chartSeriesStyle.series.push(expensesSeries); chartSeriesStyle.series.push(downloadsSeries);

#### Result (live):

## Customizing Axes

Use axis properties to customize the chart's axes, including ranges (minimum and maximum), label format, tickmark spacing, and gridlines.

The Axis class has boolean properties that allow you to turn features on or off (axisLine, labels, majorTickMarks, and majorGrid). You can style the appearance of the features that are turned on using CSS.

<div id="chartCustomizeAxes"></div>
// create FlexChart var chartCustomizeAxes = new wijmo.chart.FlexChart('#chartCustomizeAxes'); // initialize FlexChart's properties chartCustomizeAxes.initialize({ itemsSource: appData, bindingX: 'country', axisX: { axisLine: true, majorGrid: true }, axisY: { format: 'c0', max: 10000, majorUnit: 2000, axisLine: true, majorGrid: true }, series: [ { name: 'Sales', binding: 'sales' }, { name: 'Expenses', binding: 'expenses' } ] });

#### Result (live):

## Theming

The appearance of the FlexChart is defined in CSS. In addition to the default theme, we include about a dozen professionally designed themes that customize the appearance of all Wijmo controls to achieve a consistent attractive look.

To customize the appearance of the chart, inspect the elements you want to style and then create some CSS rules that apply to those elements.

For example, if you right-click one of the labels on the X axis in IE or Chrome, you will see that it is an element with the "wj-label" class, that is contained in an element with the "wj-axis-x" class, which is contained in the the top-level control element that has the "wj-flexchart" class. The first CSS rule in this example uses this information to customize the X labels. The rule selector adds the additional requirement that the parent element must have, the "wj-flexchart" and the "custom-flex-chart" classes. Without this, the rule would apply to all the charts on the page.

<div id="chartTheme" class="custom-flex-chart"></div>
// create FlexChart var chartTheme = new wijmo.chart.FlexChart('#chartTheme'); // initialize FlexChart's properties chartTheme.initialize({ itemsSource: appData, bindingX: 'country', series: [ { name: 'Sales', binding: 'sales' }, { name: 'Expenses', binding: 'expenses' }, { name: 'Downloads', binding: 'downloads' } ] });
/* custom chart theme */ .custom-flex-chart.wj-flexchart .wj-axis-x .wj-label, .custom-flex-chart.wj-flexchart .wj-legend .wj-label { font-family: 'Courier New', Courier, monospace; font-weight: bold; } .custom-flex-chart.wj-flexchart .wj-legend > rect, .custom-flex-chart.wj-flexchart .wj-plot-area > rect { fill: #f8f8f8; stroke: #c0c0c0; }

#### Result (live):

## Selection Modes

The FlexChart allows you to select series or data points by clicking or touching them. Use the selectionMode property to specify whether you want to allow selection by series, by data point, or no selection at all (selection is off by default.)

Setting the selectionMode property to Series or Point causes the FlexChart to update the Selection property when the user clicks the mouse, and to apply "wj-state-selected" class to the selected chart elements.

The Selection property returns the currently selected series. To get the currently selected data point, get the currently selected item within the selected series using the Series.collectionView.currentItem property as shown in the example.

<div id="chartSelectionMode"></div> <select id="seletionModeMenu"> <option value="0">None</option> <option value="1" selected="selected">Series</option> <option value="2">Point</option> </select> <select id="chartTypeMenu"> <option value="0" selected="selected">Column</option> <option value="1">Bar</option> <option value="2">Scatter</option> <option value="3">Line</option> <option value="4">LineSymbols</option> <option value="5">Area</option> <option value="9">Spline</option> <option value="10">SplineSymbols</option> <option value="11">SplineArea</option> </select> <div id="seriesContainer" style="display:none"> <h4>Current Selection</h4> <p>Series: <b id="seriesName"></b></p> <dl id="detailContainer" class="dl-horizontal" style="display:none"> <dt>Country</dt><dd id="seriesCountry"></dd> <dt>Sales</dt><dd id="seriesSales"></dd> <dt>Expenses</dt><dd id="seriesExpenses"></dd> <dt>Downloads</dt><dd id="seriesDownloads"></dd> </dl> </div>
var chartSelectionMode = new wijmo.chart.FlexChart('#chartSelectionMode'), typeMenu = new wijmo.input.Menu('#chartTypeMenu'), selectionModeMenu = new wijmo.input.Menu('#seletionModeMenu'), seriesContainer = document.getElementById('seriesContainer'), detailContainer = document.getElementById('detailContainer'); // initialize FlexChart's properties chartSelectionMode.initialize({ itemsSource: appData, bindingX: 'country', selectionMode: wijmo.chart.SelectionMode.Series, series: [ { name: 'Sales', binding: 'sales' }, { name: 'Expenses', binding: 'expenses' }, { name: 'Downloads', binding: 'downloads' } ] }); // update details when the FlexChart's selection changes chartSelectionMode.selectionChanged.addHandler(function () { var currentSelection = chartSelectionMode.selection, currentSelectItem; if (currentSelection) { seriesContainer.style.display = 'block'; // show container document.getElementById('seriesName').innerHTML = currentSelection.name; currentSelectItem = currentSelection.collectionView.currentItem; if (currentSelectItem && selectionModeMenu.selectedValue === '2') { setSeriesDetail(currentSelectItem); // update details } } }); // update Menu header updateMenuHeader(typeMenu, 'Chart Type'); typeMenu.selectedIndexChanged.addHandler(function () { if (typeMenu.selectedValue) { // update FlexChart' chartType chartSelectionMode.chartType = parseInt(typeMenu.selectedValue); // update Menu header updateMenuHeader(typeMenu, 'Chart Type'); } }); // update Menu header updateMenuHeader(selectionModeMenu, 'Selection Mode'); selectionModeMenu.selectedIndexChanged.addHandler(function () { if (selectionModeMenu.selectedValue) { // update FlexChart' selectionMode chartSelectionMode.selectionMode = parseInt(selectionModeMenu.selectedValue); // toggle the series panel's visiblity if (selectionModeMenu.selectedValue === '0' || !chartSelectionMode.selection) { seriesContainer.style.display = 'none'; } else { seriesContainer.style.display = 'block'; } // toggle the series panel's visiblity if (selectionModeMenu.selectedValue !== '2' || !chartSelectionMode.selection || !chartSelectionMode.selection.collectionView.currentItem) { detailContainer.style.display = 'none'; } else { // update the details setSeriesDetail(chartSelectionMode.selection.collectionView.currentItem); } // update Menu header updateMenuHeader(selectionModeMenu, 'Selection Mode'); } }); // helper method to show details of the FlexChart's current selection function setSeriesDetail(currentSelectItem) { detailContainer.style.display = 'block'; document.getElementById('seriesCountry').innerHTML = currentSelectItem.country; document.getElementById('seriesSales').innerHTML = wijmo.Globalize.format(currentSelectItem.sales, 'c2'); document.getElementById('seriesExpenses').innerHTML = wijmo.Globalize.format(currentSelectItem.expenses, 'c2'); document.getElementById('seriesDownloads').innerHTML = wijmo.Globalize.format(currentSelectItem.downloads, 'n0'); }; // helper method for changing menu header function updateMenuHeader(menu, prefix) { menu.header = '<b>' + prefix + '</b>: ' + menu.text; }

#### Result (live):

#### Current Selection

Series:

Country
Sales
Expenses
Downloads

## Toggle Series

The Series class has a visibility property that allows you to determine whether a series should be shown in the chart and in the legend, only in the legend, or completely hidden.

This sample shows how you can use the visibility property to toggle the visibility of a series using two methods:

1. Clicking on legend entries:
   The chart sets the chart's option.legendToggle property to true, which toggles the visibility property of a series when its legend entry is clicked.
2. Using checkboxes:
   When the checked state changed, it will set the visibility property of each series by the checked state.

<div id="chartLegendToggle"></div> Sales <input id="cbSales" type="checkbox"/><br /> Expenses <input id="cbExpenses" type="checkbox"/><br /> Downloads <input id="cbDownloads" type="checkbox"/>
// create FlexChart var chartLegendToggle = new wijmo.chart.FlexChart('#chartLegendToggle'); // initialize FlexChart's properties chartLegendToggle.initialize({ itemsSource: appData, bindingX: 'country', legendToggle: true, series: [ { name: 'Sales', binding: 'sales' }, { name: 'Expenses', binding: 'expenses' }, { name: 'Downloads', binding: 'downloads' } ] }); chartLegendToggle.seriesVisibilityChanged.addHandler(function () { // loop through chart series chartLegendToggle.series.forEach(function (series) { var seriesName = series.name, checked = series.visibility === wijmo.chart.SeriesVisibility.Visible; // update custom checkbox panel document.getElementById('cb' + seriesName).checked = checked; }); }); // loop through custom check boxes ['cbSales', 'cbExpenses', 'cbDownloads'].forEach(function (item, index) { // update checkbox and toggle FlexChart's series visibility when clicked var el = document.getElementById(item); el.checked = chartLegendToggle.series[index].visibility === wijmo.chart.SeriesVisibility.Visible; el.addEventListener('click', function () { if (this.checked) { chartLegendToggle.series[index].visibility = wijmo.chart.SeriesVisibility.Visible; } else { chartLegendToggle.series[index].visibility = wijmo.chart.SeriesVisibility.Legend; } }); });

#### Result (live):

Sales
Expenses
Downloads

## Gradient Colors

The FlexChart supports gradient colors.

The gradient descriptor is an expression formatted as follows: `<type>(<coords>)<colors>[:<offset>[:<opacity>]][-<colors>[:<offset>[:<opacity>]]]-<colors>[:<offset>[:<opacity>]]`. The `<type>` can be either linear or radial. The uppercase `L` or `R` letters indicate absolute coordinates offset from the SVG surface. Lowercase `l` or `r` letters indicate coordinates calculated relative to the element to which the gradient is applied. Coordinates specify a linear gradient vector as `x1`, `y1`, `x2`, `y2`, or a radial gradient as `cx`, `cy`, `r` and optional `fx`, `fy`, `fr` specifying a focal point away from the center of the circle. Specify `<colors>` as a list of dash-separated CSS color values. Each color may be followed by a custom offset and opacity value, separated with a colon character.

Linear gradient format example:

`'l(0,0,1,0)#ff0000-#00ff00-#0000ff'`, `'L(0,0,300,300)#ff0000:0.2:0.2-00ff00:0.8'`

Radial gradient format example:

`'r(0.5,0.5,1)#ff0000-#0000ff'`, `'R(100,100,100,200,200,200)#ff0000-#0000ff'`

### Basic

Select from the predefined gradient colors to see the different appearances.

<div id="predefinedChart"></div> <div> <select id="predefinedColorMenu"> <option value="l(0,0,1,0)#89f7fe-#66a6ff" selected="selected">Light Blue - l(0, 0, 1, 0)#89f7fe-#66a6ff</option> <option value="l(0,0,0,1)#13547a-#80d0c7">Aqua - l(0, 0, 0, 1)#13547a-#80d0c7</option> <option value="l(0,0,1,1)#ff0844-#ffb199">Red - l(0, 0, 1, 1)#ff0844-#ffb199</option> <option value="l(0,0,1,0)#b224ef-#7579ff-#b224ef">Purple - l(0, 0, 1, 0)#b224ef-#7579ff-#b224ef</option> <option value="r(0.5,0.5,0.7)#cc208e-#6713d2">Plum - r(0.5,0.5,0.7)#cc208e-#6713d2</option> <option value="l(0,0,1,0)#30cfd0-#330867">Deep Blue - l(0, 0, 1, 0)#30cfd0-#330867</option> <option value="l(0,0,0,1)#e27f00-#ae1a73">Orange - l(0, 0, 0, 1)#e27f00-#ae1a73</option> <option value="l(0,0,1,1)#abd800-#5c7e00">Green - l(0, 0, 1, 1)#abd800-#5c7e00</option> </select> </div>
var predefinedChart = new wijmo.chart.FlexChart('#predefinedChart'), predefinedColorMenu = new wijmo.input.Menu('#predefinedColorMenu'); // initialize FlexChart's properties predefinedChart.initialize({ itemsSource: appData, bindingX: 'country', series: [ { binding: 'sales' } ] }); updateMenuHeader(predefinedColorMenu, 'Color'); predefinedColorMenu.selectedIndexChanged.addHandler(function () { if (predefinedColorMenu.selectedValue) { applyBasicGradientColor(); updateMenuHeader(predefinedColorMenu, 'Color'); } }); applyBasicGradientColor(); function applyBasicGradientColor() { predefinedChart.series[0].style = { fill: predefinedColorMenu.selectedValue }; predefinedChart.refresh(true); }

#### Result (live):

### Advanced

Set multiple options to customize gradient color.

<div id="chartGradientColors"></div> <dl class="dl-horizontal"> <dt>Generated fill string:</dt> <dd> <label id="gradientColorsLabel"></label> </dd> <dt></dt> <dd> <select id="gradientChartType"> <option value="0" selected="selected">Column</option> <option value="1">Bar</option> <option value="5">Area</option> <option value="11">SplineArea</option> </select> </dd> <dt></dt> <dd> <select id="gradientTypeMenu"> <option value="l" selected="selected">Linear</option> <option value="r">Radial</option> </select> </dd> <dt id="dtGradientDirection"></dt> <dd id="ddGradientDirection"> <select id="gradientDirectionMenu"> <option value="horizontal" selected="selected">Horizontal</option> <option value="vertical">Vertical</option> </select> </dd> <dt>Start Color:</dt> <dd><input id="gradientStartColor"/></dd> <dt>Start Offset:</dt> <dd><input id="gradientStartOffset"/></dd> <dt>Start Opacity:</dt> <dd><input id="gradientStartOpacity"/></dd> <dt>End Color:</dt> <dd><input id="gradientEndColor"/></dd> <dt>End Offset:</dt> <dd><input id="gradientEndOffset"/></dd> <dt>End Opacity:</dt> <dd><input id="gradientEndOpacity"/></dd> </dl>
// create FlexChart and Menus var chart = new wijmo.chart.FlexChart('#chartGradientColors'), gredientLabel = document.getElementById('gradientColorsLabel'), gradientChartType = new wijmo.input.Menu('#gradientChartType'), type = new wijmo.input.Menu('#gradientTypeMenu'), dtDirection = document.getElementById('dtGradientDirection'), ddDirection = document.getElementById('ddGradientDirection'), direction = new wijmo.input.Menu('#gradientDirectionMenu'), startColor = new wijmo.input.InputColor('#gradientStartColor'), startOffset = new wijmo.input.InputNumber('#gradientStartOffset'), startOpacity = new wijmo.input.InputNumber('#gradientStartOpacity'), endColor = new wijmo.input.InputColor('#gradientEndColor'), endOffset = new wijmo.input.InputNumber('#gradientEndOffset'), endOpacity = new wijmo.input.InputNumber('#gradientEndOpacity'); // initialize FlexChart's properties chart.initialize({ itemsSource: appData, bindingX: 'country', series: [ { binding: 'sales' } ] }); applyGradientColor(); //chart type - initialize Menu's properties updateMenuHeader(gradientChartType, 'Chart Type'); gradientChartType.selectedIndexChanged.addHandler(function () { if (gradientChartType.selectedValue) { chart.chartType = +gradientChartType.selectedValue; updateMenuHeader(gradientChartType, 'Chart Type'); } }); //startColor - initialize InputColor's properties startColor.valueChanged.addHandler(function (sender) { applyGradientColor(); }); startColor.value = '#ff0000'; // startOffset - initialize InputNumber's properties startOffset.min = 0; startOffset.max = 1; startOffset.step = 0.1; startOffset.valueChanged.addHandler(function (sender) { if (sender.value < sender.min || sender.value > sender.max) { return; } applyGradientColor(); }); startOffset.value = 0; // startOpacity - initialize InputNumber's properties startOpacity.min = 0; startOpacity.max = 1; startOpacity.step = 0.1; startOpacity.valueChanged.addHandler(function (sender) { if (sender.value < sender.min || sender.value > sender.max) { return; } applyGradientColor(); }); startOpacity.value = 1; //endColor - initialize InputColor's properties endColor.valueChanged.addHandler(function (sender) { applyGradientColor(); }); endColor.value = '#0000ff'; // endOffset - initialize InputNumber's properties endOffset.min = 0; endOffset.max = 1; endOffset.step = 0.1; endOffset.valueChanged.addHandler(function (sender) { if (sender.value < sender.min || sender.value > sender.max) { return; } applyGradientColor(); }); endOffset.value = 1; // endOpacity - initialize InputNumber's properties endOpacity.min = 0; endOpacity.max = 1; endOpacity.step = 0.1; endOpacity.valueChanged.addHandler(function (sender) { if (sender.value < sender.min || sender.value > sender.max) { return; } applyGradientColor(); }); endOpacity.value = 1; updateMenuHeader(type, 'Type'); type.selectedIndexChanged.addHandler(function () { if (type.selectedValue) { updateMenuHeader(type, 'Type'); applyGradientColor(); } }); updateMenuHeader(direction, 'Direction'); direction.selectedIndexChanged.addHandler(function () { if (direction.selectedValue) { updateMenuHeader(direction, 'Direction'); applyGradientColor(); } }); // helper function for Menu headers function updateMenuHeader(menu, prefix) { menu.header = '' + prefix + ': ' + menu.text; } function applyGradientColor() { var color = '', t = type.selectedValue, d = direction.selectedValue; color = t; if (t === 'l') { dtDirection.style.display = 'block'; ddDirection.style.display = 'block'; if (d === 'horizontal') { color += '(0, 0, 1, 0)'; } else { color += '(0, 0, 0, 1)'; } } else { dtDirection.style.display = 'none'; ddDirection.style.display = 'none'; color += '(0.5, 0.5, 0.5)' } color += startColor.value; if (startOffset.value !== 0 || startOpacity.value !== 1) { color += ':' + startOffset.value; } if (startOpacity.value !== 1) { color += ':' + startOpacity.value; } color += '-' + endColor.value; if (endOffset.value !== 1 || endOpacity.value !== 1) { color += ':' + endOffset.value; } if (endOpacity.value !== 1) { color += ':' + endOpacity.value; } gradientColorsLabel.innerHTML = color; chart.series[0].style = { fill: color }; chart.refresh(true); }

#### Result (live):

Generated fill string:
Start Color:
Start Offset:
Start Opacity:
End Color:
End Offset:
End Opacity:

## Dynamic Charts

The FlexChart uses an ICollectionView internally, so any changes you make to the data source are automatically reflected in the chart.

In this sample, we use a timer to add items to the data source, discarding old items to keep the total count at 200. The result is a dynamic chart that scrolls as new data arrives.

<div id="dynamicChart"></div> <dl class="dl-horizontal"> <dt>Update Speed</dt> <dd> <div class="btn-group"> <button id="btnSlow" type="button" class="btn btn-default">Slow</button> <button id="btnMedium" type="button" class="btn btn-default">Medium</button> <button id="btnFast" type="button" class="btn btn-default">Fast</button> <button id="btnStop" type="button" class="btn btn-default">Stop</button> </div> </dd> </dl>
// dynamic data var toAddData, interval, trafficData = new wijmo.collections.ObservableArray(), setInterval = function (interval) { if (toAddData) { clearTimeout(toAddData); toAddData = null; } if (interval) { toAddData = setTimeout(function () { addTrafficItem(trafficData, interval); }); } }, // define the interval hash for the speed buttons intervalHash = { Slow: 200, Medium: 100, Fast: 50, Stop: 0 }, // create FlexChart dynamicChart = new wijmo.chart.FlexChart('#dynamicChart'); // initialize FlexChart's properties dynamicChart.initialize({ chartType: wijmo.chart.ChartType.Area, stacking: wijmo.chart.Stacking.Stacked, itemsSource: trafficData, bindingX: 'time', axisX: { format: 'mm:ss' }, series: [ { name: 'Trucks', binding: 'trucks' }, { name: 'Ships', binding: 'ships' }, { name: 'Planes', binding: 'planes' } ] }); setInterval(500); // Bind the click event to the speed buttons for (var prop in intervalHash) { document.getElementById('btn' + prop).addEventListener('click', buttonClick(intervalHash[prop])); } function buttonClick(value) { return function () { setInterval(value); }; } function addTrafficItem(trafficData, interval) { var len = trafficData.length, last = len ? trafficData[len - 1] : null, trucks = last ? last.trucks : 0, ships = last ? last.ships : 0, planes = last ? last.planes : 0; trucks = Math.max(0, trucks + Math.round(Math.random() * 50 - 25)); ships = Math.max(0, ships + Math.round(Math.random() * 10 - 5)); planes = Math.max(0, planes + Math.round(Math.random() * 10 - 5)); // add random data, limit array length trafficData.push({ time: new Date(), trucks: trucks, ships: ships, planes: planes }); if (trafficData.length > 200) { trafficData.splice(0, 1); } // keep adding if (interval) { toAddData = setTimeout(function () { addTrafficItem(trafficData, interval); }, interval); } }

#### Result (live):

Update Speed