'use strict' ; import type HTMLElement from './HTMLElement' ; import type { HTMLDOMElement } from '../DOMElementType' ; import AST from './AST.js' ; import SVGElement from '../SVG/SVGElement.js' ; import SVGRenderer from '../SVG/SVGRenderer.js' ; import U from '../../Utilities.js' ; const { attr , createElement , extend , pick } = U ; declare module '../SVG/SVGRendererLike' { interface SVGRendererLike { requires html ( str , x , y ) : HTMLElement ; } } class HTMLRenderer extends SVGRenderer { private static readonly composedClasses : Array < Function > = [ ] ; private public static compose < T extends typeof SVGRenderer > ( SVGRendererClass ) { if ( HTMLRenderer . composedClasses . indexOf ( SVGRendererClass ) === - 1 ) { HTMLRenderer . composedClasses . push ( SVGRendererClass ) ; const htmlRendererProto = HTMLRenderer . prototype , svgRendererProto = SVGRendererClass . prototype ; svgRendererProto . html = htmlRendererProto . html ; } return SVGRendererClass as ( T & typeof HTMLRenderer ) ; } private function param { string } str param { number } x param { number } y return { Highcharts . HTMLDOMElement } public html ( str , x , y ) { const wrapper = this . createElement ( 'span' ) as HTMLElement , element = wrapper . element , renderer = wrapper . renderer , isSVG = renderer . isSVG , addSetters = function ( gWrapper , style ? ) : void { [ 'opacity' , 'visibility' ] . forEach ( function ( prop ) : void { gWrapper [ prop + 'Setter' ] = function ( value , key , elem ) : void { const styleObject = gWrapper . div ? gWrapper . div . style : style ; SVGElement . prototype [ prop + 'Setter' ] . call ( this , value , key , elem ) ; if ( styleObject ) { styleObject [ key as any ] = value ; } } ; } ) ; gWrapper . addedSetters = true ; } ; wrapper . textSetter = function ( value ) : void { if ( value !== this . textStr ) { delete this . bBox ; delete this . oldTextWidth ; AST . setElementHTML ( this . element , pick ( value , '' ) ) ; this . textStr = value ; wrapper . doTransform = true ; } } ; if ( isSVG ) { addSetters ( wrapper , wrapper . element . style ) ; } wrapper . xSetter = wrapper . ySetter = wrapper . alignSetter = wrapper . rotationSetter = function ( value , key ? ) : void { if ( key === 'align' ) { wrapper . alignValue = wrapper . textAlign = value as any ; } else { wrapper [ key as any ] = value ; } wrapper . doTransform = true ; } ; wrapper . afterSetters = function ( ) : void { if ( this . doTransform ) { this . htmlUpdateTransform ( ) ; this . doTransform = false ; } } ; wrapper . attr ( { text : str , x : Math . round ( x ) , y : Math . round ( y ) } ) . css ( { position : 'absolute' } ) ; if ( ! renderer . styledMode ) { wrapper . css ( { fontFamily : this . style . fontFamily , fontSize : this . style . fontSize } ) ; } element . style . whiteSpace = 'nowrap' ; wrapper . css = wrapper . htmlCss ; if ( isSVG ) { wrapper . add = function ( svgGroupWrapper ? ) : HTMLElement { const container = renderer . box . parentNode , parents = [ ] as Array < HTMLElement > ; let htmlGroup , parentGroup ; this . parentGroup = svgGroupWrapper as any ; if ( svgGroupWrapper ) { htmlGroup = svgGroupWrapper . div ; if ( ! htmlGroup ) { parentGroup = svgGroupWrapper ; while ( parentGroup ) { parents . push ( parentGroup ) ; parentGroup = parentGroup . parentGroup ; } parents . reverse ( ) . forEach ( function ( parentGroup ) : void { const cls = attr ( parentGroup . element , 'class' ) ; private param { * } value param { string } key function translateSetter ( value , key ) { parentGroup [ key ] = value ; if ( key === 'translateX' ) { htmlGroupStyle . left = value + 'px' ; } else { htmlGroupStyle . top = value + 'px' ; } parentGroup . doTransform = true ; } const parentGroupStyles = parentGroup . styles || { } ; htmlGroup = parentGroup . div = parentGroup . div || createElement ( 'div' , cls ? { className : cls } : void 0 , { position : 'absolute' , left : ( parentGroup . translateX || 0 ) + 'px' , top : ( parentGroup . translateY || 0 ) + 'px' , display : parentGroup . display , opacity : parentGroup . opacity , cursor : parentGroupStyles . cursor , pointerEvents : ( parentGroupStyles . pointerEvents ) , visibility : parentGroup . visibility } , ( htmlGroup as any ) || container ) ; const htmlGroupStyle = ( htmlGroup as any ) . style ; extend ( parentGroup , { classSetter : ( function ( htmlGroup ) : Function { return function ( this , value ) : void { this . element . setAttribute ( 'class' , value ) ; htmlGroup . className = value ; } ; } ( htmlGroup as any ) ) , on : function ( ) : HTMLElement { if ( parents [ 0 ] . div ) { wrapper . on . apply ( { element : parents [ 0 ] . div , onEvents : parentGroup . onEvents } , arguments ) ; } return parentGroup ; } , translateXSetter : translateSetter , translateYSetter : translateSetter } ) ; if ( ! parentGroup . addedSetters ) { addSetters ( parentGroup ) ; } } ) ; } } else { htmlGroup = container as any ; } ( htmlGroup as any ) . appendChild ( element ) ; wrapper . added = true ; if ( wrapper . alignOnAdd ) { wrapper . htmlUpdateTransform ( ) ; } return wrapper ; } ; } return wrapper ; } } export default HTMLRenderer ;