billboard.js
Version:
Re-usable easy interface JavaScript chart library, based on D3 v4+
185 lines (182 loc) • 6.26 kB
JavaScript
/*!
* Copyright (c) 2017 ~ present NAVER Corp.
* billboard.js project is licensed under the MIT license
*
* billboard.js, JavaScript chart library
* https://naver.github.io/billboard.js/
*
* @version 4.0.1
*/
import { $COMMON } from '../../config/classes.js';
import { parseDate, extend } from '../../module/util/object.js';
/**
* Select subchart by giving x domain range.
* - **ℹ️ NOTE:**
* - Due to the limitations of floating point precision, domain value may not be exact returning approximately values.
* @function subchart
* @instance
* @memberof Chart
* @param {Array} domainValue If domain range is given, the subchart will be selected to the given domain. If no argument is given, the current subchart selection domain will be returned.
* @returns {Array} domain value in array
* @example
* // Specify domain for subchart selection
* chart.subchart([1, 2]);
*
* // Get the current subchart selection domain range
* // Domain value may not be exact returning approximately values.
* chart.subchart();
*/
// NOTE: declared function assigning to variable to prevent duplicated method generation in JSDoc.
const subchart = function (domainValue) {
const $$ = this.internal;
const { axis, brush, config, scale: { x, subX }, state } = $$;
let domain;
if (state.isCanvasMode) {
if (config.subchart_show) {
domain = domainValue;
if (Array.isArray(domain)) {
domain = axis.isTimeSeries() ? domain.map(x => parseDate.bind($$)(x)) : domain;
domain = $$.setCanvasSubchartDomain(domain) || state.domain;
}
else {
domain = state.domain ?? x.orgDomain();
}
}
return domain;
}
if (config.subchart_show) {
domain = domainValue;
if (Array.isArray(domain)) {
if (axis.isTimeSeries()) {
domain = domain.map(x => parseDate.bind($$)(x));
}
const isWithinRange = $$.withinRange(domain, $$.getZoomDomain("subX", true), $$.getZoomDomain("subX"));
if (isWithinRange) {
// store a copy: brush events mutate state.domain in place,
// which would corrupt the caller-passed array
state.domain = domain.slice();
brush.move(brush.getSelection(), domain.map(subX));
}
}
else {
domain = state.domain ?? x.orgDomain();
}
}
return domain;
};
extend(subchart, {
/**
* Show subchart
* - **NOTE:** for ESM imports, needs to import 'subchart' exports and instantiate it by calling `subchart()`.
* @function subchart․show
* @instance
* @memberof Chart
* @example
* // for ESM imports, needs to import 'subchart' and must be instantiated first to enable subchart's API.
* import {subchart} from "billboard.js";
*
* const chart = bb.generate({
* ...
* subchart: {
* // need to be instantiated by calling 'subchart()'
* enabled: subchart()
*
* // in case don't want subchart to be shown at initialization, instantiate with '!subchart()'
* enabled: !subchart()
* }
* });
*
* chart.subchart.show();
*/
show() {
const $$ = this.internal;
const { $el: { subchart }, config } = $$;
const show = config.subchart_show;
if (!show) {
if ($$.state.isCanvasMode) {
$$.unbindZoomEvent?.();
config.subchart_show = true;
this.resize();
return;
}
// unbind zoom event bound to chart rect area
$$.unbindZoomEvent();
config.subchart_show = !show;
!subchart.main && $$.initSubchart();
let $target = subchart.main.selectAll(`.${$COMMON.target}`);
// need to cover when new data has been loaded
if ($$.data.targets.length !== $target.size()) {
$$.updateSizes();
$$.updateTargetsForSubchart($$.data.targets);
$target = subchart.main?.selectAll(`.${$COMMON.target}`);
}
$target?.style("opacity", null);
subchart.main?.style("display", null);
this.resize();
}
},
/**
* Hide generated subchart
* - **NOTE:** for ESM imports, needs to import 'subchart' exports and instantiate it by calling `subchart()`.
* @function subchart․hide
* @instance
* @memberof Chart
* @example
* chart.subchart.hide();
*/
hide() {
const $$ = this.internal;
const { $el: { subchart: { main } }, config } = $$;
if ($$.state.isCanvasMode) {
if (config.subchart_show) {
config.subchart_show = false;
this.resize();
$$.bindZoomEvent?.();
}
return;
}
if (config.subchart_show && main?.style("display") !== "none") {
config.subchart_show = false;
main.style("display", "none");
this.resize();
}
},
/**
* Toggle the visibility of subchart
* - **NOTE:** for ESM imports, needs to import 'subchart' exports and instantiate it by calling `subchart()`.
* @function subchart․toggle
* @instance
* @memberof Chart
* @example
* // When subchart is hidden, will be shown
* // When subchart is shown, will be hidden
* chart.subchart.toggle();
*/
toggle() {
const $$ = this.internal;
const { config } = $$;
this.subchart[config.subchart_show ? "hide" : "show"]();
},
/**
* Reset subchart selection
* @function subchart․reset
* @instance
* @memberof Chart
* @example
* // Reset subchart selection
* chart.subchart.reset();
*/
reset() {
const $$ = this.internal;
const { brush } = $$;
if ($$.state.isCanvasMode) {
$$.clearCanvasSubchartDomain?.(true, false);
return;
}
brush.clear(brush.getSelection());
}
});
var apiSubchart = {
subchart
};
export { apiSubchart as default };