Utilities.js 56 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958
  1. /* *
  2. *
  3. * (c) 2010-2021 Torstein Honsi
  4. *
  5. * License: www.highcharts.com/license
  6. *
  7. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  8. *
  9. * */
  10. 'use strict';
  11. import H from './Globals.js';
  12. var charts = H.charts, doc = H.doc, win = H.win;
  13. /**
  14. * An animation configuration. Animation configurations can also be defined as
  15. * booleans, where `false` turns off animation and `true` defaults to a duration
  16. * of 500ms and defer of 0ms.
  17. *
  18. * @interface Highcharts.AnimationOptionsObject
  19. */ /**
  20. * A callback function to exectute when the animation finishes.
  21. * @name Highcharts.AnimationOptionsObject#complete
  22. * @type {Function|undefined}
  23. */ /**
  24. * The animation defer in milliseconds.
  25. * @name Highcharts.AnimationOptionsObject#defer
  26. * @type {number|undefined}
  27. */ /**
  28. * The animation duration in milliseconds.
  29. * @name Highcharts.AnimationOptionsObject#duration
  30. * @type {number|undefined}
  31. */ /**
  32. * The name of an easing function as defined on the `Math` object.
  33. * @name Highcharts.AnimationOptionsObject#easing
  34. * @type {string|Function|undefined}
  35. */ /**
  36. * A callback function to execute on each step of each attribute or CSS property
  37. * that's being animated. The first argument contains information about the
  38. * animation and progress.
  39. * @name Highcharts.AnimationOptionsObject#step
  40. * @type {Function|undefined}
  41. */
  42. /**
  43. * Creates a frame for the animated SVG element.
  44. *
  45. * @callback Highcharts.AnimationStepCallbackFunction
  46. *
  47. * @param {Highcharts.SVGElement} this
  48. * The SVG element to animate.
  49. *
  50. * @return {void}
  51. */
  52. /**
  53. * Interface description for a class.
  54. *
  55. * @interface Highcharts.Class<T>
  56. * @extends Function
  57. */ /**
  58. * Class costructor.
  59. * @function Highcharts.Class<T>#new
  60. * @param {...Array<*>} args
  61. * Constructor arguments.
  62. * @return {T}
  63. * Class instance.
  64. */
  65. /**
  66. * A style object with camel case property names to define visual appearance of
  67. * a SVG element or HTML element. The properties can be whatever styles are
  68. * supported on the given SVG or HTML element.
  69. *
  70. * @example
  71. * {
  72. * fontFamily: 'monospace',
  73. * fontSize: '1.2em'
  74. * }
  75. *
  76. * @interface Highcharts.CSSObject
  77. */ /**
  78. * @name Highcharts.CSSObject#[key:string]
  79. * @type {boolean|number|string|undefined}
  80. */ /**
  81. * Background style for the element.
  82. * @name Highcharts.CSSObject#background
  83. * @type {string|undefined}
  84. */ /**
  85. * Background color of the element.
  86. * @name Highcharts.CSSObject#backgroundColor
  87. * @type {Highcharts.ColorString|undefined}
  88. */ /**
  89. * Border style for the element.
  90. * @name Highcharts.CSSObject#border
  91. * @type {string|undefined}
  92. */ /**
  93. * Radius of the element border.
  94. * @name Highcharts.CSSObject#borderRadius
  95. * @type {number|undefined}
  96. */ /**
  97. * Color used in the element. The 'contrast' option is a Highcharts custom
  98. * property that results in black or white, depending on the background of the
  99. * element.
  100. * @name Highcharts.CSSObject#color
  101. * @type {'contrast'|Highcharts.ColorString|undefined}
  102. */ /**
  103. * Style of the mouse cursor when resting over the element.
  104. * @name Highcharts.CSSObject#cursor
  105. * @type {Highcharts.CursorValue|undefined}
  106. */ /**
  107. * Font family of the element text. Multiple values have to be in decreasing
  108. * preference order and separated by comma.
  109. * @name Highcharts.CSSObject#fontFamily
  110. * @type {string|undefined}
  111. */ /**
  112. * Font size of the element text.
  113. * @name Highcharts.CSSObject#fontSize
  114. * @type {string|undefined}
  115. */ /**
  116. * Font weight of the element text.
  117. * @name Highcharts.CSSObject#fontWeight
  118. * @type {string|undefined}
  119. */ /**
  120. * Height of the element.
  121. * @name Highcharts.CSSObject#height
  122. * @type {number|undefined}
  123. */ /**
  124. * Width of the element border.
  125. * @name Highcharts.CSSObject#lineWidth
  126. * @type {number|undefined}
  127. */ /**
  128. * Opacity of the element.
  129. * @name Highcharts.CSSObject#opacity
  130. * @type {number|undefined}
  131. */ /**
  132. * Space around the element content.
  133. * @name Highcharts.CSSObject#padding
  134. * @type {string|undefined}
  135. */ /**
  136. * Behaviour of the element when the mouse cursor rests over it.
  137. * @name Highcharts.CSSObject#pointerEvents
  138. * @type {string|undefined}
  139. */ /**
  140. * Positioning of the element.
  141. * @name Highcharts.CSSObject#position
  142. * @type {string|undefined}
  143. */ /**
  144. * Alignment of the element text.
  145. * @name Highcharts.CSSObject#textAlign
  146. * @type {string|undefined}
  147. */ /**
  148. * Additional decoration of the element text.
  149. * @name Highcharts.CSSObject#textDecoration
  150. * @type {string|undefined}
  151. */ /**
  152. * Outline style of the element text.
  153. * @name Highcharts.CSSObject#textOutline
  154. * @type {string|undefined}
  155. */ /**
  156. * Line break style of the element text. Highcharts SVG elements support
  157. * `ellipsis` when a `width` is set.
  158. * @name Highcharts.CSSObject#textOverflow
  159. * @type {string|undefined}
  160. */ /**
  161. * Top spacing of the element relative to the parent element.
  162. * @name Highcharts.CSSObject#top
  163. * @type {string|undefined}
  164. */ /**
  165. * Animated transition of selected element properties.
  166. * @name Highcharts.CSSObject#transition
  167. * @type {string|undefined}
  168. */ /**
  169. * Line break style of the element text.
  170. * @name Highcharts.CSSObject#whiteSpace
  171. * @type {string|undefined}
  172. */ /**
  173. * Width of the element.
  174. * @name Highcharts.CSSObject#width
  175. * @type {number|undefined}
  176. */
  177. /**
  178. * All possible cursor styles.
  179. *
  180. * @typedef {'alias'|'all-scroll'|'auto'|'cell'|'col-resize'|'context-menu'|'copy'|'crosshair'|'default'|'e-resize'|'ew-resize'|'grab'|'grabbing'|'help'|'move'|'n-resize'|'ne-resize'|'nesw-resize'|'no-drop'|'none'|'not-allowed'|'ns-resize'|'nw-resize'|'nwse-resize'|'pointer'|'progress'|'row-resize'|'s-resize'|'se-resize'|'sw-resize'|'text'|'vertical-text'|'w-resize'|'wait'|'zoom-in'|'zoom-out'} Highcharts.CursorValue
  181. */
  182. /**
  183. * All possible dash styles.
  184. *
  185. * @typedef {'Dash'|'DashDot'|'Dot'|'LongDash'|'LongDashDot'|'LongDashDotDot'|'ShortDash'|'ShortDashDot'|'ShortDashDotDot'|'ShortDot'|'Solid'} Highcharts.DashStyleValue
  186. */
  187. /**
  188. * Generic dictionary in TypeScript notation.
  189. * Use the native `AnyRecord` instead.
  190. *
  191. * @deprecated
  192. * @interface Highcharts.Dictionary<T>
  193. */ /**
  194. * @name Highcharts.Dictionary<T>#[key:string]
  195. * @type {T}
  196. */
  197. /**
  198. * The function callback to execute when the event is fired. The `this` context
  199. * contains the instance, that fired the event.
  200. *
  201. * @callback Highcharts.EventCallbackFunction<T>
  202. *
  203. * @param {T} this
  204. *
  205. * @param {Highcharts.Dictionary<*>|Event} [eventArguments]
  206. * Event arguments.
  207. *
  208. * @return {boolean|void}
  209. */
  210. /**
  211. * The event options for adding function callback.
  212. *
  213. * @interface Highcharts.EventOptionsObject
  214. */ /**
  215. * The order the event handler should be called. This opens for having one
  216. * handler be called before another, independent of in which order they were
  217. * added.
  218. * @name Highcharts.EventOptionsObject#order
  219. * @type {number}
  220. */ /**
  221. * Whether an event should be passive or not.
  222. * When set to `true`, the function specified by listener will never call
  223. * `preventDefault()`.
  224. * @name Highcharts.EventOptionsObject#passive
  225. * @type boolean
  226. */
  227. /**
  228. * Formats data as a string. Usually the data is accessible throught the `this`
  229. * keyword.
  230. *
  231. * @callback Highcharts.FormatterCallbackFunction<T>
  232. *
  233. * @param {T} this
  234. * Context to format
  235. *
  236. * @return {string}
  237. * Formatted text
  238. */
  239. /**
  240. * An object of key-value pairs for HTML attributes.
  241. *
  242. * @typedef {Highcharts.Dictionary<boolean|number|string|Function>} Highcharts.HTMLAttributes
  243. */
  244. /**
  245. * An HTML DOM element. The type is a reference to the regular HTMLElement in
  246. * the global scope.
  247. *
  248. * @typedef {global.HTMLElement} Highcharts.HTMLDOMElement
  249. *
  250. * @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement
  251. */
  252. /**
  253. * The iterator callback.
  254. *
  255. * @callback Highcharts.ObjectEachCallbackFunction<T>
  256. *
  257. * @param {T} this
  258. * The context.
  259. *
  260. * @param {*} value
  261. * The property value.
  262. *
  263. * @param {string} key
  264. * The property key.
  265. *
  266. * @param {*} obj
  267. * The object that objectEach is being applied to.
  268. */
  269. /**
  270. * An object containing `left` and `top` properties for the position in the
  271. * page.
  272. *
  273. * @interface Highcharts.OffsetObject
  274. */ /**
  275. * Left distance to the page border.
  276. * @name Highcharts.OffsetObject#left
  277. * @type {number}
  278. */ /**
  279. * Top distance to the page border.
  280. * @name Highcharts.OffsetObject#top
  281. * @type {number}
  282. */
  283. /**
  284. * Describes a range.
  285. *
  286. * @interface Highcharts.RangeObject
  287. */ /**
  288. * Maximum number of the range.
  289. * @name Highcharts.RangeObject#max
  290. * @type {number}
  291. */ /**
  292. * Minimum number of the range.
  293. * @name Highcharts.RangeObject#min
  294. * @type {number}
  295. */
  296. /**
  297. * If a number is given, it defines the pixel length. If a percentage string is
  298. * given, like for example `'50%'`, the setting defines a length relative to a
  299. * base size, for example the size of a container.
  300. *
  301. * @typedef {number|string} Highcharts.RelativeSize
  302. */
  303. /**
  304. * Proceed function to call original (wrapped) function.
  305. *
  306. * @callback Highcharts.WrapProceedFunction
  307. *
  308. * @param {*} [arg1]
  309. * Optional argument. Without any arguments defaults to first argument of
  310. * the wrapping function.
  311. *
  312. * @param {*} [arg2]
  313. * Optional argument. Without any arguments defaults to second argument
  314. * of the wrapping function.
  315. *
  316. * @param {*} [arg3]
  317. * Optional argument. Without any arguments defaults to third argument of
  318. * the wrapping function.
  319. *
  320. * @return {*}
  321. * Return value of the original function.
  322. */
  323. /**
  324. * The Highcharts object is the placeholder for all other members, and various
  325. * utility functions. The most important member of the namespace would be the
  326. * chart constructor.
  327. *
  328. * @example
  329. * let chart = Highcharts.chart('container', { ... });
  330. *
  331. * @namespace Highcharts
  332. */
  333. ''; // detach doclets above
  334. /**
  335. * Provide error messages for debugging, with links to online explanation. This
  336. * function can be overridden to provide custom error handling.
  337. *
  338. * @sample highcharts/chart/highcharts-error/
  339. * Custom error handler
  340. *
  341. * @function Highcharts.error
  342. *
  343. * @param {number|string} code
  344. * The error code. See
  345. * [errors.xml](https://github.com/highcharts/highcharts/blob/master/errors/errors.xml)
  346. * for available codes. If it is a string, the error message is printed
  347. * directly in the console.
  348. *
  349. * @param {boolean} [stop=false]
  350. * Whether to throw an error or just log a warning in the console.
  351. *
  352. * @param {Highcharts.Chart} [chart]
  353. * Reference to the chart that causes the error. Used in 'debugger'
  354. * module to display errors directly on the chart.
  355. * Important note: This argument is undefined for errors that lack
  356. * access to the Chart instance. In such case, the error will be
  357. * displayed on the last created chart.
  358. *
  359. * @param {Highcharts.Dictionary<string>} [params]
  360. * Additional parameters for the generated message.
  361. *
  362. * @return {void}
  363. */
  364. function error(code, stop, chart, params) {
  365. var severity = stop ? 'Highcharts error' : 'Highcharts warning';
  366. if (code === 32) {
  367. code = severity + ": Deprecated member";
  368. }
  369. var isCode = isNumber(code);
  370. var message = isCode ?
  371. severity + " #" + code + ": www.highcharts.com/errors/" + code + "/" :
  372. code.toString();
  373. var defaultHandler = function () {
  374. if (stop) {
  375. throw new Error(message);
  376. }
  377. // else ...
  378. if (win.console &&
  379. error.messages.indexOf(message) === -1 // prevent console flooting
  380. ) {
  381. console.warn(message); // eslint-disable-line no-console
  382. }
  383. };
  384. if (typeof params !== 'undefined') {
  385. var additionalMessages_1 = '';
  386. if (isCode) {
  387. message += '?';
  388. }
  389. objectEach(params, function (value, key) {
  390. additionalMessages_1 += "\n - " + key + ": " + value;
  391. if (isCode) {
  392. message += encodeURI(key) + '=' + encodeURI(value);
  393. }
  394. });
  395. message += additionalMessages_1;
  396. }
  397. fireEvent(Highcharts, 'displayError', { chart: chart, code: code, message: message, params: params }, defaultHandler);
  398. error.messages.push(message);
  399. }
  400. (function (error) {
  401. error.messages = [];
  402. })(error || (error = {}));
  403. /* eslint-disable valid-jsdoc */
  404. /**
  405. * Utility function to deep merge two or more objects and return a third object.
  406. * If the first argument is true, the contents of the second object is copied
  407. * into the first object. The merge function can also be used with a single
  408. * object argument to create a deep copy of an object.
  409. *
  410. * @function Highcharts.merge<T>
  411. *
  412. * @param {boolean} extend
  413. * Whether to extend the left-side object (a) or return a whole new
  414. * object.
  415. *
  416. * @param {T|undefined} a
  417. * The first object to extend. When only this is given, the function
  418. * returns a deep copy.
  419. *
  420. * @param {...Array<object|undefined>} [n]
  421. * An object to merge into the previous one.
  422. *
  423. * @return {T}
  424. * The merged object. If the first argument is true, the return is the
  425. * same as the second argument.
  426. */ /**
  427. * Utility function to deep merge two or more objects and return a third object.
  428. * The merge function can also be used with a single object argument to create a
  429. * deep copy of an object.
  430. *
  431. * @function Highcharts.merge<T>
  432. *
  433. * @param {T|undefined} a
  434. * The first object to extend. When only this is given, the function
  435. * returns a deep copy.
  436. *
  437. * @param {...Array<object|undefined>} [n]
  438. * An object to merge into the previous one.
  439. *
  440. * @return {T}
  441. * The merged object. If the first argument is true, the return is the
  442. * same as the second argument.
  443. */
  444. function merge() {
  445. /* eslint-enable valid-jsdoc */
  446. var i, args = arguments, ret = {};
  447. var doCopy = function (copy, original) {
  448. // An object is replacing a primitive
  449. if (typeof copy !== 'object') {
  450. copy = {};
  451. }
  452. objectEach(original, function (value, key) {
  453. // Prototype pollution (#14883)
  454. if (key === '__proto__' || key === 'constructor') {
  455. return;
  456. }
  457. // Copy the contents of objects, but not arrays or DOM nodes
  458. if (isObject(value, true) &&
  459. !isClass(value) &&
  460. !isDOMElement(value)) {
  461. copy[key] = doCopy(copy[key] || {}, value);
  462. // Primitives and arrays are copied over directly
  463. }
  464. else {
  465. copy[key] = original[key];
  466. }
  467. });
  468. return copy;
  469. };
  470. // If first argument is true, copy into the existing object. Used in
  471. // setOptions.
  472. if (args[0] === true) {
  473. ret = args[1];
  474. args = Array.prototype.slice.call(args, 2);
  475. }
  476. // For each argument, extend the return
  477. var len = args.length;
  478. for (i = 0; i < len; i++) {
  479. ret = doCopy(ret, args[i]);
  480. }
  481. return ret;
  482. }
  483. /**
  484. * Constrain a value to within a lower and upper threshold.
  485. *
  486. * @private
  487. * @param {number} value The initial value
  488. * @param {number} min The lower threshold
  489. * @param {number} max The upper threshold
  490. * @return {number} Returns a number value within min and max.
  491. */
  492. function clamp(value, min, max) {
  493. return value > min ? value < max ? value : max : min;
  494. }
  495. // eslint-disable-next-line valid-jsdoc
  496. /**
  497. * Remove settings that have not changed, to avoid unnecessary rendering or
  498. * computing (#9197).
  499. * @private
  500. */
  501. function cleanRecursively(newer, older) {
  502. var result = {};
  503. objectEach(newer, function (_val, key) {
  504. var ob;
  505. // Dive into objects (except DOM nodes)
  506. if (isObject(newer[key], true) &&
  507. !newer.nodeType && // #10044
  508. older[key]) {
  509. ob = cleanRecursively(newer[key], older[key]);
  510. if (Object.keys(ob).length) {
  511. result[key] = ob;
  512. }
  513. // Arrays, primitives and DOM nodes are copied directly
  514. }
  515. else if (isObject(newer[key]) ||
  516. newer[key] !== older[key]) {
  517. result[key] = newer[key];
  518. }
  519. });
  520. return result;
  521. }
  522. /**
  523. * Shortcut for parseInt
  524. *
  525. * @private
  526. * @function Highcharts.pInt
  527. *
  528. * @param {*} s
  529. * any
  530. *
  531. * @param {number} [mag]
  532. * Magnitude
  533. *
  534. * @return {number}
  535. * number
  536. */
  537. function pInt(s, mag) {
  538. return parseInt(s, mag || 10);
  539. }
  540. /**
  541. * Utility function to check for string type.
  542. *
  543. * @function Highcharts.isString
  544. *
  545. * @param {*} s
  546. * The item to check.
  547. *
  548. * @return {boolean}
  549. * True if the argument is a string.
  550. */
  551. function isString(s) {
  552. return typeof s === 'string';
  553. }
  554. /**
  555. * Utility function to check if an item is an array.
  556. *
  557. * @function Highcharts.isArray
  558. *
  559. * @param {*} obj
  560. * The item to check.
  561. *
  562. * @return {boolean}
  563. * True if the argument is an array.
  564. */
  565. function isArray(obj) {
  566. var str = Object.prototype.toString.call(obj);
  567. return str === '[object Array]' || str === '[object Array Iterator]';
  568. }
  569. /**
  570. * Utility function to check if an item is of type object.
  571. *
  572. * @function Highcharts.isObject
  573. *
  574. * @param {*} obj
  575. * The item to check.
  576. *
  577. * @param {boolean} [strict=false]
  578. * Also checks that the object is not an array.
  579. *
  580. * @return {boolean}
  581. * True if the argument is an object.
  582. */
  583. function isObject(obj, strict) {
  584. return (!!obj &&
  585. typeof obj === 'object' &&
  586. (!strict || !isArray(obj))); // eslint-disable-line @typescript-eslint/no-explicit-any
  587. }
  588. /**
  589. * Utility function to check if an Object is a HTML Element.
  590. *
  591. * @function Highcharts.isDOMElement
  592. *
  593. * @param {*} obj
  594. * The item to check.
  595. *
  596. * @return {boolean}
  597. * True if the argument is a HTML Element.
  598. */
  599. function isDOMElement(obj) {
  600. return isObject(obj) && typeof obj.nodeType === 'number';
  601. }
  602. /**
  603. * Utility function to check if an Object is a class.
  604. *
  605. * @function Highcharts.isClass
  606. *
  607. * @param {object|undefined} obj
  608. * The item to check.
  609. *
  610. * @return {boolean}
  611. * True if the argument is a class.
  612. */
  613. function isClass(obj) {
  614. var c = obj && obj.constructor;
  615. return !!(isObject(obj, true) &&
  616. !isDOMElement(obj) &&
  617. (c && c.name && c.name !== 'Object'));
  618. }
  619. /**
  620. * Utility function to check if an item is a number and it is finite (not NaN,
  621. * Infinity or -Infinity).
  622. *
  623. * @function Highcharts.isNumber
  624. *
  625. * @param {*} n
  626. * The item to check.
  627. *
  628. * @return {boolean}
  629. * True if the item is a finite number
  630. */
  631. function isNumber(n) {
  632. return typeof n === 'number' && !isNaN(n) && n < Infinity && n > -Infinity;
  633. }
  634. /**
  635. * Remove the last occurence of an item from an array.
  636. *
  637. * @function Highcharts.erase
  638. *
  639. * @param {Array<*>} arr
  640. * The array.
  641. *
  642. * @param {*} item
  643. * The item to remove.
  644. *
  645. * @return {void}
  646. */
  647. function erase(arr, item) {
  648. var i = arr.length;
  649. while (i--) {
  650. if (arr[i] === item) {
  651. arr.splice(i, 1);
  652. break;
  653. }
  654. }
  655. }
  656. /**
  657. * Check if an object is null or undefined.
  658. *
  659. * @function Highcharts.defined
  660. *
  661. * @param {*} obj
  662. * The object to check.
  663. *
  664. * @return {boolean}
  665. * False if the object is null or undefined, otherwise true.
  666. */
  667. function defined(obj) {
  668. return typeof obj !== 'undefined' && obj !== null;
  669. }
  670. /**
  671. * Set or get an attribute or an object of attributes. To use as a setter, pass
  672. * a key and a value, or let the second argument be a collection of keys and
  673. * values. To use as a getter, pass only a string as the second argument.
  674. *
  675. * @function Highcharts.attr
  676. *
  677. * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} elem
  678. * The DOM element to receive the attribute(s).
  679. *
  680. * @param {string|Highcharts.HTMLAttributes|Highcharts.SVGAttributes} [prop]
  681. * The property or an object of key-value pairs.
  682. *
  683. * @param {number|string} [value]
  684. * The value if a single property is set.
  685. *
  686. * @return {string|null|undefined}
  687. * When used as a getter, return the value.
  688. */
  689. function attr(elem, prop, value) {
  690. var ret;
  691. // if the prop is a string
  692. if (isString(prop)) {
  693. // set the value
  694. if (defined(value)) {
  695. elem.setAttribute(prop, value);
  696. // get the value
  697. }
  698. else if (elem && elem.getAttribute) {
  699. ret = elem.getAttribute(prop);
  700. // IE7 and below cannot get class through getAttribute (#7850)
  701. if (!ret && prop === 'class') {
  702. ret = elem.getAttribute(prop + 'Name');
  703. }
  704. }
  705. // else if prop is defined, it is a hash of key/value pairs
  706. }
  707. else {
  708. objectEach(prop, function (val, key) {
  709. elem.setAttribute(key, val);
  710. });
  711. }
  712. return ret;
  713. }
  714. /**
  715. * Check if an element is an array, and if not, make it into an array.
  716. *
  717. * @function Highcharts.splat
  718. *
  719. * @param {*} obj
  720. * The object to splat.
  721. *
  722. * @return {Array}
  723. * The produced or original array.
  724. */
  725. function splat(obj) {
  726. return isArray(obj) ? obj : [obj];
  727. }
  728. /**
  729. * Set a timeout if the delay is given, otherwise perform the function
  730. * synchronously.
  731. *
  732. * @function Highcharts.syncTimeout
  733. *
  734. * @param {Function} fn
  735. * The function callback.
  736. *
  737. * @param {number} delay
  738. * Delay in milliseconds.
  739. *
  740. * @param {*} [context]
  741. * An optional context to send to the function callback.
  742. *
  743. * @return {number}
  744. * An identifier for the timeout that can later be cleared with
  745. * Highcharts.clearTimeout. Returns -1 if there is no timeout.
  746. */
  747. function syncTimeout(fn, delay, context) {
  748. if (delay > 0) {
  749. return setTimeout(fn, delay, context);
  750. }
  751. fn.call(0, context);
  752. return -1;
  753. }
  754. /**
  755. * Internal clear timeout. The function checks that the `id` was not removed
  756. * (e.g. by `chart.destroy()`). For the details see
  757. * [issue #7901](https://github.com/highcharts/highcharts/issues/7901).
  758. *
  759. * @function Highcharts.clearTimeout
  760. *
  761. * @param {number} id
  762. * Id of a timeout.
  763. *
  764. * @return {void}
  765. */
  766. function internalClearTimeout(id) {
  767. if (defined(id)) {
  768. clearTimeout(id);
  769. }
  770. }
  771. /* eslint-disable valid-jsdoc */
  772. /**
  773. * Utility function to extend an object with the members of another.
  774. *
  775. * @function Highcharts.extend<T>
  776. *
  777. * @param {T|undefined} a
  778. * The object to be extended.
  779. *
  780. * @param {Partial<T>} b
  781. * The object to add to the first one.
  782. *
  783. * @return {T}
  784. * Object a, the original object.
  785. */
  786. function extend(a, b) {
  787. /* eslint-enable valid-jsdoc */
  788. var n;
  789. if (!a) {
  790. a = {};
  791. }
  792. for (n in b) { // eslint-disable-line guard-for-in
  793. a[n] = b[n];
  794. }
  795. return a;
  796. }
  797. /* eslint-disable valid-jsdoc */
  798. /**
  799. * Return the first value that is not null or undefined.
  800. *
  801. * @function Highcharts.pick<T>
  802. *
  803. * @param {...Array<T|null|undefined>} items
  804. * Variable number of arguments to inspect.
  805. *
  806. * @return {T}
  807. * The value of the first argument that is not null or undefined.
  808. */
  809. function pick() {
  810. var args = arguments;
  811. var length = args.length;
  812. for (var i = 0; i < length; i++) {
  813. var arg = args[i];
  814. if (typeof arg !== 'undefined' && arg !== null) {
  815. return arg;
  816. }
  817. }
  818. }
  819. /**
  820. * Set CSS on a given element.
  821. *
  822. * @function Highcharts.css
  823. *
  824. * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} el
  825. * An HTML DOM element.
  826. *
  827. * @param {Highcharts.CSSObject} styles
  828. * Style object with camel case property names.
  829. *
  830. * @return {void}
  831. */
  832. function css(el, styles) {
  833. if (H.isMS && !H.svg) { // #2686
  834. if (styles && typeof styles.opacity !== 'undefined') {
  835. styles.filter =
  836. 'alpha(opacity=' + (styles.opacity * 100) + ')';
  837. }
  838. }
  839. extend(el.style, styles);
  840. }
  841. /**
  842. * Utility function to create an HTML element with attributes and styles.
  843. *
  844. * @function Highcharts.createElement
  845. *
  846. * @param {string} tag
  847. * The HTML tag.
  848. *
  849. * @param {Highcharts.HTMLAttributes} [attribs]
  850. * Attributes as an object of key-value pairs.
  851. *
  852. * @param {Highcharts.CSSObject} [styles]
  853. * Styles as an object of key-value pairs.
  854. *
  855. * @param {Highcharts.HTMLDOMElement} [parent]
  856. * The parent HTML object.
  857. *
  858. * @param {boolean} [nopad=false]
  859. * If true, remove all padding, border and margin.
  860. *
  861. * @return {Highcharts.HTMLDOMElement}
  862. * The created DOM element.
  863. */
  864. function createElement(tag, attribs, styles, parent, nopad) {
  865. var el = doc.createElement(tag);
  866. if (attribs) {
  867. extend(el, attribs);
  868. }
  869. if (nopad) {
  870. css(el, { padding: '0', border: 'none', margin: '0' });
  871. }
  872. if (styles) {
  873. css(el, styles);
  874. }
  875. if (parent) {
  876. parent.appendChild(el);
  877. }
  878. return el;
  879. }
  880. // eslint-disable-next-line valid-jsdoc
  881. /**
  882. * Extend a prototyped class by new members.
  883. *
  884. * @function Highcharts.extendClass<T>
  885. *
  886. * @param {Highcharts.Class<T>} parent
  887. * The parent prototype to inherit.
  888. *
  889. * @param {Highcharts.Dictionary<*>} members
  890. * A collection of prototype members to add or override compared to the
  891. * parent prototype.
  892. *
  893. * @return {Highcharts.Class<T>}
  894. * A new prototype.
  895. */
  896. function extendClass(parent, members) {
  897. var obj = (function () { });
  898. obj.prototype = new parent(); // eslint-disable-line new-cap
  899. extend(obj.prototype, members);
  900. return obj;
  901. }
  902. /**
  903. * Left-pad a string to a given length by adding a character repetetively.
  904. *
  905. * @function Highcharts.pad
  906. *
  907. * @param {number} number
  908. * The input string or number.
  909. *
  910. * @param {number} [length]
  911. * The desired string length.
  912. *
  913. * @param {string} [padder=0]
  914. * The character to pad with.
  915. *
  916. * @return {string}
  917. * The padded string.
  918. */
  919. function pad(number, length, padder) {
  920. return new Array((length || 2) +
  921. 1 -
  922. String(number)
  923. .replace('-', '')
  924. .length).join(padder || '0') + number;
  925. }
  926. /**
  927. * Return a length based on either the integer value, or a percentage of a base.
  928. *
  929. * @function Highcharts.relativeLength
  930. *
  931. * @param {Highcharts.RelativeSize} value
  932. * A percentage string or a number.
  933. *
  934. * @param {number} base
  935. * The full length that represents 100%.
  936. *
  937. * @param {number} [offset=0]
  938. * A pixel offset to apply for percentage values. Used internally in
  939. * axis positioning.
  940. *
  941. * @return {number}
  942. * The computed length.
  943. */
  944. function relativeLength(value, base, offset) {
  945. return (/%$/).test(value) ?
  946. (base * parseFloat(value) / 100) + (offset || 0) :
  947. parseFloat(value);
  948. }
  949. /**
  950. * Wrap a method with extended functionality, preserving the original function.
  951. *
  952. * @function Highcharts.wrap
  953. *
  954. * @param {*} obj
  955. * The context object that the method belongs to. In real cases, this is
  956. * often a prototype.
  957. *
  958. * @param {string} method
  959. * The name of the method to extend.
  960. *
  961. * @param {Highcharts.WrapProceedFunction} func
  962. * A wrapper function callback. This function is called with the same
  963. * arguments as the original function, except that the original function
  964. * is unshifted and passed as the first argument.
  965. */
  966. function wrap(obj, method, func) {
  967. var proceed = obj[method];
  968. obj[method] = function () {
  969. var args = Array.prototype.slice.call(arguments), outerArgs = arguments, ctx = this;
  970. ctx.proceed = function () {
  971. proceed.apply(ctx, arguments.length ? arguments : outerArgs);
  972. };
  973. args.unshift(proceed);
  974. var ret = func.apply(this, args);
  975. ctx.proceed = null;
  976. return ret;
  977. };
  978. }
  979. /**
  980. * Get the magnitude of a number.
  981. *
  982. * @function Highcharts.getMagnitude
  983. *
  984. * @param {number} num
  985. * The number.
  986. *
  987. * @return {number}
  988. * The magnitude, where 1-9 are magnitude 1, 10-99 magnitude 2 etc.
  989. */
  990. function getMagnitude(num) {
  991. return Math.pow(10, Math.floor(Math.log(num) / Math.LN10));
  992. }
  993. /**
  994. * Take an interval and normalize it to multiples of round numbers.
  995. *
  996. * @deprecated
  997. * @function Highcharts.normalizeTickInterval
  998. *
  999. * @param {number} interval
  1000. * The raw, un-rounded interval.
  1001. *
  1002. * @param {Array<*>} [multiples]
  1003. * Allowed multiples.
  1004. *
  1005. * @param {number} [magnitude]
  1006. * The magnitude of the number.
  1007. *
  1008. * @param {boolean} [allowDecimals]
  1009. * Whether to allow decimals.
  1010. *
  1011. * @param {boolean} [hasTickAmount]
  1012. * If it has tickAmount, avoid landing on tick intervals lower than
  1013. * original.
  1014. *
  1015. * @return {number}
  1016. * The normalized interval.
  1017. *
  1018. * @todo
  1019. * Move this function to the Axis prototype. It is here only for historical
  1020. * reasons.
  1021. */
  1022. function normalizeTickInterval(interval, multiples, magnitude, allowDecimals, hasTickAmount) {
  1023. var i, retInterval = interval;
  1024. // round to a tenfold of 1, 2, 2.5 or 5
  1025. magnitude = pick(magnitude, 1);
  1026. var normalized = interval / magnitude;
  1027. // multiples for a linear scale
  1028. if (!multiples) {
  1029. multiples = hasTickAmount ?
  1030. // Finer grained ticks when the tick amount is hard set, including
  1031. // when alignTicks is true on multiple axes (#4580).
  1032. [1, 1.2, 1.5, 2, 2.5, 3, 4, 5, 6, 8, 10] :
  1033. // Else, let ticks fall on rounder numbers
  1034. [1, 2, 2.5, 5, 10];
  1035. // the allowDecimals option
  1036. if (allowDecimals === false) {
  1037. if (magnitude === 1) {
  1038. multiples = multiples.filter(function (num) {
  1039. return num % 1 === 0;
  1040. });
  1041. }
  1042. else if (magnitude <= 0.1) {
  1043. multiples = [1 / magnitude];
  1044. }
  1045. }
  1046. }
  1047. // normalize the interval to the nearest multiple
  1048. for (i = 0; i < multiples.length; i++) {
  1049. retInterval = multiples[i];
  1050. // only allow tick amounts smaller than natural
  1051. if ((hasTickAmount &&
  1052. retInterval * magnitude >= interval) ||
  1053. (!hasTickAmount &&
  1054. (normalized <=
  1055. (multiples[i] +
  1056. (multiples[i + 1] || multiples[i])) / 2))) {
  1057. break;
  1058. }
  1059. }
  1060. // Multiply back to the correct magnitude. Correct floats to appropriate
  1061. // precision (#6085).
  1062. retInterval = correctFloat(retInterval * magnitude, -Math.round(Math.log(0.001) / Math.LN10));
  1063. return retInterval;
  1064. }
  1065. /**
  1066. * Sort an object array and keep the order of equal items. The ECMAScript
  1067. * standard does not specify the behaviour when items are equal.
  1068. *
  1069. * @function Highcharts.stableSort
  1070. *
  1071. * @param {Array<*>} arr
  1072. * The array to sort.
  1073. *
  1074. * @param {Function} sortFunction
  1075. * The function to sort it with, like with regular Array.prototype.sort.
  1076. *
  1077. * @return {void}
  1078. */
  1079. function stableSort(arr, sortFunction) {
  1080. // @todo It seems like Chrome since v70 sorts in a stable way internally,
  1081. // plus all other browsers do it, so over time we may be able to remove this
  1082. // function
  1083. var length = arr.length;
  1084. var sortValue, i;
  1085. // Add index to each item
  1086. for (i = 0; i < length; i++) {
  1087. arr[i].safeI = i; // stable sort index
  1088. }
  1089. arr.sort(function (a, b) {
  1090. sortValue = sortFunction(a, b);
  1091. return sortValue === 0 ? a.safeI - b.safeI : sortValue;
  1092. });
  1093. // Remove index from items
  1094. for (i = 0; i < length; i++) {
  1095. delete arr[i].safeI; // stable sort index
  1096. }
  1097. }
  1098. /**
  1099. * Non-recursive method to find the lowest member of an array. `Math.min` raises
  1100. * a maximum call stack size exceeded error in Chrome when trying to apply more
  1101. * than 150.000 points. This method is slightly slower, but safe.
  1102. *
  1103. * @function Highcharts.arrayMin
  1104. *
  1105. * @param {Array<*>} data
  1106. * An array of numbers.
  1107. *
  1108. * @return {number}
  1109. * The lowest number.
  1110. */
  1111. function arrayMin(data) {
  1112. var i = data.length, min = data[0];
  1113. while (i--) {
  1114. if (data[i] < min) {
  1115. min = data[i];
  1116. }
  1117. }
  1118. return min;
  1119. }
  1120. /**
  1121. * Non-recursive method to find the lowest member of an array. `Math.max` raises
  1122. * a maximum call stack size exceeded error in Chrome when trying to apply more
  1123. * than 150.000 points. This method is slightly slower, but safe.
  1124. *
  1125. * @function Highcharts.arrayMax
  1126. *
  1127. * @param {Array<*>} data
  1128. * An array of numbers.
  1129. *
  1130. * @return {number}
  1131. * The highest number.
  1132. */
  1133. function arrayMax(data) {
  1134. var i = data.length, max = data[0];
  1135. while (i--) {
  1136. if (data[i] > max) {
  1137. max = data[i];
  1138. }
  1139. }
  1140. return max;
  1141. }
  1142. /**
  1143. * Utility method that destroys any SVGElement instances that are properties on
  1144. * the given object. It loops all properties and invokes destroy if there is a
  1145. * destroy method. The property is then delete.
  1146. *
  1147. * @function Highcharts.destroyObjectProperties
  1148. *
  1149. * @param {*} obj
  1150. * The object to destroy properties on.
  1151. *
  1152. * @param {*} [except]
  1153. * Exception, do not destroy this property, only delete it.
  1154. */
  1155. function destroyObjectProperties(obj, except) {
  1156. objectEach(obj, function (val, n) {
  1157. // If the object is non-null and destroy is defined
  1158. if (val && val !== except && val.destroy) {
  1159. // Invoke the destroy
  1160. val.destroy();
  1161. }
  1162. // Delete the property from the object.
  1163. delete obj[n];
  1164. });
  1165. }
  1166. /**
  1167. * Discard a HTML element by moving it to the bin and delete.
  1168. *
  1169. * @function Highcharts.discardElement
  1170. *
  1171. * @param {Highcharts.HTMLDOMElement} element
  1172. * The HTML node to discard.
  1173. */
  1174. function discardElement(element) {
  1175. // create a garbage bin element, not part of the DOM
  1176. if (!garbageBin) {
  1177. garbageBin = createElement('div');
  1178. }
  1179. // move the node and empty bin
  1180. if (element) {
  1181. garbageBin.appendChild(element);
  1182. }
  1183. garbageBin.innerHTML = '';
  1184. }
  1185. var garbageBin;
  1186. /**
  1187. * Fix JS round off float errors.
  1188. *
  1189. * @function Highcharts.correctFloat
  1190. *
  1191. * @param {number} num
  1192. * A float number to fix.
  1193. *
  1194. * @param {number} [prec=14]
  1195. * The precision.
  1196. *
  1197. * @return {number}
  1198. * The corrected float number.
  1199. */
  1200. function correctFloat(num, prec) {
  1201. return parseFloat(num.toPrecision(prec || 14));
  1202. }
  1203. /**
  1204. * The time unit lookup
  1205. *
  1206. * @ignore
  1207. */
  1208. var timeUnits = {
  1209. millisecond: 1,
  1210. second: 1000,
  1211. minute: 60000,
  1212. hour: 3600000,
  1213. day: 24 * 3600000,
  1214. week: 7 * 24 * 3600000,
  1215. month: 28 * 24 * 3600000,
  1216. year: 364 * 24 * 3600000
  1217. };
  1218. /**
  1219. * Easing definition
  1220. *
  1221. * @private
  1222. * @function Math.easeInOutSine
  1223. *
  1224. * @param {number} pos
  1225. * Current position, ranging from 0 to 1.
  1226. *
  1227. * @return {number}
  1228. * Ease result
  1229. */
  1230. Math.easeInOutSine = function (pos) {
  1231. return -0.5 * (Math.cos(Math.PI * pos) - 1);
  1232. };
  1233. /**
  1234. * Returns the value of a property path on a given object.
  1235. *
  1236. * @private
  1237. * @function getNestedProperty
  1238. *
  1239. * @param {string} path
  1240. * Path to the property, for example `custom.myValue`.
  1241. *
  1242. * @param {unknown} obj
  1243. * Instance containing the property on the specific path.
  1244. *
  1245. * @return {unknown}
  1246. * The unknown property value.
  1247. */
  1248. function getNestedProperty(path, parent) {
  1249. var pathElements = path.split('.');
  1250. while (pathElements.length && defined(parent)) {
  1251. var pathElement = pathElements.shift();
  1252. // Filter on the key
  1253. if (typeof pathElement === 'undefined' ||
  1254. pathElement === '__proto__') {
  1255. return; // undefined
  1256. }
  1257. var child = parent[pathElement];
  1258. // Filter on the child
  1259. if (!defined(child) ||
  1260. typeof child === 'function' ||
  1261. typeof child.nodeType === 'number' ||
  1262. child === win) {
  1263. return; // undefined
  1264. }
  1265. // Else, proceed
  1266. parent = child;
  1267. }
  1268. return parent;
  1269. }
  1270. /**
  1271. * Get the computed CSS value for given element and property, only for numerical
  1272. * properties. For width and height, the dimension of the inner box (excluding
  1273. * padding) is returned. Used for fitting the chart within the container.
  1274. *
  1275. * @function Highcharts.getStyle
  1276. *
  1277. * @param {Highcharts.HTMLDOMElement} el
  1278. * An HTML element.
  1279. *
  1280. * @param {string} prop
  1281. * The property name.
  1282. *
  1283. * @param {boolean} [toInt=true]
  1284. * Parse to integer.
  1285. *
  1286. * @return {number|string|undefined}
  1287. * The style value.
  1288. */
  1289. function getStyle(el, prop, toInt) {
  1290. var customGetStyle = (H.getStyle || // oldie getStyle
  1291. getStyle);
  1292. var style;
  1293. // For width and height, return the actual inner pixel size (#4913)
  1294. if (prop === 'width') {
  1295. var offsetWidth = Math.min(el.offsetWidth, el.scrollWidth);
  1296. // In flex boxes, we need to use getBoundingClientRect and floor it,
  1297. // because scrollWidth doesn't support subpixel precision (#6427) ...
  1298. var boundingClientRectWidth = el.getBoundingClientRect &&
  1299. el.getBoundingClientRect().width;
  1300. // ...unless if the containing div or its parents are transform-scaled
  1301. // down, in which case the boundingClientRect can't be used as it is
  1302. // also scaled down (#9871, #10498).
  1303. if (boundingClientRectWidth < offsetWidth &&
  1304. boundingClientRectWidth >= offsetWidth - 1) {
  1305. offsetWidth = Math.floor(boundingClientRectWidth);
  1306. }
  1307. return Math.max(0, // #8377
  1308. (offsetWidth -
  1309. (customGetStyle(el, 'padding-left', true) || 0) -
  1310. (customGetStyle(el, 'padding-right', true) || 0)));
  1311. }
  1312. if (prop === 'height') {
  1313. return Math.max(0, // #8377
  1314. (Math.min(el.offsetHeight, el.scrollHeight) -
  1315. (customGetStyle(el, 'padding-top', true) || 0) -
  1316. (customGetStyle(el, 'padding-bottom', true) || 0)));
  1317. }
  1318. if (!win.getComputedStyle) {
  1319. // SVG not supported, forgot to load oldie.js?
  1320. error(27, true);
  1321. }
  1322. // Otherwise, get the computed style
  1323. var css = win.getComputedStyle(el, undefined); // eslint-disable-line no-undefined
  1324. if (css) {
  1325. style = css.getPropertyValue(prop);
  1326. if (pick(toInt, prop !== 'opacity')) {
  1327. style = pInt(style);
  1328. }
  1329. }
  1330. return style;
  1331. }
  1332. /**
  1333. * Search for an item in an array.
  1334. *
  1335. * @function Highcharts.inArray
  1336. *
  1337. * @deprecated
  1338. *
  1339. * @param {*} item
  1340. * The item to search for.
  1341. *
  1342. * @param {Array<*>} arr
  1343. * The array or node collection to search in.
  1344. *
  1345. * @param {number} [fromIndex=0]
  1346. * The index to start searching from.
  1347. *
  1348. * @return {number}
  1349. * The index within the array, or -1 if not found.
  1350. */
  1351. function inArray(item, arr, fromIndex) {
  1352. error(32, false, void 0, { 'Highcharts.inArray': 'use Array.indexOf' });
  1353. return arr.indexOf(item, fromIndex);
  1354. }
  1355. /* eslint-disable valid-jsdoc */
  1356. /**
  1357. * Return the value of the first element in the array that satisfies the
  1358. * provided testing function.
  1359. *
  1360. * @function Highcharts.find<T>
  1361. *
  1362. * @param {Array<T>} arr
  1363. * The array to test.
  1364. *
  1365. * @param {Function} callback
  1366. * The callback function. The function receives the item as the first
  1367. * argument. Return `true` if this item satisfies the condition.
  1368. *
  1369. * @return {T|undefined}
  1370. * The value of the element.
  1371. */
  1372. var find = Array.prototype.find ?
  1373. /* eslint-enable valid-jsdoc */
  1374. function (arr, callback) {
  1375. return arr.find(callback);
  1376. } :
  1377. // Legacy implementation. PhantomJS, IE <= 11 etc. #7223.
  1378. function (arr, callback) {
  1379. var i;
  1380. var length = arr.length;
  1381. for (i = 0; i < length; i++) {
  1382. if (callback(arr[i], i)) { // eslint-disable-line callback-return
  1383. return arr[i];
  1384. }
  1385. }
  1386. };
  1387. /**
  1388. * Returns an array of a given object's own properties.
  1389. *
  1390. * @function Highcharts.keys
  1391. * @deprecated
  1392. *
  1393. * @param {*} obj
  1394. * The object of which the properties are to be returned.
  1395. *
  1396. * @return {Array<string>}
  1397. * An array of strings that represents all the properties.
  1398. */
  1399. function keys(obj) {
  1400. error(32, false, void 0, { 'Highcharts.keys': 'use Object.keys' });
  1401. return Object.keys(obj);
  1402. }
  1403. /**
  1404. * Get the element's offset position, corrected for `overflow: auto`.
  1405. *
  1406. * @function Highcharts.offset
  1407. *
  1408. * @param {global.Element} el
  1409. * The DOM element.
  1410. *
  1411. * @return {Highcharts.OffsetObject}
  1412. * An object containing `left` and `top` properties for the position in
  1413. * the page.
  1414. */
  1415. function offset(el) {
  1416. var docElem = doc.documentElement, box = (el.parentElement || el.parentNode) ?
  1417. el.getBoundingClientRect() :
  1418. { top: 0, left: 0, width: 0, height: 0 };
  1419. return {
  1420. top: box.top + (win.pageYOffset || docElem.scrollTop) -
  1421. (docElem.clientTop || 0),
  1422. left: box.left + (win.pageXOffset || docElem.scrollLeft) -
  1423. (docElem.clientLeft || 0),
  1424. width: box.width,
  1425. height: box.height
  1426. };
  1427. }
  1428. /* eslint-disable valid-jsdoc */
  1429. /**
  1430. * Iterate over object key pairs in an object.
  1431. *
  1432. * @function Highcharts.objectEach<T>
  1433. *
  1434. * @param {*} obj
  1435. * The object to iterate over.
  1436. *
  1437. * @param {Highcharts.ObjectEachCallbackFunction<T>} fn
  1438. * The iterator callback. It passes three arguments:
  1439. * * value - The property value.
  1440. * * key - The property key.
  1441. * * obj - The object that objectEach is being applied to.
  1442. *
  1443. * @param {T} [ctx]
  1444. * The context.
  1445. *
  1446. * @return {void}
  1447. */
  1448. function objectEach(obj, fn, ctx) {
  1449. /* eslint-enable valid-jsdoc */
  1450. for (var key in obj) {
  1451. if (Object.hasOwnProperty.call(obj, key)) {
  1452. fn.call(ctx || obj[key], obj[key], key, obj);
  1453. }
  1454. }
  1455. }
  1456. /**
  1457. * Iterate over an array.
  1458. *
  1459. * @deprecated
  1460. * @function Highcharts.each
  1461. *
  1462. * @param {Array<*>} arr
  1463. * The array to iterate over.
  1464. *
  1465. * @param {Function} fn
  1466. * The iterator callback. It passes three arguments:
  1467. * - `item`: The array item.
  1468. * - `index`: The item's index in the array.
  1469. * - `arr`: The array that each is being applied to.
  1470. *
  1471. * @param {*} [ctx]
  1472. * The context.
  1473. *
  1474. * @return {void}
  1475. */
  1476. /**
  1477. * Filter an array by a callback.
  1478. *
  1479. * @deprecated
  1480. * @function Highcharts.grep
  1481. *
  1482. * @param {Array<*>} arr
  1483. * The array to filter.
  1484. *
  1485. * @param {Function} callback
  1486. * The callback function. The function receives the item as the first
  1487. * argument. Return `true` if the item is to be preserved.
  1488. *
  1489. * @return {Array<*>}
  1490. * A new, filtered array.
  1491. */
  1492. /**
  1493. * Map an array by a callback.
  1494. *
  1495. * @deprecated
  1496. * @function Highcharts.map
  1497. *
  1498. * @param {Array<*>} arr
  1499. * The array to map.
  1500. *
  1501. * @param {Function} fn
  1502. * The callback function. Return the new value for the new array.
  1503. *
  1504. * @return {Array<*>}
  1505. * A new array item with modified items.
  1506. */
  1507. /**
  1508. * Reduce an array to a single value.
  1509. *
  1510. * @deprecated
  1511. * @function Highcharts.reduce
  1512. *
  1513. * @param {Array<*>} arr
  1514. * The array to reduce.
  1515. *
  1516. * @param {Function} fn
  1517. * The callback function. Return the reduced value. Receives 4
  1518. * arguments: Accumulated/reduced value, current value, current array
  1519. * index, and the array.
  1520. *
  1521. * @param {*} initialValue
  1522. * The initial value of the accumulator.
  1523. *
  1524. * @return {*}
  1525. * The reduced value.
  1526. */
  1527. /**
  1528. * Test whether at least one element in the array passes the test implemented by
  1529. * the provided function.
  1530. *
  1531. * @deprecated
  1532. * @function Highcharts.some
  1533. *
  1534. * @param {Array<*>} arr
  1535. * The array to test
  1536. *
  1537. * @param {Function} fn
  1538. * The function to run on each item. Return truty to pass the test.
  1539. * Receives arguments `currentValue`, `index` and `array`.
  1540. *
  1541. * @param {*} ctx
  1542. * The context.
  1543. *
  1544. * @return {boolean}
  1545. */
  1546. objectEach({
  1547. map: 'map',
  1548. each: 'forEach',
  1549. grep: 'filter',
  1550. reduce: 'reduce',
  1551. some: 'some'
  1552. }, function (val, key) {
  1553. H[key] = function (arr) {
  1554. var _a;
  1555. error(32, false, void 0, (_a = {}, _a["Highcharts." + key] = "use Array." + val, _a));
  1556. return Array.prototype[val].apply(arr, [].slice.call(arguments, 1));
  1557. };
  1558. });
  1559. /* eslint-disable valid-jsdoc */
  1560. /**
  1561. * Add an event listener.
  1562. *
  1563. * @function Highcharts.addEvent<T>
  1564. *
  1565. * @param {Highcharts.Class<T>|T} el
  1566. * The element or object to add a listener to. It can be a
  1567. * {@link HTMLDOMElement}, an {@link SVGElement} or any other object.
  1568. *
  1569. * @param {string} type
  1570. * The event type.
  1571. *
  1572. * @param {Highcharts.EventCallbackFunction<T>|Function} fn
  1573. * The function callback to execute when the event is fired.
  1574. *
  1575. * @param {Highcharts.EventOptionsObject} [options]
  1576. * Options for adding the event.
  1577. *
  1578. * @return {Function}
  1579. * A callback function to remove the added event.
  1580. */
  1581. function addEvent(el, type, fn, options) {
  1582. /* eslint-enable valid-jsdoc */
  1583. if (options === void 0) { options = {}; }
  1584. // Add hcEvents to either the prototype (in case we're running addEvent on a
  1585. // class) or the instance. If hasOwnProperty('hcEvents') is false, it is
  1586. // inherited down the prototype chain, in which case we need to set the
  1587. // property on this instance (which may itself be a prototype).
  1588. var owner = typeof el === 'function' && el.prototype || el;
  1589. if (!Object.hasOwnProperty.call(owner, 'hcEvents')) {
  1590. owner.hcEvents = {};
  1591. }
  1592. var events = owner.hcEvents;
  1593. // Allow click events added to points, otherwise they will be prevented by
  1594. // the TouchPointer.pinch function after a pinch zoom operation (#7091).
  1595. if (H.Point && // without H a dependency loop occurs
  1596. el instanceof H.Point &&
  1597. el.series &&
  1598. el.series.chart) {
  1599. el.series.chart.runTrackerClick = true;
  1600. }
  1601. // Handle DOM events
  1602. // If the browser supports passive events, add it to improve performance
  1603. // on touch events (#11353).
  1604. var addEventListener = (el.addEventListener || H.addEventListenerPolyfill);
  1605. if (addEventListener) {
  1606. addEventListener.call(el, type, fn, H.supportsPassiveEvents ? {
  1607. passive: options.passive === void 0 ?
  1608. type.indexOf('touch') !== -1 : options.passive,
  1609. capture: false
  1610. } : false);
  1611. }
  1612. if (!events[type]) {
  1613. events[type] = [];
  1614. }
  1615. var eventObject = {
  1616. fn: fn,
  1617. order: typeof options.order === 'number' ? options.order : Infinity
  1618. };
  1619. events[type].push(eventObject);
  1620. // Order the calls
  1621. events[type].sort(function (a, b) { return a.order - b.order; });
  1622. // Return a function that can be called to remove this event.
  1623. return function () {
  1624. removeEvent(el, type, fn);
  1625. };
  1626. }
  1627. /* eslint-disable valid-jsdoc */
  1628. /**
  1629. * Remove an event that was added with {@link Highcharts#addEvent}.
  1630. *
  1631. * @function Highcharts.removeEvent<T>
  1632. *
  1633. * @param {Highcharts.Class<T>|T} el
  1634. * The element to remove events on.
  1635. *
  1636. * @param {string} [type]
  1637. * The type of events to remove. If undefined, all events are removed
  1638. * from the element.
  1639. *
  1640. * @param {Highcharts.EventCallbackFunction<T>} [fn]
  1641. * The specific callback to remove. If undefined, all events that match
  1642. * the element and optionally the type are removed.
  1643. *
  1644. * @return {void}
  1645. */
  1646. function removeEvent(el, type, fn) {
  1647. /* eslint-enable valid-jsdoc */
  1648. /**
  1649. * @private
  1650. * @param {string} type - event type
  1651. * @param {Highcharts.EventCallbackFunction<T>} fn - callback
  1652. * @return {void}
  1653. */
  1654. function removeOneEvent(type, fn) {
  1655. var removeEventListener = (el.removeEventListener || H.removeEventListenerPolyfill);
  1656. if (removeEventListener) {
  1657. removeEventListener.call(el, type, fn, false);
  1658. }
  1659. }
  1660. /**
  1661. * @private
  1662. * @param {any} eventCollection - collection
  1663. * @return {void}
  1664. */
  1665. function removeAllEvents(eventCollection) {
  1666. var types, len;
  1667. if (!el.nodeName) {
  1668. return; // break on non-DOM events
  1669. }
  1670. if (type) {
  1671. types = {};
  1672. types[type] = true;
  1673. }
  1674. else {
  1675. types = eventCollection;
  1676. }
  1677. objectEach(types, function (_val, n) {
  1678. if (eventCollection[n]) {
  1679. len = eventCollection[n].length;
  1680. while (len--) {
  1681. removeOneEvent(n, eventCollection[n][len].fn);
  1682. }
  1683. }
  1684. });
  1685. }
  1686. var owner = typeof el === 'function' && el.prototype || el;
  1687. if (Object.hasOwnProperty.call(owner, 'hcEvents')) {
  1688. var events = owner.hcEvents;
  1689. if (type) {
  1690. var typeEvents = (events[type] || []);
  1691. if (fn) {
  1692. events[type] = typeEvents.filter(function (obj) {
  1693. return fn !== obj.fn;
  1694. });
  1695. removeOneEvent(type, fn);
  1696. }
  1697. else {
  1698. removeAllEvents(events);
  1699. events[type] = [];
  1700. }
  1701. }
  1702. else {
  1703. removeAllEvents(events);
  1704. delete owner.hcEvents;
  1705. }
  1706. }
  1707. }
  1708. /* eslint-disable valid-jsdoc */
  1709. /**
  1710. * Fire an event that was registered with {@link Highcharts#addEvent}.
  1711. *
  1712. * @function Highcharts.fireEvent<T>
  1713. *
  1714. * @param {T} el
  1715. * The object to fire the event on. It can be a {@link HTMLDOMElement},
  1716. * an {@link SVGElement} or any other object.
  1717. *
  1718. * @param {string} type
  1719. * The type of event.
  1720. *
  1721. * @param {Highcharts.Dictionary<*>|Event} [eventArguments]
  1722. * Custom event arguments that are passed on as an argument to the event
  1723. * handler.
  1724. *
  1725. * @param {Highcharts.EventCallbackFunction<T>|Function} [defaultFunction]
  1726. * The default function to execute if the other listeners haven't
  1727. * returned false.
  1728. *
  1729. * @return {void}
  1730. */
  1731. function fireEvent(el, type, eventArguments, defaultFunction) {
  1732. /* eslint-enable valid-jsdoc */
  1733. var e, i;
  1734. eventArguments = eventArguments || {};
  1735. if (doc.createEvent &&
  1736. (el.dispatchEvent ||
  1737. (el.fireEvent &&
  1738. // Enable firing events on Highcharts instance.
  1739. el !== H))) {
  1740. e = doc.createEvent('Events');
  1741. e.initEvent(type, true, true);
  1742. eventArguments = extend(e, eventArguments);
  1743. if (el.dispatchEvent) {
  1744. el.dispatchEvent(eventArguments);
  1745. }
  1746. else {
  1747. el.fireEvent(type, eventArguments);
  1748. }
  1749. }
  1750. else if (el.hcEvents) {
  1751. if (!eventArguments.target) {
  1752. // We're running a custom event
  1753. extend(eventArguments, {
  1754. // Attach a simple preventDefault function to skip
  1755. // default handler if called. The built-in
  1756. // defaultPrevented property is not overwritable (#5112)
  1757. preventDefault: function () {
  1758. eventArguments.defaultPrevented = true;
  1759. },
  1760. // Setting target to native events fails with clicking
  1761. // the zoom-out button in Chrome.
  1762. target: el,
  1763. // If the type is not set, we're running a custom event
  1764. // (#2297). If it is set, we're running a browser event,
  1765. // and setting it will cause en error in IE8 (#2465).
  1766. type: type
  1767. });
  1768. }
  1769. var events = [];
  1770. var object = el;
  1771. var multilevel = false;
  1772. // Recurse up the inheritance chain and collect hcEvents set as own
  1773. // objects on the prototypes.
  1774. while (object.hcEvents) {
  1775. if (Object.hasOwnProperty.call(object, 'hcEvents') &&
  1776. object.hcEvents[type]) {
  1777. if (events.length) {
  1778. multilevel = true;
  1779. }
  1780. events.unshift.apply(events, object.hcEvents[type]);
  1781. }
  1782. object = Object.getPrototypeOf(object);
  1783. }
  1784. // For performance reasons, only sort the event handlers in case we are
  1785. // dealing with multiple levels in the prototype chain. Otherwise, the
  1786. // events are already sorted in the addEvent function.
  1787. if (multilevel) {
  1788. // Order the calls
  1789. events.sort(function (a, b) { return a.order - b.order; });
  1790. }
  1791. // Call the collected event handlers
  1792. events.forEach(function (obj) {
  1793. // If the event handler returns false, prevent the default handler
  1794. // from executing
  1795. if (obj.fn.call(el, eventArguments) === false) {
  1796. eventArguments.preventDefault();
  1797. }
  1798. });
  1799. }
  1800. // Run the default if not prevented
  1801. if (defaultFunction && !eventArguments.defaultPrevented) {
  1802. defaultFunction.call(el, eventArguments);
  1803. }
  1804. }
  1805. var serialMode;
  1806. /**
  1807. * Get a unique key for using in internal element id's and pointers. The key is
  1808. * composed of a random hash specific to this Highcharts instance, and a
  1809. * counter.
  1810. *
  1811. * @example
  1812. * let id = uniqueKey(); // => 'highcharts-x45f6hp-0'
  1813. *
  1814. * @function Highcharts.uniqueKey
  1815. *
  1816. * @return {string}
  1817. * A unique key.
  1818. */
  1819. var uniqueKey = (function () {
  1820. var hash = Math.random().toString(36).substring(2, 9) + '-';
  1821. var id = 0;
  1822. return function () {
  1823. return 'highcharts-' + (serialMode ? '' : hash) + id++;
  1824. };
  1825. }());
  1826. /**
  1827. * Activates a serial mode for element IDs provided by
  1828. * {@link Highcharts.uniqueKey}. This mode can be used in automated tests, where
  1829. * a simple comparison of two rendered SVG graphics is needed.
  1830. *
  1831. * **Note:** This is only for testing purposes and will break functionality in
  1832. * webpages with multiple charts.
  1833. *
  1834. * @example
  1835. * if (
  1836. * process &&
  1837. * process.env.NODE_ENV === 'development'
  1838. * ) {
  1839. * Highcharts.useSerialIds(true);
  1840. * }
  1841. *
  1842. * @function Highcharts.useSerialIds
  1843. *
  1844. * @param {boolean} [mode]
  1845. * Changes the state of serial mode.
  1846. *
  1847. * @return {boolean|undefined}
  1848. * State of the serial mode.
  1849. */
  1850. function useSerialIds(mode) {
  1851. return (serialMode = pick(mode, serialMode));
  1852. }
  1853. function isFunction(obj) {
  1854. return typeof obj === 'function';
  1855. }
  1856. // Register Highcharts as a plugin in jQuery
  1857. if (win.jQuery) {
  1858. /**
  1859. * Highcharts-extended JQuery.
  1860. *
  1861. * @external JQuery
  1862. */
  1863. /**
  1864. * Helper function to return the chart of the current JQuery selector
  1865. * element.
  1866. *
  1867. * @function external:JQuery#highcharts
  1868. *
  1869. * @return {Highcharts.Chart}
  1870. * The chart that is linked to the JQuery selector element.
  1871. */ /**
  1872. * Factory function to create a chart in the current JQuery selector
  1873. * element.
  1874. *
  1875. * @function external:JQuery#highcharts
  1876. *
  1877. * @param {'Chart'|'Map'|'StockChart'|string} [className]
  1878. * Name of the factory class in the Highcharts namespace.
  1879. *
  1880. * @param {Highcharts.Options} [options]
  1881. * The chart options structure.
  1882. *
  1883. * @param {Highcharts.ChartCallbackFunction} [callback]
  1884. * Function to run when the chart has loaded and and all external
  1885. * images are loaded. Defining a
  1886. * [chart.events.load](https://api.highcharts.com/highcharts/chart.events.load)
  1887. * handler is equivalent.
  1888. *
  1889. * @return {JQuery}
  1890. * The current JQuery selector.
  1891. */
  1892. win.jQuery.fn.highcharts = function () {
  1893. var args = [].slice.call(arguments);
  1894. if (this[0]) { // this[0] is the renderTo div
  1895. // Create the chart
  1896. if (args[0]) {
  1897. new H[ // eslint-disable-line computed-property-spacing, no-new
  1898. // Constructor defaults to Chart
  1899. isString(args[0]) ? args.shift() : 'Chart'](this[0], args[0], args[1]);
  1900. return this;
  1901. }
  1902. // When called without parameters or with the return argument,
  1903. // return an existing chart
  1904. return charts[attr(this[0], 'data-highcharts-chart')];
  1905. }
  1906. };
  1907. }
  1908. // TODO use named exports when supported.
  1909. var utilitiesModule = {
  1910. addEvent: addEvent,
  1911. arrayMax: arrayMax,
  1912. arrayMin: arrayMin,
  1913. attr: attr,
  1914. clamp: clamp,
  1915. cleanRecursively: cleanRecursively,
  1916. clearTimeout: internalClearTimeout,
  1917. correctFloat: correctFloat,
  1918. createElement: createElement,
  1919. css: css,
  1920. defined: defined,
  1921. destroyObjectProperties: destroyObjectProperties,
  1922. discardElement: discardElement,
  1923. erase: erase,
  1924. error: error,
  1925. extend: extend,
  1926. extendClass: extendClass,
  1927. find: find,
  1928. fireEvent: fireEvent,
  1929. getMagnitude: getMagnitude,
  1930. getNestedProperty: getNestedProperty,
  1931. getStyle: getStyle,
  1932. inArray: inArray,
  1933. isArray: isArray,
  1934. isClass: isClass,
  1935. isDOMElement: isDOMElement,
  1936. isFunction: isFunction,
  1937. isNumber: isNumber,
  1938. isObject: isObject,
  1939. isString: isString,
  1940. keys: keys,
  1941. merge: merge,
  1942. normalizeTickInterval: normalizeTickInterval,
  1943. objectEach: objectEach,
  1944. offset: offset,
  1945. pad: pad,
  1946. pick: pick,
  1947. pInt: pInt,
  1948. relativeLength: relativeLength,
  1949. removeEvent: removeEvent,
  1950. splat: splat,
  1951. stableSort: stableSort,
  1952. syncTimeout: syncTimeout,
  1953. timeUnits: timeUnits,
  1954. uniqueKey: uniqueKey,
  1955. useSerialIds: useSerialIds,
  1956. wrap: wrap
  1957. };
  1958. export default utilitiesModule;