'use strict' ; import type Chart from '../../Core/Chart/Chart' ; import type Legend from '../../Core/Legend/Legend' ; import type Options from '../../Core/Options' ; import type Point from '../../Core/Series/Point' ; import type Series from '../../Core/Series/Series' ; import BubbleLegendDefaults from './BubbleLegendDefaults.js' ; import BubbleLegendItem from './BubbleLegendItem.js' ; import D from '../../Core/DefaultOptions.js' ; const { setOptions } = D ; import U from '../../Core/Utilities.js' ; const { addEvent , objectEach , wrap } = U ; namespace BubbleLegendComposition { const composedClasses = [ ] ; /**
     * If ranges are not specified, determine ranges from rendered bubble series
     * and render legend again.
     */ function chartDrawChartBox ( this , proceed , options , callback ) { const chart = this , legend = chart . legend , bubbleSeries = getVisibleBubbleSeriesIndex ( chart ) >= 0 ; let bubbleLegendOptions , bubbleSizes ; if ( legend && legend . options . enabled && legend . bubbleLegend && ( legend . options . bubbleLegend as any ) . autoRanges && bubbleSeries ) { bubbleLegendOptions = legend . bubbleLegend . options ; bubbleSizes = legend . bubbleLegend . predictBubbleSizes ( ) ; legend . bubbleLegend . updateRanges ( bubbleSizes [ 0 ] , bubbleSizes [ 1 ] ) ; if ( ! bubbleLegendOptions . placed ) { legend . group . placed = false ; legend . allItems . forEach ( function ( item ) : void { ( item . legendGroup as any ) . translateY = null ; } ) ; } legend . render ( ) ; chart . getMargins ( ) ; chart . axes . forEach ( function ( axis ) : void { if ( axis . visible ) { axis . render ( ) ; } if ( ! bubbleLegendOptions . placed ) { axis . setScale ( ) ; axis . updateNames ( ) ; objectEach ( axis . ticks , function ( tick ) : void { tick . isNew = true ; tick . isNewLabel = true ; } ) ; } } ) ; bubbleLegendOptions . placed = true ; chart . getMargins ( ) ; proceed . call ( chart , options , callback ) ; legend . bubbleLegend . correctSizes ( ) ; retranslateItems ( legend , getLinesHeights ( legend ) ) ; } else { proceed . call ( chart , options , callback ) ; if ( legend && legend . options . enabled && legend . bubbleLegend ) { legend . render ( ) ; retranslateItems ( legend , getLinesHeights ( legend ) ) ; } } } private param { Highcharts . Chart } ChartClass param { Highcharts . Legend } LegendClass param { Highcharts . Series } SeriesClass export function compose ( ChartClass , LegendClass , SeriesClass ) { if ( composedClasses . indexOf ( ChartClass ) === - 1 ) { composedClasses . push ( ChartClass ) ; setOptions ( { legend : { bubbleLegend : BubbleLegendDefaults } } ) ; wrap ( ChartClass . prototype , 'drawChartBox' , chartDrawChartBox ) ; } if ( composedClasses . indexOf ( LegendClass ) === - 1 ) { composedClasses . push ( LegendClass ) ; addEvent ( LegendClass , 'afterGetAllItems' , onLegendAfterGetAllItems ) ; } if ( composedClasses . indexOf ( SeriesClass ) === - 1 ) { composedClasses . push ( SeriesClass ) ; addEvent ( SeriesClass , 'legendItemClick' , onSeriesLegendItemClick ) ; } } private function param { Highcharts . Chart } chart return { number } function getVisibleBubbleSeriesIndex ( chart ) { const series = chart . series ; let i = 0 ; while ( i < series . length ) { if ( series [ i ] && series [ i ] . isBubble && series [ i ] . visible && ( series [ i ] as any ) . zData . length ) { return i ; } i ++ ; } return - 1 ; } private function param { Highcharts . Legend } legend return { Array < Highcharts . Dictionary < number > > } function getLinesHeights ( legend ) { const items = legend . allItems , lines = [ ] as Array < Record < string , number > > , length = items . length ; let lastLine , i = 0 , j = 0 ; for ( i = 0 ; i < length ; i ++ ) { if ( items [ i ] . legendItemHeight ) { ( items [ i ] as any ) . itemHeight = items [ i ] . legendItemHeight ; } if ( items [ i ] === items [ length - 1 ] || items [ i + 1 ] && ( items [ i ] . _legendItemPos as any ) [ 1 ] !== ( items [ i + 1 ] . _legendItemPos as any ) [ 1 ] ) { lines . push ( { height : 0 } ) ; lastLine = lines [ lines . length - 1 ] ; for ( j ; j <= i ; j ++ ) { if ( ( items [ j ] as any ) . itemHeight > lastLine . height ) { lastLine . height = ( items [ j ] as any ) . itemHeight ; } } lastLine . step = i ; } } return lines ; } /**
     * Start the bubble legend creation process.
     */ function onLegendAfterGetAllItems ( this , e ) { const legend = this , bubbleLegend = legend . bubbleLegend , legendOptions = legend . options , options = legendOptions . bubbleLegend , bubbleSeriesIndex = getVisibleBubbleSeriesIndex ( legend . chart ) ; if ( bubbleLegend && bubbleLegend . ranges && bubbleLegend . ranges . length ) { if ( ( options as any ) . ranges . length ) { ( options as any ) . autoRanges = ! ! ( options as any ) . ranges [ 0 ] . autoRanges ; } legend . destroyItem ( bubbleLegend ) ; } if ( bubbleSeriesIndex >= 0 && legendOptions . enabled && ( options as any ) . enabled ) { ( options as any ) . seriesIndex = bubbleSeriesIndex ; legend . bubbleLegend = new BubbleLegendItem ( options as any , legend ) ; legend . bubbleLegend . addToLegend ( e . allItems ) ; } } /**
     * Toggle bubble legend depending on the visible status of bubble series.
     */ function onSeriesLegendItemClick ( this ) { const series = this , chart = series . chart , visible = series . visible , legend = series . chart . legend ; let status ; if ( legend && legend . bubbleLegend ) { series . visible = ! visible ; series . ignoreSeries = visible ; status = getVisibleBubbleSeriesIndex ( chart ) >= 0 ; if ( legend . bubbleLegend . visible !== status ) { legend . update ( { bubbleLegend : { enabled : status } } ) ; legend . bubbleLegend . visible = status ; } series . visible = visible ; } } private function param { Highcharts . Legend } legend param { Array < Highcharts . Dictionary < number > > } lines function retranslateItems ( legend , lines ) { const items = legend . allItems , rtl = legend . options . rtl ; let orgTranslateX , orgTranslateY , movementX , actualLine = 0 ; items . forEach ( function ( item , index ) : void { orgTranslateX = ( item . legendGroup as any ) . translateX ; orgTranslateY = ( item . _legendItemPos as any ) [ 1 ] ; movementX = ( item as any ) . movementX ; if ( movementX || ( rtl && ( item as any ) . ranges ) ) { movementX = rtl ? orgTranslateX - ( item as any ) . options . maxSize / 2 : orgTranslateX + movementX ; ( item . legendGroup as any ) . attr ( { translateX : movementX } ) ; } if ( index > lines [ actualLine ] . step ) { actualLine ++ ; } ( item . legendGroup as any ) . attr ( { translateY : Math . round ( orgTranslateY + lines [ actualLine ] . height / 2 ) } ) ; ( item . _legendItemPos as any ) [ 1 ] = orgTranslateY + lines [ actualLine ] . height / 2 ; } ) ; } } export default BubbleLegendComposition ;