'use strict' ; import type { AlignValue } from '../../Core/Renderer/AlignObject' ; import type { LabelsItemsOptions } from '../../Core/Options' ; import type ColorString from '../../Core/Color/ColorString' ; import type ColorType from '../../Core/Color/ColorType' ; import type CSSObject from '../../Core/Renderer/CSSObject' ; import type EventCallback from '../../Core/EventCallback' ; import type GradientColor from '../../Core/Color/GradientColor' ; import { HTMLDOMElement } from '../../Core/Renderer/DOMElementType' ; import type HTMLElement from '../../Core/Renderer/HTML/HTMLElement' ; import type HTMLRenderer from '../../Core/Renderer/HTML/HTMLRenderer' ; import type PointerEvent from '../../Core/PointerEvent' ; import type ShadowOptionsObject from '../../Core/Renderer/ShadowOptionsObject' ; import type SizeObject from '../../Core/Renderer/SizeObject' ; import type SVGPath from '../../Core/Renderer/SVG/SVGPath' ; import type SymbolOptions from '../../Core/Renderer/SVG/SymbolOptions' ; import Chart from '../../Core/Chart/Chart.js' ; import Color from '../../Core/Color/Color.js' ; const color = Color . parse ; import H from '../../Core/Globals.js' ; const { deg2rad , doc , noop , svg , win } = H ; import D from '../../Core/DefaultOptions.js' ; const { getOptions } = D ; import { Palette } from '../../Core/Color/Palettes.js' ; import Pointer from '../../Core/Pointer.js' ; import RendererRegistry from '../../Core/Renderer/RendererRegistry.js' ; import SVGElement from '../../Core/Renderer/SVG/SVGElement.js' ; import SVGRenderer from '../../Core/Renderer/SVG/SVGRenderer.js' ; import U from '../../Core/Utilities.js' ; const { addEvent , createElement , css , defined , discardElement , erase , extend , extendClass , isArray , isNumber , isObject , pick , pInt , uniqueKey } = U ; import VMLRenderer3D from './VMLRenderer3D.js' ; declare module '../../Core/Chart/ChartLike' { interface ChartLike { requires ieSanitizeSVG ( svg ) : string ; requires isReadyToRender ( ) : boolean ; } } declare module '../../Core/Chart/ChartOptions' { interface ChartOptions { deprecated defaultSeriesType ? : string ; } } declare module '../../Core/EventCallback' { interface EventCallback < T > { requires hcKey ? : string ; } } declare module '../../Core/GlobalsLike' { interface GlobalsLike extends OldInterface { } } declare module '../../Core/Options' { interface Options { deprecated global ? : Oldie . GlobalOptions ; deprecated labels ? : Oldie . LabelsOptions ; } } declare module '../../Core/Renderer/SVG/SVGRendererLike' { interface SVGRendererLike { requires isVML ? : boolean ; requires getSpanWidth ( wrapper , tspan ) : number ; requires invertChild ( element , parentNode ) : void ; requires measureSpanWidth ( text , style ) : number ; } } type OldInterface = typeof Highcharts ; private declare global { deprecated todo namespace Highcharts { interface GlobalOptions { deprecated canvasToolsURL ? : string ; deprecated Date ? : Function ; deprecated getTimezoneOffset ? : Function ; deprecated timezone ? : string ; deprecated timezoneOffset ? : number ; deprecated useUTC ? : boolean ; requires VMLRadialGradientURL ? : string ; } requires interface VMLAttributes extends AnyRecord { d ? : VMLPathArray ; end ? : number ; innerR ? : number ; r ? : number ; src ? : string ; start ? : number ; } requires interface VMLClipRectObject extends VMLElement { count : number ; height : number ; left : number ; members : Array < VMLElement > ; top : number ; width : number ; getCSS ( wrapper ) : CSSObject ; updateClipping ( ) : void ; } requires interface VMLDOMElement extends HTMLDOMElement { deprecated [ attributeKey ] : any ; cutOff ? : number ; path ? : VMLPathString ; stroked ? : boolean ; } requires interface VMLPathArray extends Array < ( number | string ) > { isArc ? : boolean ; } interface VMLPathString extends String { value ? : string ; } requires class VMLElement { public added ? : boolean ; public alignOnAdd ? : unknown ; public className ? : string ; public d ? : string ; public deferUpdateTransform ? : unknown ; public destroyClip ? : Function ; public docMode8 : boolean ; public element : VMLDOMElement ; public elemHeight ? : number ; public getBBox : SVGElement [ 'getBBox' ] ; public heightSetter : VMLElement [ 'xSetter' ] ; public inverted ? : boolean ; public isCircle ? : boolean ; public onAdd ? : Function ; public opacitySetter : Function ; public parentGroup ? : VMLElement ; public r ? : number ; public renderer : VMLRenderer ; public rotation ? : number ; public shadows ? : Array < VMLDOMElement > ; public 'stroke-opacitySetter' : VMLElement [ 'fill-opacitySetter' ] ; public updateShadows : Function ; public updateTransform : HTMLElement [ 'htmlUpdateTransform' ] ; public widthSetter : VMLElement [ 'xSetter' ] ; public xCorr ? : number ; public yCorr ? : number ; public ySetter : VMLElement [ 'xSetter' ] ; public add ( parent ? ) ; public attr ( attr ? ) ; public attr ( key , val ) ; public classGetter ( ) ; public classSetter ( value ) ; public clip ( clipRect ) ; public css ( style ) ; public cutOffPath ( path , length ) ; public dashstyleSetter ( value , key , element ) ; public destroy ( ) ; public dSetter ( value , key , element ) ; public 'fill-opacitySetter' ( value , key , element ) ; public fillGetter ( ) ; public fillSetter ( value , key , element ) ; public getAttr ( key ) ; public getSpanCorrection ( width , baseline , alignCorrection , rotation , align ) ; public init ( renderer , nodeName ) ; public on ( eventType , handler ) ; public pathToVML ( value ) ; public rotationSetter ( value , key , element ) ; public safeRemoveChild ( element ) ; public setAttr ( key , value ) ; public setSpanRotation ( ) ; public shadow ( shadowOptions , group , cutOff ) ; public strokeGetter ( ) ; public strokeSetter ( value , key , element ) ; public 'stroke-widthSetter' ( value , key , element ) ; public titleSetter ( value , key ) ; public updateClipping ( ) ; public visibilitySetter ( value , key , element ) ; public xSetter ( value , key , element ) ; public zIndexSetter ( value , key , element ) ; } requires class VMLRenderer { public Element : typeof VMLElement ; public alignedObjects : SVGRenderer [ 'alignedObjects' ] ; public box : HTMLDOMElement ; public boxWrapper : VMLElement ; public cache : SVGRenderer [ 'cache' ] ; public cacheKeys : SVGRenderer [ 'cacheKeys' ] ; public gradients : SVGRenderer [ 'gradients' ] ; public imgCount : number ; public isIE8 : boolean ; public isVML : true ; public setSize : SVGRenderer [ 'setSize' ] ; public symbols : SVGRenderer [ 'symbols' ] ; public circle ( obj ) ; public circle ( x , y , r ) ; public clipRect ( size ) ; public clipRect ( x , y , width , height ) ; public color < T extends ColorType > ( color , elem , prop , wrapper ) ; public createElement ( nodeName ) ; public crispPolyLine ( points , width ) ; public g ( name ) ; public image ( src , x , y , width , height ) ; public init ( container , width , height ) ; public invertChild ( element , parentNode ) ; public isHidden ( ) ; public path ( path ? ) ; public prepVML ( markup ) ; public symbol ( name ) ; public text ( str , x , y ) ; } requires function addEventListenerPolyfill < T extends EventTarget > ( this , type , fn ) ; requires function removeEventListenerPolyfill < T extends EventTarget > ( this , type , fn ) ; } interface CSSStyleSheet { deprecated cssText : string ; } interface Document { deprecated documentMode ? : number ; deprecated namespaces ? : TridentNamespaceCollection ; deprecated createStyleSheet ( url ? , index ? ) : CSSStyleSheet ; } interface EventTarget { requires hcEventsIE ? : { [ key ] : ( e : Event ) => void ; } ; deprecated attachEvent ( event , pDisp ) : boolean ; deprecated detachEvent ( event , pDisp ) : ( number | true ) ; } interface Document { deprecated exitFullscreen : ( ) => Promise < void > ; deprecated mozCancelFullScreen : Function ; deprecated msExitFullscreen : Function ; deprecated msHidden : boolean ; deprecated webkitExitFullscreen : Function ; deprecated webkitHidden : boolean ; } interface Element { deprecated currentStyle ? : ElementCSSInlineStyle ; deprecated mozRequestFullScreen : Function ; deprecated msMatchesSelector : Element [ 'matches' ] ; deprecated msRequestFullscreen : Function ; deprecated webkitMatchesSelector : Element [ 'matches' ] ; deprecated webkitRequestFullScreen : Function ; } interface MSPointerEvent { deprecated readonly MSPOINTER_TYPE_TOUCH : string ; } interface PointerEvent { deprecated readonly MSPOINTER_TYPE_TOUCH : string ; deprecated readonly toElement : Element ; } interface HTMLCanvasElement { deprecated msToBlob : Function ; } deprecated interface TridentNamespace { readonly name : string ; onreadystatechange ? : Function ; readonly readyState : ( 'complete' | 'interactive' | 'loaded' | 'loading' | 'uninitialized' ) ; readonly urn : string ; attachEvent ( evtName , fn ) : boolean ; detachEvent ( evtName , fn ) : void ; doImport ( url ) : void ; } deprecated interface TridentNamespaceCollection { [ key ] : ( Function | TridentNamespace ) ; add ( name , urn , url ? ) : TridentNamespace ; item ( name ) : TridentNamespace ; } interface Window { deprecated createObjectURL ? : ( typeof URL ) [ 'createObjectURL' ] ; deprecated opera ? : unknown ; deprecated webkitAudioContext ? : typeof AudioContext ; deprecated webkitURL ? : typeof URL ; } } let VMLRenderer , VMLElement ; type { string } default since requires apioption ( getOptions ( ) . global as any ) . VMLRadialGradientURL = 'http://code.highcharts.com/@product.version@/gfx/vml-radial-gradient.png' ; if ( doc && ! doc . defaultView ) { ( H as any ) . getStyle = U . getStyle = function getStyle ( el , prop ) : number { let val , alias = ( { width : 'clientWidth' , height : 'clientHeight' } as Record < string , string > ) [ prop ] ; if ( el . style [ prop as any ] ) { return pInt ( el . style [ prop as any ] ) ; } if ( prop === 'opacity' ) { prop = 'filter' ; } if ( alias ) { el . style . zoom = 1 as any ; return Math . max ( ( el as any ) [ alias ] - 2 * getStyle ( el , 'padding' ) , 0 ) ; } val = ( el . currentStyle as any ) [ prop . replace ( /\-(\w)/g , function ( a , b ) : string { return b . toUpperCase ( ) ; } ) ] ; if ( prop === 'filter' ) { val = val . replace ( /alpha\(opacity=([0-9]+)\)/ , function ( a , b ) : string { return ( ( b as any ) / 100 ) as any ; } ) ; } return val === '' ? 1 : pInt ( val ) ; } ; } if ( ! svg ) { addEvent ( SVGElement , 'afterInit' , function ( this ) : void { if ( this . element . nodeName === 'text' ) { this . css ( { position : 'absolute' } ) ; } } ) ; ignore function Pointer . prototype . normalize = function < T extends PointerEvent > ( e , chartPosition ? ) : T { e = e || win . event ; if ( ! e . target ) { ( e as any ) . target = e . srcElement ; } if ( ! chartPosition ) { this . chartPosition = chartPosition = this . getChartPosition ( ) ; } return extend ( e , { chartX : Math . round ( Math . max ( ( e as any ) . x , ( e as any ) . clientX - chartPosition . left ) ) , chartY : Math . round ( ( e as any ) . y ) } ) as T ; } ; private function Chart . prototype . ieSanitizeSVG = function ( svg ) : string { svg = svg . replace ( /<IMG /g , '<image ' ) . replace ( /<(\/?)TITLE>/g , '<$1title>' ) . replace ( /height=([^" ]+)/g , 'height="$1"' ) . replace ( /width=([^" ]+)/g , 'width="$1"' ) . replace ( /hc-svg-href="([^"]+)">/g , 'xlink:href="$1"/>' ) . replace ( / id=([^" >]+)/g , ' id="$1"' ) . replace ( /class=([^" >]+)/g , 'class="$1"' ) . replace ( / transform /g , ' ' ) . replace ( /:(path|rect)/g , '$1' ) . replace ( /style="([^"]+)"/g , function ( s ) : string { return s . toLowerCase ( ) ; } ) ; return svg ; } ; private function Chart . prototype . isReadyToRender = function ( ) : boolean { const chart = this ; if ( ! svg && ( win == win . top && doc . readyState !== 'complete' ) ) { doc . attachEvent ( 'onreadystatechange' , function ( ) : void { doc . detachEvent ( 'onreadystatechange' , chart . firstRender ) ; if ( doc . readyState === 'complete' ) { chart . firstRender ( ) ; } } ) ; return false ; } return true ; } ; if ( ! doc . createElementNS ) { doc . createElementNS = function ( ns , tagName ) : HTMLDOMElement { return doc . createElement ( tagName ) ; } as any ; } private function H . addEventListenerPolyfill = function < T extends EventTarget > ( this , type , fn ) : void { const el = this ; private function wrappedFn ( e ) { ( e as any ) . target = e . srcElement || win ; fn . call ( el , e ) ; } if ( el . attachEvent ) { if ( ! el . hcEventsIE ) { el . hcEventsIE = { } ; } if ( ! fn . hcKey ) { fn . hcKey = uniqueKey ( ) ; } el . hcEventsIE [ fn . hcKey ] = wrappedFn ; el . attachEvent ( 'on' + type , wrappedFn ) ; } } ; private function H . removeEventListenerPolyfill = function < T extends EventTarget > ( this , type , fn ) : void { if ( this . detachEvent ) { fn = ( this . hcEventsIE as any ) [ fn . hcKey as any ] ; this . detachEvent ( 'on' + type , fn ) ; } } ; private class name augments Highcharts . SVGElement VMLElement = { docMode8 : doc && doc . documentMode === 8 , function init : function ( this , renderer , nodeName ) : void { let wrapper = this , markup = [ '<' , nodeName , ' filled="f" stroked="f"' ] , style = [ 'position: ' , 'absolute' , ';' ] , isDiv = nodeName === 'div' ; if ( nodeName === 'shape' || isDiv ) { style . push ( 'left:0;top:0;width:1px;height:1px;' ) ; } style . push ( 'visibility: ' , isDiv ? 'hidden' : 'visible' ) ; markup . push ( ' style="' , style . join ( '' ) , '"/>' ) ; if ( nodeName ) { markup = isDiv || nodeName === 'span' || nodeName === 'img' ? ( markup . join ( '' ) as any ) : renderer . prepVML ( markup ) ; wrapper . element = createElement ( markup as any ) ; } wrapper . renderer = renderer ; } , function add : function ( this , parent ) : Highcharts . VMLElement { const wrapper = this , renderer = wrapper . renderer , element = wrapper . element , box = renderer . box , inverted = parent && parent . inverted , parentNode = parent ? parent . element || parent : box ; if ( parent ) { this . parentGroup = parent ; } if ( inverted ) { renderer . invertChild ( element , parentNode ) ; } parentNode . appendChild ( element ) ; wrapper . added = true ; if ( wrapper . alignOnAdd && ! wrapper . deferUpdateTransform ) { wrapper . updateTransform ( ) ; } if ( wrapper . onAdd ) { wrapper . onAdd ( ) ; } if ( this . className ) { this . attr ( 'class' , this . className ) ; } return wrapper ; } , function updateTransform : SVGElement . prototype . htmlUpdateTransform as HTMLElement [ 'htmlUpdateTransform' ] , function setSpanRotation : function ( this ) : void { const rotation = this . rotation , costheta = Math . cos ( ( rotation as any ) * deg2rad ) , sintheta = Math . sin ( ( rotation as any ) * deg2rad ) ; css ( this . element , { filter : rotation ? [ 'progid:DXImageTransform.Microsoft.Matrix(M11=' , costheta , ', M12=' , - sintheta , ', M21=' , sintheta , ', M22=' , costheta , ', sizingMethod=\'auto expand\')' ] . join ( '' ) : 'none' } ) ; } , function getSpanCorrection : function ( this , width , baseline , alignCorrection , rotation , align ) : void { let costheta = rotation ? Math . cos ( rotation * deg2rad ) : 1 , sintheta = rotation ? Math . sin ( rotation * deg2rad ) : 0 , height = pick ( this . elemHeight , this . element . offsetHeight ) , quad , nonLeft = align && align !== 'left' ; this . xCorr = ( costheta < 0 && - width ) as any ; this . yCorr = ( sintheta < 0 && - height ) as any ; quad = costheta * sintheta < 0 ; ( this . xCorr as any ) += ( sintheta * baseline * ( quad ? 1 - alignCorrection : alignCorrection ) ) ; ( this . yCorr as any ) -= ( costheta * baseline * ( rotation ? ( quad ? alignCorrection : 1 - alignCorrection ) : 1 ) ) ; if ( nonLeft ) { ( this . xCorr as any ) -= width * alignCorrection * ( costheta < 0 ? - 1 : 1 ) ; if ( rotation ) { ( this . yCorr as any ) -= ( height * alignCorrection * ( sintheta < 0 ? - 1 : 1 ) ) ; } css ( this . element , { textAlign : align } ) ; } } , function pathToVML : function ( this , value ) : string { let i = value . length , path = [ ] ; while ( i -- ) { if ( isNumber ( value [ i ] ) ) { path [ i ] = Math . round ( ( value [ i ] as any ) * 10 ) - 5 ; } else if ( value [ i ] === 'Z' ) { path [ i ] = 'x' ; } else { path [ i ] = value [ i ] ; if ( value . isArc && ( value [ i ] === 'wa' || value [ i ] === 'at' ) ) { if ( path [ i + 5 ] === path [ i + 7 ] ) { ( path as any ) [ i + 7 ] += value [ i + 7 ] > value [ i + 5 ] ? 1 : - 1 ; } if ( path [ i + 6 ] === path [ i + 8 ] ) { ( path as any ) [ i + 8 ] += value [ i + 8 ] > value [ i + 6 ] ? 1 : - 1 ; } } } } return path . join ( ' ' ) || 'x' ; } , function clip : function ( this , clipRect ) : Highcharts . VMLElement { let wrapper = this , clipMembers , cssRet ; if ( clipRect ) { clipMembers = clipRect . members ; erase ( clipMembers , wrapper ) ; clipMembers . push ( wrapper ) ; wrapper . destroyClip = function ( ) : void { erase ( clipMembers , wrapper ) ; } ; cssRet = clipRect . getCSS ( wrapper ) ; } else { if ( wrapper . destroyClip ) { wrapper . destroyClip ( ) ; } cssRet = { clip : wrapper . docMode8 ? 'inherit' : 'rect(auto)' } ; } return wrapper . css ( cssRet ) ; } , function css : SVGElement . prototype . htmlCss as any , function safeRemoveChild : function ( this , element ) : void { if ( element . parentNode ) { discardElement ( element ) ; } } , function destroy : function ( this ) : void { if ( this . destroyClip ) { this . destroyClip ( ) ; } return SVGElement . prototype . destroy . apply ( this ) ; } , function on : function ( this , eventType , handler ) : Highcharts . VMLElement { this . element [ 'on' + eventType ] = function ( ) : void { const e = win . event as Event ; ( e . target as any ) = e . srcElement ; handler ( e ) ; } ; return this ; } , function cutOffPath : function ( this , path , length ) : string { let len ; path = path . split ( /[ ,,]/ ) as any ; len = path . length ; if ( len === 9 || len === 11 ) { ( path [ len - 4 ] as any ) = ( path [ len - 2 ] as any ) = pInt ( path [ len - 2 ] ) - 10 * length ; } return ( path as any ) . join ( ' ' ) ; } , function shadow : function ( this , shadowOptions , group , cutOff ) : Highcharts . VMLElement { let shadows = [ ] , i , element = this . element , renderer = this . renderer , shadow , elemStyle = element . style , markup , path = element . path , strokeWidth , modifiedPath , shadowWidth , shadowElementOpacity ; if ( path && typeof path . value !== 'string' ) { path = 'x' ; } modifiedPath = path ; if ( shadowOptions ) { shadowWidth = pick ( shadowOptions . width , 3 ) ; shadowElementOpacity = ( shadowOptions . opacity || 0.15 ) / shadowWidth ; for ( i = 1 ; i <= 3 ; i ++ ) { strokeWidth = ( shadowWidth * 2 ) + 1 - ( 2 * i ) ; if ( cutOff ) { modifiedPath = this . cutOffPath ( ( path as any ) . value , strokeWidth + 0.5 ) ; } markup = [ '<shape isShadow="true" strokeweight="' , strokeWidth , '" filled="false" path="' , modifiedPath , '" coordsize="10 10" style="' , element . style . cssText , '" />' ] ; shadow = createElement ( renderer . prepVML ( markup as any ) , null as any , { left : ( pInt ( elemStyle . left ) + pick ( shadowOptions . offsetX , 1 ) ) + 'px' , top : ( pInt ( elemStyle . top ) + pick ( shadowOptions . offsetY , 1 ) ) + 'px' } ) ; if ( cutOff ) { shadow . cutOff = strokeWidth + 1 ; } markup = [ '<stroke color="' , shadowOptions . color || Palette . neutralColor100 , '" opacity="' , shadowElementOpacity * i , '"/>' ] ; createElement ( renderer . prepVML ( markup ) , null as any , null as any , shadow ) ; if ( group ) { group . element . appendChild ( shadow ) ; } else { ( element . parentNode as any ) . insertBefore ( shadow , element ) ; } shadows . push ( shadow ) ; } this . shadows = shadows ; } return this ; } , updateShadows : noop , setAttr : function ( this , key , value ) : void { if ( this . docMode8 ) { this . element [ key ] = value ; } else { this . element . setAttribute ( key , value ) ; } } , getAttr : function ( this , key ) : ( null | string ) { if ( this . docMode8 ) { return this . element [ key ] ; } return this . element . getAttribute ( key ) ; } , classSetter : function ( this , value ) : void { ( this . added ? this . element : this ) . className = value ; } , dashstyleSetter : function ( this , value , key , element ) : void { const strokeElem = element . getElementsByTagName ( 'stroke' ) [ 0 ] as ( Highcharts . VMLDOMElement ) || createElement ( this . renderer . prepVML ( [ '<stroke/>' ] ) , null as any , null as any , element ) ; strokeElem [ key ] = value || 'solid' ; ( this as any ) [ key ] = value ; } , dSetter : function ( this , value , key , element ) : void { let i , shadows = this . shadows ; value = value || [ ] ; this . d = value . join && value . join ( ' ' ) ; element . path = ( value as any ) = this . pathToVML ( value ) ; if ( shadows ) { i = shadows . length ; while ( i -- ) { shadows [ i ] . path = shadows [ i ] . cutOff ? this . cutOffPath ( value as any , shadows [ i ] . cutOff as any ) : ( value as any ) ; } } this . setAttr ( key , value as any ) ; } , fillSetter : function ( this , value , key , element ) : void { const nodeName = element . nodeName ; if ( nodeName === 'SPAN' ) { element . style . color = value ; } else if ( nodeName !== 'IMG' ) { element . filled = value !== 'none' ; this . setAttr ( 'fillcolor' , this . renderer . color ( value , element , key , this ) ) ; } } , 'fill-opacitySetter' : function ( this , value , key , element ) : void { createElement ( this . renderer . prepVML ( [ '<' , key . split ( '-' ) [ 0 ] , ' opacity="' , value , '"/>' ] ) , null as any , null as any , element ) ; } , opacitySetter : noop , rotationSetter : function ( this , value , key , element ) : void { const style = element . style ; ( this as any ) [ key ] = style [ key as any ] = value ; style . left = - Math . round ( Math . sin ( ( value as any ) * deg2rad ) + 1 ) + 'px' ; style . top = Math . round ( Math . cos ( ( value as any ) * deg2rad ) ) + 'px' ; } , strokeSetter : function ( this , value , key , element ) : void { this . setAttr ( 'strokecolor' , this . renderer . color ( value , element , key , this ) ) ; } , 'stroke-widthSetter' : function ( this , value , key , element ) : void { element . stroked = ! ! value ; ( this as any ) [ key ] = value ; if ( isNumber ( value ) ) { value += 'px' as any ; } this . setAttr ( 'strokeweight' , value as any ) ; } , titleSetter : function ( this , value , key ) : void { this . setAttr ( key , value ) ; } , visibilitySetter : function ( this , value , key , element ) : void { if ( value === 'inherit' ) { value = 'visible' ; } if ( this . shadows ) { this . shadows . forEach ( function ( shadow ) : void { shadow . style [ key as any ] = value ; } ) ; } if ( element . nodeName === 'DIV' ) { value = value === 'hidden' ? '-999em' : ( 0 as any ) ; if ( ! this . docMode8 ) { element . style [ key as any ] = value ? 'visible' : 'hidden' ; } key = 'top' ; } element . style [ key as any ] = value ; } , xSetter : function ( this , value , key , element ) : void { ( this as any ) [ key ] = value ; if ( key === 'x' ) { key = 'left' ; } else if ( key === 'y' ) { key = 'top' ; } if ( this . updateClipping ) { ( this as any ) [ key ] = value ; this . updateClipping ( ) ; } else { element . style [ key as any ] = value ; } } , zIndexSetter : function ( this , value , key , element ) : void { element . style [ key as any ] = value ; } , fillGetter : function ( this ) : string { return this . getAttr ( 'fillcolor' ) || '' ; } , strokeGetter : function ( this ) : string { return this . getAttr ( 'strokecolor' ) || '' ; } , classGetter : function ( this ) : string { return this . getAttr ( 'className' ) || '' ; } } as any ; ( VMLElement as any ) [ 'stroke-opacitySetter' ] = ( VMLElement as any ) [ 'fill-opacitySetter' ] ; H . VMLElement = VMLElement = extendClass ( SVGElement , VMLElement ) ; VMLElement . prototype . ySetter = VMLElement . prototype . widthSetter = VMLElement . prototype . heightSetter = VMLElement . prototype . xSetter ; private class name augments Highcharts . SVGRenderer const VMLRendererExtension = { Element : VMLElement , isIE8 : win . navigator . userAgent . indexOf ( 'MSIE 8.0' ) > - 1 , function param { Highcharts . HTMLDOMElement } container param { number } width param { number } height init : function ( this , container , width , height ) : void { let renderer = this , boxWrapper , box , css ; this . crispPolyLine = SVGRenderer . prototype . crispPolyLine ; renderer . alignedObjects = [ ] ; boxWrapper = renderer . createElement ( 'div' ) . css ( { position : 'relative' } ) ; box = boxWrapper . element ; container . appendChild ( boxWrapper . element ) ; renderer . isVML = true ; renderer . box = box ; renderer . boxWrapper = boxWrapper ; renderer . gradients = { } ; renderer . cache = { } ; renderer . cacheKeys = [ ] ; renderer . imgCount = 0 ; renderer . setSize ( width , height , false ) ; if ( ! ( doc . namespaces as any ) . hcv ) { ( doc . namespaces as any ) . add ( 'hcv' , 'urn:schemas-microsoft-com:vml' ) ; css = 'hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke' + '{ behavior:url(#default#VML); display: inline-block; } ' ; try { doc . createStyleSheet ( ) . cssText = css ; } catch ( e ) { ( doc . styleSheets [ 0 ] as any ) . cssText += css ; } } } , function isHidden : function ( this ) : boolean { return ! this . box . offsetWidth ; } , function clipRect : function ( this , x , y , width , height ) : Highcharts . VMLClipRectObject { const clipRect = ( this . createElement as any ) ( ) , isObj = isObject ( x ) ; return extend ( clipRect , { members : [ ] , count : 0 , left : ( isObj ? ( x as any ) . x : x ) + 1 , top : ( isObj ? ( x as any ) . y : y ) + 1 , width : ( isObj ? ( x as any ) . width : width ) - 1 , height : ( isObj ? ( x as any ) . height : height ) - 1 , getCSS : function ( this , wrapper ) : CSSObject { const element = wrapper . element , nodeName = element . nodeName , isShape = nodeName === 'shape' , inverted = wrapper . inverted , rect = this , top = rect . top - ( isShape ? element . offsetTop : 0 ) , left = rect . left , right = left + rect . width , bottom = top + rect . height , ret = { clip : 'rect(' + Math . round ( inverted ? left : top ) + 'px,' + Math . round ( inverted ? bottom : right ) + 'px,' + Math . round ( inverted ? right : bottom ) + 'px,' + Math . round ( inverted ? top : left ) + 'px)' } ; if ( ! inverted && wrapper . docMode8 && nodeName === 'DIV' ) { extend ( ret , { width : right + 'px' , height : bottom + 'px' } ) ; } return ret ; } , updateClipping : function ( this ) : void { clipRect . members . forEach ( function ( member ) : void { if ( member . element ) { member . css ( clipRect . getCSS ( member ) ) ; } } ) ; } } ) ; } , function param { T } color return { T } color : function < T extends ColorType > ( this , colorOption , elem , prop , wrapper ) : T { let renderer = this , colorObject , regexRgba = /^rgba/ , markup , fillType , ret = 'none' as T ; if ( colorOption && ( colorOption as GradientColor ) . linearGradient ) { fillType = 'gradient' ; } else if ( colorOption && ( colorOption as GradientColor ) . radialGradient ) { fillType = 'pattern' ; } if ( fillType ) { let stopColor , stopOpacity , gradient = ( ( colorOption as GradientColor ) . linearGradient || ( colorOption as GradientColor ) . radialGradient ) as any , x1 , y1 , x2 , y2 , opacity1 , opacity2 , color1 , color2 , fillAttr = '' , stops = ( colorOption as GradientColor ) . stops , firstStop , lastStop , colors = [ ] , addFillNode = function ( ) : void { markup = [ '<fill colors="' + colors . join ( ',' ) + '" opacity="' , opacity2 , '" o:opacity2="' , opacity1 , '" type="' , fillType as any , '" ' , fillAttr , 'focus="100%" method="any" />' ] ; createElement ( renderer . prepVML ( markup ) , null as any , null as any , elem ) ; } ; firstStop = stops [ 0 ] ; lastStop = stops [ stops . length - 1 ] ; if ( firstStop [ 0 ] > 0 ) { stops . unshift ( [ 0 , firstStop [ 1 ] ] ) ; } if ( lastStop [ 0 ] < 1 ) { stops . push ( [ 1 , lastStop [ 1 ] ] ) ; } stops . forEach ( function ( stop , i ) : void { if ( regexRgba . test ( stop [ 1 ] ) ) { colorObject = color ( stop [ 1 ] ) ; stopColor = colorObject . get ( 'rgb' ) as any ; stopOpacity = colorObject . get ( 'a' ) as any ; } else { stopColor = stop [ 1 ] ; stopOpacity = 1 ; } colors . push ( ( stop [ 0 ] * 100 ) + '% ' + stopColor ) ; if ( ! i ) { opacity1 = stopOpacity as any ; color2 = stopColor ; } else { opacity2 = stopOpacity as any ; color1 = stopColor ; } } ) ; if ( prop === 'fill' ) { if ( fillType === 'gradient' ) { x1 = ( gradient as any ) . x1 || ( gradient as any ) [ 0 ] || 0 ; y1 = ( gradient as any ) . y1 || ( gradient as any ) [ 1 ] || 0 ; x2 = ( gradient as any ) . x2 || ( gradient as any ) [ 2 ] || 0 ; y2 = ( gradient as any ) . y2 || ( gradient as any ) [ 3 ] || 0 ; fillAttr = 'angle="' + ( 90 - Math . atan ( ( y2 - y1 ) / ( x2 - x1 ) ) * 180 / Math . PI ) + '"' ; addFillNode ( ) ; } else { let r = ( gradient as any ) . r , sizex = r * 2 , sizey = r * 2 , cx = ( gradient as any ) . cx , cy = ( gradient as any ) . cy , radialReference = elem . radialReference , bBox , applyRadialGradient = function ( ) : void { if ( radialReference ) { bBox = wrapper . getBBox ( ) ; cx += ( radialReference [ 0 ] - bBox . x ) / bBox . width - 0.5 ; cy += ( radialReference [ 1 ] - bBox . y ) / bBox . height - 0.5 ; sizex *= radialReference [ 2 ] / bBox . width ; sizey *= radialReference [ 2 ] / bBox . height ; } fillAttr = 'src="' + ( getOptions ( ) . global as any ) . VMLRadialGradientURL + '" ' + 'size="' + sizex + ',' + sizey + '" ' + 'origin="0.5,0.5" ' + 'position="' + cx + ',' + cy + '" ' + 'color2="' + color2 + '" ' ; addFillNode ( ) ; } ; if ( wrapper . added ) { applyRadialGradient ( ) ; } else { wrapper . onAdd = applyRadialGradient ; } ret = color1 as any ; } } else { ret = stopColor as any ; } } else if ( regexRgba . test ( colorOption as any ) && elem . tagName !== 'IMG' ) { colorObject = color ( colorOption ) ; ( wrapper as any ) [ prop + '-opacitySetter' ] ( colorObject . get ( 'a' ) , prop , elem ) ; ret = colorObject . get ( 'rgb' ) as any ; } else { const propNodes = elem . getElementsByTagName ( prop ) as any ; if ( propNodes . length ) { propNodes [ 0 ] . opacity = 1 ; propNodes [ 0 ] . type = 'solid' ; } ret = colorOption ; } return ret ; } , function param { Array < ( number | string ) > } markup prepVML : function ( this , markup ) : string { const vmlStyle = 'display:inline-block;behavior:url(#default#VML);' , isIE8 = this . isIE8 ; markup = markup . join ( '' ) as any ; if ( isIE8 ) { markup = ( markup as any ) . replace ( '/>' , ' xmlns="urn:schemas-microsoft-com:vml" />' ) ; if ( markup . indexOf ( 'style="' ) === - 1 ) { markup = ( markup as any ) . replace ( '/>' , ' style="' + vmlStyle + '" />' ) ; } else { markup = ( markup as any ) . replace ( 'style="' , 'style="' + vmlStyle ) ; } } else { markup = ( markup as any ) . replace ( '<' , '<hcv:' ) ; } return markup as any ; } , function text : ( SVGRenderer . prototype as HTMLRenderer ) . html , function param { Highcharts . VMLAttributes | Highcharts . VMLPathArray } path path : function ( this , path ? ) : Highcharts . VMLElement { const attr = { coordsize : '10 10' } as Highcharts . VMLAttributes ; if ( isArray ( path ) ) { attr . d = path as any ; } else if ( isObject ( path ) ) { extend ( attr , path as any ) ; } return this . createElement ( 'shape' ) . attr ( attr ) ; } , function circle : function ( this , x , y ? , r ? ) : Highcharts . VMLElement { const circle = this . symbol ( 'circle' ) ; if ( isObject ( x ) ) { r = ( x as any ) . r ; y = ( x as any ) . y ; x = ( x as any ) . x ; } circle . isCircle = true ; circle . r = r ; return circle . attr ( { x : x , y : y } ) ; } , function param { string } name g : function ( this , name ) : Highcharts . VMLElement { let wrapper , attribs ; if ( name ) { attribs = { 'className' : 'highcharts-' + name , 'class' : 'highcharts-' + name } ; } wrapper = this . createElement ( 'div' ) . attr ( attribs ) ; return wrapper ; } , function image : function ( this , src , x , y , width , height ) : Highcharts . VMLElement { const obj = this . createElement ( 'img' ) . attr ( { src : src } ) ; if ( arguments . length > 1 ) { obj . attr ( { x : x , y : y , width : width , height : height } ) ; } return obj ; } , function createElement : function ( this , nodeName ) : Highcharts . VMLElement { return nodeName === 'rect' ? this . symbol ( nodeName ) : SVGRenderer . prototype . createElement . call ( this , nodeName ) as any ; } , function invertChild : function ( this , element , parentNode ) : void { const ren = this , parentStyle = parentNode . style , imgStyle = element . tagName === 'IMG' && element . style ; css ( element , { flip : 'x' , left : ( pInt ( parentStyle . width ) - ( imgStyle ? pInt ( imgStyle . top ) : 1 ) ) + 'px' , top : ( pInt ( parentStyle . height ) - ( imgStyle ? pInt ( imgStyle . left ) : 1 ) ) + 'px' , rotation : - 90 } ) ; [ ] . forEach . call ( element . childNodes , function ( child ) : void { ren . invertChild ( child , element ) ; } ) ; } , name type { Highcharts . Dictionary < Function > } symbols : { arc : function ( x , y , w , h , options ) : Highcharts . VMLPathArray { let start = options . start as any , end = options . end as any , radius = options . r || w || h , innerRadius = options . innerR as any , cosStart = Math . cos ( start ) , sinStart = Math . sin ( start ) , cosEnd = Math . cos ( end ) , sinEnd = Math . sin ( end ) , ret ; if ( end - start === 0 ) { return [ 'x' ] ; } ret = [ 'wa' , x - radius , y - radius , x + radius , y + radius , x + radius * cosStart , y + radius * sinStart , x + radius * cosEnd , y + radius * sinEnd ] ; if ( options . open && ! innerRadius ) { ret . push ( 'e' , 'M' , x , y ) ; } ret . push ( 'at' , x - innerRadius , y - innerRadius , x + innerRadius , y + innerRadius , x + innerRadius * cosEnd , y + innerRadius * sinEnd , x + innerRadius * cosStart , y + innerRadius * sinStart , 'x' , 'e' ) ; ret . isArc = true ; return ret ; } , circle : function ( x , y , w , h , wrapper ) : Highcharts . VMLPathArray { if ( wrapper && defined ( wrapper . r ) ) { w = h = 2 * ( wrapper . r as any ) ; } if ( wrapper && wrapper . isCircle ) { x -= w / 2 ; y -= h / 2 ; } return [ 'wa' , x , y , x + w , y + h , x + w , y + h / 2 , x + w , y + h / 2 , 'e' ] ; } , /**
             * Add rectangle symbol path which eases rotation and omits arcsize
             * problems compared to the built-in VML roundrect shape. When
             * borders are not rounded, use the simpler square path, else use
             * the callout path without the arrow.
             */ rect : function ( x , y , w , h , options ) : SVGPath { return SVGRenderer . prototype . symbols [ ! defined ( options ) || ! options . r ? 'square' : 'callout' ] . call ( 0 , x , y , w , h , options ) ; } } } ; H . VMLRenderer = VMLRenderer = function ( this ) : void { this . init . apply ( this , arguments as any ) ; } as any ; extend ( VMLRenderer . prototype , SVGRenderer . prototype as any ) ; extend ( VMLRenderer . prototype , VMLRendererExtension as any ) ; RendererRegistry . registerRendererType ( 'VMLRenderer' , VMLRenderer , true ) ; VMLRenderer3D . compose ( VMLRenderer , SVGRenderer ) ; } SVGRenderer . prototype . getSpanWidth = function ( this , wrapper , tspan ) : number { let renderer = this , bBox = wrapper . getBBox ( true ) , actualWidth = bBox . width ; if ( ! svg && renderer . forExport ) { actualWidth = renderer . measureSpanWidth ( ( tspan . firstChild as any ) . data , wrapper . styles as any ) ; } return actualWidth ; } ; SVGRenderer . prototype . measureSpanWidth = function ( this , text , styles ) : number { let measuringSpan = doc . createElement ( 'span' ) , offsetWidth , textNode = doc . createTextNode ( text ) ; measuringSpan . appendChild ( textNode ) ; css ( measuringSpan , styles ) ; this . box . appendChild ( measuringSpan ) ; offsetWidth = measuringSpan . offsetWidth ; discardElement ( measuringSpan ) ; return offsetWidth ; } ; namespace Oldie { export interface GlobalOptions { deprecated canvasToolsURL ? : string ; deprecated Date ? : Function ; deprecated getTimezoneOffset ? : Function ; deprecated timezone ? : string ; deprecated timezoneOffset ? : number ; deprecated useUTC ? : boolean ; } export interface LabelsOptions { items ? : Array < LabelsItemsOptions > ; style ? : CSSObject ; } } declare module '../../Core/Renderer/RendererType' { interface RendererTypeRegistry { VMLRenderer : typeof VMLRenderer ; } } export default Oldie ;