403Webshell
Server IP : 80.87.202.40  /  Your IP : 216.73.216.169
Web Server : Apache
System : Linux rospirotorg.ru 5.14.0-539.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 5 22:26:13 UTC 2024 x86_64
User : bitrix ( 600)
PHP Version : 8.2.27
Disable Function : NONE
MySQL : OFF |  cURL : ON |  WGET : ON |  Perl : ON |  Python : OFF |  Sudo : ON |  Pkexec : ON
Directory :  /home/bitrix/ext_www/rospirotorg.ru/bitrix/js/catalog/store-chart/src/charts/

Upload File :
current_dir [ Writeable] document_root [ Writeable]

 

Command :


[ Back ]     

Current File : /home/bitrix/ext_www/rospirotorg.ru/bitrix/js/catalog/store-chart/src/charts/stacked-bar-chart.js
// @flow

import {Loc, Event, Tag} from 'main.core';
import type {TChartProps, TColumn, TSeries} from "../types/chart";
import {Popup} from "main.popup";
import './stacked-bar-chart.css';

type TProps = {
	isPopupEnabled: boolean,
	chartProps: TChartProps,
	onChartClick?: ((column: TColumn, series: TSeries) => void),
	onSeriesLabelLoad?: ((chartLegendList: Array) => void),
};

export class StackedBarChart
{
	#chartId: string;
	#chart: am4charts.XYChart;
	#chartPopup: Popup | null;
	#isChartCommon: boolean;
	#onChartClick: Function | null;

	#onSeriesLabelLoadHandler: Function | null;
	#legendIsPrepared: boolean = false;

	#axes = {
		categoryAxis: am4charts.CategoryAxis,
		valueAxis: am4charts.ValueAxis,
	};

	#seriesList: Array<[TSeries, am4charts.ColumnSeries]> = [];
	#seriesLoadedLen: number = 0;

	#isPopupEnabled: boolean;

	constructor(props: TProps)
	{
		this.#isPopupEnabled = props?.isPopupEnabled;
		this.#chartPopup = null;
		this.#onChartClick = props.onChartClick;
		this.#onSeriesLabelLoadHandler = props?.onSeriesLabelLoad;
		this.#initializeChart(props.chartProps);
	}

	#initializeChart(chartProps: TChartProps): void
	{
		window.am4core.useTheme(am4themes_animated);

		this.#chartId = chartProps.id;
		this.#chart = am4core.create(this.#chartId, am4charts.XYChart);
		this.#chart.data = [];

		this.#chart.zoomOutButton.readerTitle = Loc.getMessage('STORE_CHART_ZOOMOUT_TITLE');

		this.#chart.legend = new am4charts.Legend();
		this.#chart.legend.position = 'bottom';

		this.#initAxes();
		this.#initColumnsData(chartProps.columns);
		this.#initSeries(chartProps.seriesList);

		if (chartProps.isCommonChart)
		{
			this.#axes.categoryAxis.renderer.labels.template.html = chartProps.label;
		}

		this.#chart.events.on("inited", () => {
			this.#onChartLoaded();
		});
	}

	#initColumnsTitle(): void
	{
		this.#chart.data.forEach((columnData) => {
			this.#axes.categoryAxis.dataItemsByCategory.getKey(columnData['id']).text = columnData['name'];
		});
	}

	#initAxes(): void
	{
		this.#axes.categoryAxis = this.#chart.xAxes.push(new am4charts.CategoryAxis());
		this.#axes.categoryAxis.dataFields.category = 'id';
		this.#axes.categoryAxis.renderer.grid.template.opacity = 0;

		this.#axes.valueAxis = this.#chart.yAxes.push(new am4charts.ValueAxis());
		this.#axes.valueAxis.min = 0;
		this.#axes.valueAxis.renderer.grid.template.opacity = 0;
		this.#axes.valueAxis.renderer.ticks.template.strokeOpacity = 0.5;
		this.#axes.valueAxis.renderer.ticks.template.length = 10;
		this.#axes.valueAxis.renderer.line.strokeOpacity = 0.5;
		this.#axes.valueAxis.renderer.baseGrid.disabled = true;
		this.#axes.valueAxis.renderer.minGridDistance = 40;
		this.#axes.valueAxis.calculateTotals = true;

		// some space needed for the total label
		this.#axes.categoryAxis.renderer.labels.template.marginRight = 40;
	}

	#initColumnsData(columnsData: Array<TColumn>): void
	{
		this.#chart.data = columnsData.map((columnData) => {
			columnData.id = columnData.id ? columnData.id : BX.util.getRandomString(4);
			return columnData;
		});
	}

	#initSeries(seriesList: Array<TSeries>): void
	{
		const emptySeries = StackedBarChart.createSeries({
			id: 5,
			title: 'empty',
			color: '#ffffff',
		});
		emptySeries.hiddenInLegend = true;
		emptySeries.maskBullets = false;
		this.#chart.series.push(emptySeries);

		seriesList.sort((firstSeries: TSeries, secondSeries: TSeries) => {
			if (!firstSeries.weight)
			{
				return -1;
			}

			if (firstSeries.weight < secondSeries.weight)
			{
				return 1;
			}
			else if (firstSeries.weight > secondSeries.weight)
			{
				return -1;
			}

			return 0;
		});

		seriesList.forEach((seriesData: TSeries) => {
			const seriesObject = this.#chart.series.push(StackedBarChart.createSeries(seriesData));
			this.#seriesList[seriesData.id] = [
				seriesData,
				seriesObject,
			];
			this.#seriesLoadedLen++;

			seriesObject.events.on("inited", (eventObject: Object) => {
				this.#onSeriesLoaded(eventObject.target, seriesData.id);
			}, this);
		});
	}

	#onSeriesLoaded(event, seriesId: string): void
	{
		if (this.#chart.legend.labels.values.length === this.#seriesLoadedLen)
		{
			this.#prepareChartLegend()
		}

		if (this.#isPopupEnabled)
		{
			this.#bindPopupEvents(event, seriesId);
		}
	}

	#prepareChartLegend(): void
	{
		if (this.#legendIsPrepared)
		{
			return;
		}
		else
		{
			this.#legendIsPrepared = true;
		}

		if (this.#onSeriesLabelLoadHandler instanceof Function)
		{
			this.#onSeriesLabelLoadHandler(this.#chart.legend.labels.values);
		}
	}

	#onChartLoaded(): void
	{
		if (!this.#isChartCommon)
		{
			this.#initColumnsTitle();
		}
		else
		{
			this.#axes.categoryAxis.dataItemsByCategory.getKey('0').text = '';
		}
	}

	#bindPopupEvents(seriesObject: Object, seriesId: string): void
	{
		for (let i = 0; i < seriesObject.columns.length; i++)
		{
			const [series,] = this.#seriesList[seriesId];
			const column = {
				columnObject: seriesObject.columns.getIndex(i),
				columnSeries: series,
				storedData: this.#chart.data[i],
			};

			Event.bind(column.columnObject.group.node, 'mouseover', this.#onStuckMouseOver.bind(this, column));
			Event.bind(column.columnObject.group.node, 'mouseout', this.#onStuckMouseOut.bind(this, column));

			if (this.#onChartClick)
			{
				column.columnObject.group.node.style.cursor = 'pointer';
				Event.bind(column.columnObject.group.node, 'click', () => this.#onChartClick(column.storedData, series));
			}
		}
	}

	#onStuckMouseOver(column: Object): void
	{
		let popupContent = column.columnSeries?.getPopupContent(column.storedData);
		if (popupContent && !this.#chartPopup)
		{
			let popupTitle = column.columnSeries.title;
			if (typeof popupContent === 'object')
			{
				popupTitle = popupContent.title ? popupContent.title : popupTitle;
				popupContent = popupContent.content;
			}

			this.#chartPopup = new Popup(
				`stacked-bar-chart-popup-${BX.util.getRandomString(4)}`,
				column.columnObject.group.node,
				{
					content: StackedBarChart.formPopupContent(column.columnSeries.color, popupTitle, popupContent),
					bindOptions: {
						position: "top"
					},
					offsetLeft: 30,
					offsetTop: -1,
					noAllPaddings: true,
					autoHide: false,
					draggable: {restrict: false},
					cacheable: false,
				}
			);
			this.#chartPopup.show();
		}
	}

	#onStuckMouseOut(column: Object): void
	{
		if (this.#chartPopup)
		{
			this.#chartPopup.close();
			this.#chartPopup.destroy();
			this.#chartPopup = null;
		}
	}

	static formPopupContent(color: string, title: string, innerContent: string): HTMLElement
	{
		return Tag.render`
			<div id="chart-popup-template" class="stacked-bar-chart-popup" style="border-color: ${color};">
				<div class="stacked-bar-chart-popup-head">
					<div id="chart-popup-template-title" class="stacked-bar-chart-popup-title">${title}</div>
				</div>
				<div class="stacked-bar-chart-popup-main">
					<div class="stacked-bar-chart-popup-info">
						${innerContent}
					</div>
				</div>
			</div>
		`;
	}

	static createSeries(seriesData: TSeries): am4charts.ColumnSeries
	{
		const series = new am4charts.ColumnSeries();
		series.dataFields.valueY = seriesData.id;
		series.dataFields.categoryX = 'id';
		series.stacked = true;
		series.name = seriesData.title;
		series.fill = am4core.color(seriesData.color);
		series.stroke = am4core.color('#ffffff');

		return series;
	}
}

Youez - 2016 - github.com/yon3zu
LinuXploit