apexcharts
Version:
A JavaScript Chart Library
312 lines (271 loc) • 9.17 kB
JavaScript
import Graphics from '../Graphics'
import Utils from '../../utils/Utils'
export default class Helpers {
constructor(lgCtx) {
this.w = lgCtx.w
this.lgCtx = lgCtx
}
getLegendStyles() {
let stylesheet = document.createElement('style')
stylesheet.setAttribute('type', 'text/css')
const nonce =
this.lgCtx.ctx?.opts?.chart?.nonce || this.w.config.chart.nonce
if (nonce) {
stylesheet.setAttribute('nonce', nonce)
}
const text = `
.apexcharts-flip-y {
transform: scaleY(-1) translateY(-100%);
transform-origin: top;
transform-box: fill-box;
}
.apexcharts-flip-x {
transform: scaleX(-1);
transform-origin: center;
transform-box: fill-box;
}
.apexcharts-legend {
display: flex;
overflow: auto;
padding: 0 10px;
}
.apexcharts-legend.apexcharts-legend-group-horizontal {
flex-direction: column;
}
.apexcharts-legend-group {
display: flex;
}
.apexcharts-legend-group-vertical {
flex-direction: column-reverse;
}
.apexcharts-legend.apx-legend-position-bottom, .apexcharts-legend.apx-legend-position-top {
flex-wrap: wrap
}
.apexcharts-legend.apx-legend-position-right, .apexcharts-legend.apx-legend-position-left {
flex-direction: column;
bottom: 0;
}
.apexcharts-legend.apx-legend-position-bottom.apexcharts-align-left, .apexcharts-legend.apx-legend-position-top.apexcharts-align-left, .apexcharts-legend.apx-legend-position-right, .apexcharts-legend.apx-legend-position-left {
justify-content: flex-start;
align-items: flex-start;
}
.apexcharts-legend.apx-legend-position-bottom.apexcharts-align-center, .apexcharts-legend.apx-legend-position-top.apexcharts-align-center {
justify-content: center;
align-items: center;
}
.apexcharts-legend.apx-legend-position-bottom.apexcharts-align-right, .apexcharts-legend.apx-legend-position-top.apexcharts-align-right {
justify-content: flex-end;
align-items: flex-end;
}
.apexcharts-legend-series {
cursor: pointer;
line-height: normal;
display: flex;
align-items: center;
}
.apexcharts-legend-text {
position: relative;
font-size: 14px;
}
.apexcharts-legend-text *, .apexcharts-legend-marker * {
pointer-events: none;
}
.apexcharts-legend-marker {
position: relative;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
margin-right: 1px;
}
.apexcharts-legend-series.apexcharts-no-click {
cursor: auto;
}
.apexcharts-legend .apexcharts-hidden-zero-series, .apexcharts-legend .apexcharts-hidden-null-series {
display: none !important;
}
.apexcharts-inactive-legend {
opacity: 0.45;
}
`
let rules = document.createTextNode(text)
stylesheet.appendChild(rules)
return stylesheet
}
getLegendDimensions() {
const w = this.w
let currLegendsWrap =
w.globals.dom.baseEl.querySelector('.apexcharts-legend')
let { width: currLegendsWrapWidth, height: currLegendsWrapHeight } =
currLegendsWrap.getBoundingClientRect()
return {
clwh: currLegendsWrapHeight,
clww: currLegendsWrapWidth,
}
}
appendToForeignObject() {
const gl = this.w.globals
gl.dom.elLegendForeign.appendChild(this.getLegendStyles())
}
toggleDataSeries(seriesCnt, isHidden) {
const w = this.w
if (w.globals.axisCharts || w.config.chart.type === 'radialBar') {
w.globals.resized = true // we don't want initial animations again
let seriesEl = null
let realIndex = null
// yes, make it null. 1 series will rise at a time
w.globals.risingSeries = []
if (w.globals.axisCharts) {
seriesEl = w.globals.dom.baseEl.querySelector(
`.apexcharts-series[data\\:realIndex='${seriesCnt}']`
)
realIndex = parseInt(seriesEl.getAttribute('data:realIndex'), 10)
} else {
seriesEl = w.globals.dom.baseEl.querySelector(
`.apexcharts-series[rel='${seriesCnt + 1}']`
)
realIndex = parseInt(seriesEl.getAttribute('rel'), 10) - 1
}
if (isHidden) {
const seriesToMakeVisible = [
{
cs: w.globals.collapsedSeries,
csi: w.globals.collapsedSeriesIndices,
},
{
cs: w.globals.ancillaryCollapsedSeries,
csi: w.globals.ancillaryCollapsedSeriesIndices,
},
]
seriesToMakeVisible.forEach((r) => {
this.riseCollapsedSeries(r.cs, r.csi, realIndex)
})
} else {
this.hideSeries({ seriesEl, realIndex })
}
} else {
// for non-axis charts i.e pie / donuts
let seriesEl = w.globals.dom.Paper.findOne(
` .apexcharts-series[rel='${seriesCnt + 1}'] path`
)
const type = w.config.chart.type
if (type === 'pie' || type === 'polarArea' || type === 'donut') {
let dataLabels = w.config.plotOptions.pie.donut.labels
const graphics = new Graphics(this.lgCtx.ctx)
graphics.pathMouseDown(seriesEl, null)
this.lgCtx.ctx.pie.printDataLabelsInner(seriesEl.node, dataLabels)
}
seriesEl.fire('click')
}
}
getSeriesAfterCollapsing({ realIndex }) {
const w = this.w
const gl = w.globals
let series = Utils.clone(w.config.series)
if (gl.axisCharts) {
let yaxis = w.config.yaxis[gl.seriesYAxisReverseMap[realIndex]]
const collapseData = {
index: realIndex,
data: series[realIndex].data.slice(),
type: series[realIndex].type || w.config.chart.type,
}
if (yaxis && yaxis.show && yaxis.showAlways) {
if (gl.ancillaryCollapsedSeriesIndices.indexOf(realIndex) < 0) {
gl.ancillaryCollapsedSeries.push(collapseData)
gl.ancillaryCollapsedSeriesIndices.push(realIndex)
}
} else {
if (gl.collapsedSeriesIndices.indexOf(realIndex) < 0) {
gl.collapsedSeries.push(collapseData)
gl.collapsedSeriesIndices.push(realIndex)
let removeIndexOfRising = gl.risingSeries.indexOf(realIndex)
gl.risingSeries.splice(removeIndexOfRising, 1)
}
}
} else {
gl.collapsedSeries.push({
index: realIndex,
data: series[realIndex],
})
gl.collapsedSeriesIndices.push(realIndex)
}
gl.allSeriesCollapsed =
gl.collapsedSeries.length + gl.ancillaryCollapsedSeries.length ===
w.config.series.length
return this._getSeriesBasedOnCollapsedState(series)
}
hideSeries({ seriesEl, realIndex }) {
const w = this.w
let series = this.getSeriesAfterCollapsing({
realIndex,
})
let seriesChildren = seriesEl.childNodes
for (let sc = 0; sc < seriesChildren.length; sc++) {
if (
seriesChildren[sc].classList.contains('apexcharts-series-markers-wrap')
) {
if (seriesChildren[sc].classList.contains('apexcharts-hide')) {
seriesChildren[sc].classList.remove('apexcharts-hide')
} else {
seriesChildren[sc].classList.add('apexcharts-hide')
}
}
}
this.lgCtx.ctx.updateHelpers._updateSeries(
series,
w.config.chart.animations.dynamicAnimation.enabled
)
}
riseCollapsedSeries(collapsedSeries, seriesIndices, realIndex) {
const w = this.w
let series = Utils.clone(w.config.series)
if (collapsedSeries.length > 0) {
for (let c = 0; c < collapsedSeries.length; c++) {
if (collapsedSeries[c].index === realIndex) {
if (w.globals.axisCharts) {
series[realIndex].data = collapsedSeries[c].data.slice()
} else {
series[realIndex] = collapsedSeries[c].data
}
if (typeof series[realIndex] !== 'number') {
series[realIndex].hidden = false
}
collapsedSeries.splice(c, 1)
seriesIndices.splice(c, 1)
w.globals.risingSeries.push(realIndex)
}
}
series = this._getSeriesBasedOnCollapsedState(series)
this.lgCtx.ctx.updateHelpers._updateSeries(
series,
w.config.chart.animations.dynamicAnimation.enabled
)
}
}
_getSeriesBasedOnCollapsedState(series) {
const w = this.w
let collapsed = 0
if (w.globals.axisCharts) {
series.forEach((s, sI) => {
if (
!(
w.globals.collapsedSeriesIndices.indexOf(sI) < 0 &&
w.globals.ancillaryCollapsedSeriesIndices.indexOf(sI) < 0
)
) {
series[sI].data = []
collapsed++
}
})
} else {
series.forEach((s, sI) => {
if (!w.globals.collapsedSeriesIndices.indexOf(sI) < 0) {
series[sI] = 0
collapsed++
}
})
}
w.globals.allSeriesCollapsed = collapsed === series.length
return series
}
}