| Index: packages/charted/examples/charts/demo_interactive.dart
|
| diff --git a/packages/charted/examples/charts/demo_interactive.dart b/packages/charted/examples/charts/demo_interactive.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..4688866504f5813259bcaf896998833f0755f661
|
| --- /dev/null
|
| +++ b/packages/charted/examples/charts/demo_interactive.dart
|
| @@ -0,0 +1,256 @@
|
| +/*
|
| + * Copyright 2014 Google Inc. All rights reserved.
|
| + *
|
| + * Use of this source code is governed by a BSD-style
|
| + * license that can be found in the LICENSE file or at
|
| + * https://developers.google.com/open-source/licenses/bsd
|
| + */
|
| +
|
| +library charted.demo.interactive;
|
| +
|
| +import 'dart:html';
|
| +import 'package:observe/observe.dart';
|
| +import 'package:charted/charts/charts.dart';
|
| +
|
| +import 'demo_charts.dart';
|
| +
|
| +const List DIMENSION_COLUMNS = const[0, 4];
|
| +
|
| +int customSeriesCounter = 0;
|
| +
|
| +Map RENDERERS = {
|
| + 'bar-chart': 'Bar chart',
|
| + 'line-chart': 'Line chart',
|
| + 'stacked-bar-chart': 'Stacked bar chart',
|
| + 'waterfall-chart': 'Waterfall chart',
|
| +};
|
| +
|
| +CartesianRenderer getRendererForType(String name) {
|
| + if (name == 'bar-chart') return new BarChartRenderer();
|
| + if (name == 'line-chart') return new LineChartRenderer();
|
| + if (name == 'stacked-bar-chart') return new StackedBarChartRenderer();
|
| + return new BarChartRenderer();
|
| +}
|
| +
|
| +String getTypeForRenderer(CartesianRenderer renderer) {
|
| + if (renderer is BarChartRenderer) return 'bar-chart';
|
| + if (renderer is LineChartRenderer) return 'line-chart';
|
| + if (renderer is StackedBarChartRenderer) return 'stacked-bar-chart';
|
| + return 'bar-chart';
|
| +}
|
| +
|
| +main() {
|
| + List DATA_SOURCE = ORDINAL_DATA;
|
| + ChartSeries activeSeries,
|
| + defaultSeries = new ChartSeries("Default series",
|
| + new ObservableList.from([ 2, 3 ]), new BarChartRenderer());
|
| +
|
| + ObservableList rows = new ObservableList.from(DATA_SOURCE.sublist(0, 10)),
|
| + columns = new ObservableList.from(ORDINAL_DATA_COLUMNS),
|
| + seriesList = new ObservableList.from([ defaultSeries ]);
|
| +
|
| + ChartData data = new ChartData(columns, rows);
|
| + ChartConfig config = new ChartConfig(seriesList, DIMENSION_COLUMNS);
|
| +
|
| + CartesianArea area =
|
| + new CartesianArea(querySelector('.chart-host'),
|
| + data, config, autoUpdate: true, useTwoDimensionAxes: false);
|
| +
|
| + area.addChartBehavior(new ChartTooltip());
|
| + config.legend = new ChartLegend(querySelector('.chart-legend-host'));
|
| +
|
| + area.draw();
|
| +
|
| + /*
|
| + * Create and hook up the control panel
|
| + */
|
| +
|
| + ButtonElement addRowButton = querySelector('#add-row'),
|
| + removeRowButton = querySelector('#remove-row'),
|
| + addSeriesButton = querySelector('#add-series'),
|
| + removeSeriesButton = querySelector('#remove-series');
|
| +
|
| + InputElement useRTLScriptCheckBox = querySelector('#rtl-use-script'),
|
| + switchAxesForRTLCheckBox = querySelector('#rtl-switch-axes'),
|
| + useRTLLayoutCheckBox = querySelector('#rtl-use-layout');
|
| +
|
| + SelectElement seriesSelect = querySelector('#select-series'),
|
| + rendererSelect = querySelector('#select-renderer');
|
| +
|
| + Element columnButtons = querySelector('#column-buttons'),
|
| + chartsContainer = querySelector('.chart-wrapper');
|
| +
|
| + /*
|
| + * RTL handling
|
| + */
|
| +
|
| + useRTLLayoutCheckBox.onChange.listen((_) {
|
| + bool isRTL = useRTLLayoutCheckBox.checked;
|
| + config.isRTL = isRTL;
|
| + chartsContainer.attributes['dir'] = isRTL ? 'rtl' : 'ltr';
|
| + });
|
| +
|
| + useRTLScriptCheckBox.onChange.listen((_) {
|
| + bool isRTL = useRTLScriptCheckBox.checked;
|
| + rows.clear();
|
| + DATA_SOURCE = isRTL ? ORDINAL_DATA_RTL : ORDINAL_DATA;
|
| + rows.addAll(DATA_SOURCE.sublist(0, 10));
|
| + });
|
| +
|
| + /*
|
| + * Updating rows
|
| + */
|
| +
|
| + updateRowButtonStates() {
|
| + addRowButton.disabled = rows.length >= DATA_SOURCE.length;
|
| + removeRowButton.disabled = rows.length <= 1;
|
| + }
|
| +
|
| + addRowButton.onClick.listen((_) {
|
| + if (rows.length < DATA_SOURCE.length) {
|
| + rows.add(DATA_SOURCE.elementAt(rows.length));
|
| + }
|
| + updateRowButtonStates();
|
| + });
|
| +
|
| + removeRowButton.onClick.listen((_) {
|
| + if (rows.length > 0) rows.removeLast();
|
| + updateRowButtonStates();
|
| + });
|
| +
|
| +
|
| + /*
|
| + * Series selection
|
| + */
|
| +
|
| + selectSeries(ChartSeries series) {
|
| + activeSeries = series;
|
| +
|
| + List<Element> options = rendererSelect.children.toList();
|
| + String rendererType = getTypeForRenderer(series.renderer);
|
| + for (int i = 0; i < options.length; i++) {
|
| + if ((options[i] as OptionElement).value == rendererType)
|
| + rendererSelect.selectedIndex = i;
|
| + }
|
| +
|
| + List buttons = querySelectorAll('.column-button');
|
| + Iterable measures = series.measures;
|
| + for (int i = 0; i < buttons.length; i++) {
|
| + buttons[i].checked = measures.contains(i + 1);
|
| + }
|
| + }
|
| +
|
| + updateSeriesSelector([ChartSeries selected]) {
|
| + seriesSelect.children.clear();
|
| + seriesList.forEach((ChartSeries item) {
|
| + var option = new OptionElement()
|
| + ..value = item.name
|
| + ..text = item.name;
|
| + seriesSelect.append(option);
|
| + });
|
| + selectSeries(selected == null ? seriesList.first : selected);
|
| + }
|
| +
|
| + seriesSelect.onChange.listen(
|
| + (_) => selectSeries(seriesList.firstWhere(
|
| + (ChartSeries x) => x.name == seriesSelect.value)));
|
| +
|
| +
|
| + /*
|
| + * Renderer selection for active series
|
| + */
|
| +
|
| + updateRendererSelector() {
|
| + rendererSelect.children.clear();
|
| + RENDERERS.forEach((name, label) {
|
| + var option = new OptionElement()
|
| + ..value = name
|
| + ..text = label;
|
| + rendererSelect.append(option);
|
| + });
|
| + }
|
| +
|
| + rendererSelect.onChange.listen((_) {
|
| + activeSeries.renderer = getRendererForType(rendererSelect.value);
|
| + });
|
| +
|
| +
|
| + /*
|
| + * Column selection on active series
|
| + */
|
| +
|
| + updateColumns([Event e]) {
|
| + if (activeSeries == null) return;
|
| +
|
| + List<Element> buttons = querySelectorAll('.column-button');
|
| + InputElement firstChecked;
|
| + for (int i = 0; i < buttons.length && firstChecked == null; i++) {
|
| + if ((buttons[i] as InputElement).checked) firstChecked = buttons[i];
|
| + }
|
| +
|
| + List measures = activeSeries.measures as List;
|
| + int index = buttons.indexOf(e.target) + 1;
|
| + if ((e.target as InputElement).checked) {
|
| + measures.add(index);
|
| + buttons.forEach((InputElement b) => b.disabled = false);
|
| + } else {
|
| + measures.remove(index);
|
| + if (measures.length <= 1) firstChecked.disabled = true;
|
| + }
|
| + }
|
| +
|
| + updateColumnsList() {
|
| + columnButtons.children.clear();
|
| + for (int i = 0; i < ORDINAL_DATA_COLUMNS.length; ++i) {
|
| + if (i == 0) continue;
|
| + var row = new DivElement(),
|
| + spec = ORDINAL_DATA_COLUMNS.elementAt(i),
|
| + button = new InputElement()
|
| + ..className = 'column-button'
|
| + ..type = 'checkbox'
|
| + ..value = spec.label
|
| + ..id = 'column-$i'
|
| + ..onChange.listen((e) => updateColumns(e)),
|
| + label = new LabelElement()
|
| + ..text = spec.label
|
| + ..htmlFor = 'column-$i';
|
| + row.children.addAll([button,label]);
|
| + columnButtons.append(row);
|
| + };
|
| + }
|
| +
|
| +
|
| + /*
|
| + * Updates to series
|
| + */
|
| +
|
| + updateSeriesButtonStates() {
|
| + removeSeriesButton.disabled = seriesList.length <= 1;
|
| + }
|
| +
|
| + addSeriesButton.onClick.listen((_) {
|
| + var name = 'New Series ${customSeriesCounter}',
|
| + series = new ChartSeries(name, new ObservableList.from([1, 2, 3]),
|
| + new BarChartRenderer());
|
| + seriesList.add(series);
|
| + updateSeriesSelector(series);
|
| + seriesSelect.selectedIndex = seriesList.length - 1;
|
| + updateSeriesButtonStates();
|
| + customSeriesCounter++;
|
| + });
|
| +
|
| + removeSeriesButton.onClick.listen((_) {
|
| + if (seriesList.length > 0) seriesList.removeLast();
|
| + updateSeriesSelector();
|
| + updateSeriesButtonStates();
|
| + });
|
| +
|
| +
|
| + /*
|
| + * Update UI
|
| + */
|
| +
|
| + updateColumnsList();
|
| + updateRendererSelector();
|
| + updateSeriesSelector();
|
| +}
|
|
|