Utilities.js 62 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152
  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 `Record<string, any>` 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. * var 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.
  357. *
  358. * @param {Highcharts.Dictionary<string>} [params]
  359. * Additional parameters for the generated message.
  360. *
  361. * @return {void}
  362. */
  363. function error(code, stop, chart, params) {
  364. var severity = stop ? 'Highcharts error' : 'Highcharts warning';
  365. if (code === 32) {
  366. code = severity + ": Deprecated member";
  367. }
  368. var isCode = isNumber(code), message = isCode ?
  369. severity + " #" + code + ": www.highcharts.com/errors/" + code + "/" :
  370. code.toString(), defaultHandler = function () {
  371. if (stop) {
  372. throw new Error(message);
  373. }
  374. // else ...
  375. if (win.console &&
  376. error.messages.indexOf(message) === -1 // prevent console flooting
  377. ) {
  378. console.warn(message); // eslint-disable-line no-console
  379. }
  380. };
  381. if (typeof params !== 'undefined') {
  382. var additionalMessages_1 = '';
  383. if (isCode) {
  384. message += '?';
  385. }
  386. objectEach(params, function (value, key) {
  387. additionalMessages_1 += "\n - " + key + ": " + value;
  388. if (isCode) {
  389. message += encodeURI(key) + '=' + encodeURI(value);
  390. }
  391. });
  392. message += additionalMessages_1;
  393. }
  394. if (chart) {
  395. fireEvent(chart, 'displayError', { code: code, message: message, params: params }, defaultHandler);
  396. }
  397. else {
  398. defaultHandler();
  399. }
  400. error.messages.push(message);
  401. }
  402. (function (error) {
  403. error.messages = [];
  404. })(error || (error = {}));
  405. /* eslint-disable valid-jsdoc */
  406. /**
  407. * Utility function to deep merge two or more objects and return a third object.
  408. * If the first argument is true, the contents of the second object is copied
  409. * into the first object. The merge function can also be used with a single
  410. * object argument to create a deep copy of an object.
  411. *
  412. * @function Highcharts.merge<T>
  413. *
  414. * @param {boolean} extend
  415. * Whether to extend the left-side object (a) or return a whole new
  416. * object.
  417. *
  418. * @param {T|undefined} a
  419. * The first object to extend. When only this is given, the function
  420. * returns a deep copy.
  421. *
  422. * @param {...Array<object|undefined>} [n]
  423. * An object to merge into the previous one.
  424. *
  425. * @return {T}
  426. * The merged object. If the first argument is true, the return is the
  427. * same as the second argument.
  428. */ /**
  429. * Utility function to deep merge two or more objects and return a third object.
  430. * The merge function can also be used with a single object argument to create a
  431. * deep copy of an object.
  432. *
  433. * @function Highcharts.merge<T>
  434. *
  435. * @param {T|undefined} a
  436. * The first object to extend. When only this is given, the function
  437. * returns a deep copy.
  438. *
  439. * @param {...Array<object|undefined>} [n]
  440. * An object to merge into the previous one.
  441. *
  442. * @return {T}
  443. * The merged object. If the first argument is true, the return is the
  444. * same as the second argument.
  445. */
  446. function merge() {
  447. /* eslint-enable valid-jsdoc */
  448. var i, args = arguments, len, ret = {}, doCopy = function (copy, original) {
  449. // An object is replacing a primitive
  450. if (typeof copy !== 'object') {
  451. copy = {};
  452. }
  453. objectEach(original, function (value, key) {
  454. // Prototype pollution (#14883)
  455. if (key === '__proto__' || key === 'constructor') {
  456. return;
  457. }
  458. // Copy the contents of objects, but not arrays or DOM nodes
  459. if (isObject(value, true) &&
  460. !isClass(value) &&
  461. !isDOMElement(value)) {
  462. copy[key] = doCopy(copy[key] || {}, value);
  463. // Primitives and arrays are copied over directly
  464. }
  465. else {
  466. copy[key] = original[key];
  467. }
  468. });
  469. return copy;
  470. };
  471. // If first argument is true, copy into the existing object. Used in
  472. // setOptions.
  473. if (args[0] === true) {
  474. ret = args[1];
  475. args = Array.prototype.slice.call(args, 2);
  476. }
  477. // For each argument, extend the return
  478. len = args.length;
  479. for (i = 0; i < len; i++) {
  480. ret = doCopy(ret, args[i]);
  481. }
  482. return ret;
  483. }
  484. /**
  485. * Constrain a value to within a lower and upper threshold.
  486. *
  487. * @private
  488. * @param {number} value The initial value
  489. * @param {number} min The lower threshold
  490. * @param {number} max The upper threshold
  491. * @return {number} Returns a number value within min and max.
  492. */
  493. function clamp(value, min, max) {
  494. return value > min ? value < max ? value : max : min;
  495. }
  496. // eslint-disable-next-line valid-jsdoc
  497. /**
  498. * Remove settings that have not changed, to avoid unnecessary rendering or
  499. * computing (#9197).
  500. * @private
  501. */
  502. function cleanRecursively(newer, older) {
  503. var result = {};
  504. objectEach(newer, function (_val, key) {
  505. var ob;
  506. // Dive into objects (except DOM nodes)
  507. if (isObject(newer[key], true) &&
  508. !newer.nodeType && // #10044
  509. older[key]) {
  510. ob = cleanRecursively(newer[key], older[key]);
  511. if (Object.keys(ob).length) {
  512. result[key] = ob;
  513. }
  514. // Arrays, primitives and DOM nodes are copied directly
  515. }
  516. else if (isObject(newer[key]) ||
  517. newer[key] !== older[key]) {
  518. result[key] = newer[key];
  519. }
  520. });
  521. return result;
  522. }
  523. /**
  524. * Shortcut for parseInt
  525. *
  526. * @private
  527. * @function Highcharts.pInt
  528. *
  529. * @param {*} s
  530. * any
  531. *
  532. * @param {number} [mag]
  533. * Magnitude
  534. *
  535. * @return {number}
  536. * number
  537. */
  538. function pInt(s, mag) {
  539. return parseInt(s, mag || 10);
  540. }
  541. /**
  542. * Utility function to check for string type.
  543. *
  544. * @function Highcharts.isString
  545. *
  546. * @param {*} s
  547. * The item to check.
  548. *
  549. * @return {boolean}
  550. * True if the argument is a string.
  551. */
  552. function isString(s) {
  553. return typeof s === 'string';
  554. }
  555. /**
  556. * Utility function to check if an item is an array.
  557. *
  558. * @function Highcharts.isArray
  559. *
  560. * @param {*} obj
  561. * The item to check.
  562. *
  563. * @return {boolean}
  564. * True if the argument is an array.
  565. */
  566. function isArray(obj) {
  567. var str = Object.prototype.toString.call(obj);
  568. return str === '[object Array]' || str === '[object Array Iterator]';
  569. }
  570. /**
  571. * Utility function to check if an item is of type object.
  572. *
  573. * @function Highcharts.isObject
  574. *
  575. * @param {*} obj
  576. * The item to check.
  577. *
  578. * @param {boolean} [strict=false]
  579. * Also checks that the object is not an array.
  580. *
  581. * @return {boolean}
  582. * True if the argument is an object.
  583. */
  584. function isObject(obj, strict) {
  585. return (!!obj &&
  586. typeof obj === 'object' &&
  587. (!strict || !isArray(obj))); // eslint-disable-line @typescript-eslint/no-explicit-any
  588. }
  589. /**
  590. * Utility function to check if an Object is a HTML Element.
  591. *
  592. * @function Highcharts.isDOMElement
  593. *
  594. * @param {*} obj
  595. * The item to check.
  596. *
  597. * @return {boolean}
  598. * True if the argument is a HTML Element.
  599. */
  600. function isDOMElement(obj) {
  601. return isObject(obj) && typeof obj.nodeType === 'number';
  602. }
  603. /**
  604. * Utility function to check if an Object is a class.
  605. *
  606. * @function Highcharts.isClass
  607. *
  608. * @param {object|undefined} obj
  609. * The item to check.
  610. *
  611. * @return {boolean}
  612. * True if the argument is a class.
  613. */
  614. function isClass(obj) {
  615. var c = obj && obj.constructor;
  616. return !!(isObject(obj, true) &&
  617. !isDOMElement(obj) &&
  618. (c && c.name && c.name !== 'Object'));
  619. }
  620. /**
  621. * Utility function to check if an item is a number and it is finite (not NaN,
  622. * Infinity or -Infinity).
  623. *
  624. * @function Highcharts.isNumber
  625. *
  626. * @param {*} n
  627. * The item to check.
  628. *
  629. * @return {boolean}
  630. * True if the item is a finite number
  631. */
  632. function isNumber(n) {
  633. return typeof n === 'number' && !isNaN(n) && n < Infinity && n > -Infinity;
  634. }
  635. /**
  636. * Remove the last occurence of an item from an array.
  637. *
  638. * @function Highcharts.erase
  639. *
  640. * @param {Array<*>} arr
  641. * The array.
  642. *
  643. * @param {*} item
  644. * The item to remove.
  645. *
  646. * @return {void}
  647. */
  648. function erase(arr, item) {
  649. var i = arr.length;
  650. while (i--) {
  651. if (arr[i] === item) {
  652. arr.splice(i, 1);
  653. break;
  654. }
  655. }
  656. }
  657. /**
  658. * Check if an object is null or undefined.
  659. *
  660. * @function Highcharts.defined
  661. *
  662. * @param {*} obj
  663. * The object to check.
  664. *
  665. * @return {boolean}
  666. * False if the object is null or undefined, otherwise true.
  667. */
  668. function defined(obj) {
  669. return typeof obj !== 'undefined' && obj !== null;
  670. }
  671. /**
  672. * Set or get an attribute or an object of attributes. To use as a setter, pass
  673. * a key and a value, or let the second argument be a collection of keys and
  674. * values. To use as a getter, pass only a string as the second argument.
  675. *
  676. * @function Highcharts.attr
  677. *
  678. * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} elem
  679. * The DOM element to receive the attribute(s).
  680. *
  681. * @param {string|Highcharts.HTMLAttributes|Highcharts.SVGAttributes} [prop]
  682. * The property or an object of key-value pairs.
  683. *
  684. * @param {number|string} [value]
  685. * The value if a single property is set.
  686. *
  687. * @return {string|null|undefined}
  688. * When used as a getter, return the value.
  689. */
  690. function attr(elem, prop, value) {
  691. var ret;
  692. // if the prop is a string
  693. if (isString(prop)) {
  694. // set the value
  695. if (defined(value)) {
  696. elem.setAttribute(prop, value);
  697. // get the value
  698. }
  699. else if (elem && elem.getAttribute) {
  700. ret = elem.getAttribute(prop);
  701. // IE7 and below cannot get class through getAttribute (#7850)
  702. if (!ret && prop === 'class') {
  703. ret = elem.getAttribute(prop + 'Name');
  704. }
  705. }
  706. // else if prop is defined, it is a hash of key/value pairs
  707. }
  708. else {
  709. objectEach(prop, function (val, key) {
  710. elem.setAttribute(key, val);
  711. });
  712. }
  713. return ret;
  714. }
  715. /**
  716. * Check if an element is an array, and if not, make it into an array.
  717. *
  718. * @function Highcharts.splat
  719. *
  720. * @param {*} obj
  721. * The object to splat.
  722. *
  723. * @return {Array}
  724. * The produced or original array.
  725. */
  726. function splat(obj) {
  727. return isArray(obj) ? obj : [obj];
  728. }
  729. /**
  730. * Set a timeout if the delay is given, otherwise perform the function
  731. * synchronously.
  732. *
  733. * @function Highcharts.syncTimeout
  734. *
  735. * @param {Function} fn
  736. * The function callback.
  737. *
  738. * @param {number} delay
  739. * Delay in milliseconds.
  740. *
  741. * @param {*} [context]
  742. * An optional context to send to the function callback.
  743. *
  744. * @return {number}
  745. * An identifier for the timeout that can later be cleared with
  746. * Highcharts.clearTimeout. Returns -1 if there is no timeout.
  747. */
  748. function syncTimeout(fn, delay, context) {
  749. if (delay > 0) {
  750. return setTimeout(fn, delay, context);
  751. }
  752. fn.call(0, context);
  753. return -1;
  754. }
  755. /**
  756. * Internal clear timeout. The function checks that the `id` was not removed
  757. * (e.g. by `chart.destroy()`). For the details see
  758. * [issue #7901](https://github.com/highcharts/highcharts/issues/7901).
  759. *
  760. * @function Highcharts.clearTimeout
  761. *
  762. * @param {number} id
  763. * Id of a timeout.
  764. *
  765. * @return {void}
  766. */
  767. function internalClearTimeout(id) {
  768. if (defined(id)) {
  769. clearTimeout(id);
  770. }
  771. }
  772. /* eslint-disable valid-jsdoc */
  773. /**
  774. * Utility function to extend an object with the members of another.
  775. *
  776. * @function Highcharts.extend<T>
  777. *
  778. * @param {T|undefined} a
  779. * The object to be extended.
  780. *
  781. * @param {object} b
  782. * The object to add to the first one.
  783. *
  784. * @return {T}
  785. * Object a, the original object.
  786. */
  787. function extend(a, b) {
  788. /* eslint-enable valid-jsdoc */
  789. var n;
  790. if (!a) {
  791. a = {};
  792. }
  793. for (n in b) { // eslint-disable-line guard-for-in
  794. a[n] = b[n];
  795. }
  796. return a;
  797. }
  798. /* eslint-disable valid-jsdoc */
  799. /**
  800. * Return the first value that is not null or undefined.
  801. *
  802. * @function Highcharts.pick<T>
  803. *
  804. * @param {...Array<T|null|undefined>} items
  805. * Variable number of arguments to inspect.
  806. *
  807. * @return {T}
  808. * The value of the first argument that is not null or undefined.
  809. */
  810. function pick() {
  811. var args = arguments;
  812. var length = args.length;
  813. for (var i = 0; i < length; i++) {
  814. var arg = args[i];
  815. if (typeof arg !== 'undefined' && arg !== null) {
  816. return arg;
  817. }
  818. }
  819. }
  820. /**
  821. * Set CSS on a given element.
  822. *
  823. * @function Highcharts.css
  824. *
  825. * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} el
  826. * An HTML DOM element.
  827. *
  828. * @param {Highcharts.CSSObject} styles
  829. * Style object with camel case property names.
  830. *
  831. * @return {void}
  832. */
  833. function css(el, styles) {
  834. if (H.isMS && !H.svg) { // #2686
  835. if (styles && typeof styles.opacity !== 'undefined') {
  836. styles.filter =
  837. 'alpha(opacity=' + (styles.opacity * 100) + ')';
  838. }
  839. }
  840. extend(el.style, styles);
  841. }
  842. /**
  843. * Utility function to create an HTML element with attributes and styles.
  844. *
  845. * @function Highcharts.createElement
  846. *
  847. * @param {string} tag
  848. * The HTML tag.
  849. *
  850. * @param {Highcharts.HTMLAttributes} [attribs]
  851. * Attributes as an object of key-value pairs.
  852. *
  853. * @param {Highcharts.CSSObject} [styles]
  854. * Styles as an object of key-value pairs.
  855. *
  856. * @param {Highcharts.HTMLDOMElement} [parent]
  857. * The parent HTML object.
  858. *
  859. * @param {boolean} [nopad=false]
  860. * If true, remove all padding, border and margin.
  861. *
  862. * @return {Highcharts.HTMLDOMElement}
  863. * The created DOM element.
  864. */
  865. function createElement(tag, attribs, styles, parent, nopad) {
  866. var el = doc.createElement(tag);
  867. if (attribs) {
  868. extend(el, attribs);
  869. }
  870. if (nopad) {
  871. css(el, { padding: '0', border: 'none', margin: '0' });
  872. }
  873. if (styles) {
  874. css(el, styles);
  875. }
  876. if (parent) {
  877. parent.appendChild(el);
  878. }
  879. return el;
  880. }
  881. // eslint-disable-next-line valid-jsdoc
  882. /**
  883. * Extend a prototyped class by new members.
  884. *
  885. * @function Highcharts.extendClass<T>
  886. *
  887. * @param {Highcharts.Class<T>} parent
  888. * The parent prototype to inherit.
  889. *
  890. * @param {Highcharts.Dictionary<*>} members
  891. * A collection of prototype members to add or override compared to the
  892. * parent prototype.
  893. *
  894. * @return {Highcharts.Class<T>}
  895. * A new prototype.
  896. */
  897. function extendClass(parent, members) {
  898. var obj = (function () { });
  899. obj.prototype = new parent(); // eslint-disable-line new-cap
  900. extend(obj.prototype, members);
  901. return obj;
  902. }
  903. /**
  904. * Left-pad a string to a given length by adding a character repetetively.
  905. *
  906. * @function Highcharts.pad
  907. *
  908. * @param {number} number
  909. * The input string or number.
  910. *
  911. * @param {number} [length]
  912. * The desired string length.
  913. *
  914. * @param {string} [padder=0]
  915. * The character to pad with.
  916. *
  917. * @return {string}
  918. * The padded string.
  919. */
  920. function pad(number, length, padder) {
  921. return new Array((length || 2) +
  922. 1 -
  923. String(number)
  924. .replace('-', '')
  925. .length).join(padder || '0') + number;
  926. }
  927. /**
  928. * Return a length based on either the integer value, or a percentage of a base.
  929. *
  930. * @function Highcharts.relativeLength
  931. *
  932. * @param {Highcharts.RelativeSize} value
  933. * A percentage string or a number.
  934. *
  935. * @param {number} base
  936. * The full length that represents 100%.
  937. *
  938. * @param {number} [offset=0]
  939. * A pixel offset to apply for percentage values. Used internally in
  940. * axis positioning.
  941. *
  942. * @return {number}
  943. * The computed length.
  944. */
  945. function relativeLength(value, base, offset) {
  946. return (/%$/).test(value) ?
  947. (base * parseFloat(value) / 100) + (offset || 0) :
  948. parseFloat(value);
  949. }
  950. /**
  951. * Wrap a method with extended functionality, preserving the original function.
  952. *
  953. * @function Highcharts.wrap
  954. *
  955. * @param {*} obj
  956. * The context object that the method belongs to. In real cases, this is
  957. * often a prototype.
  958. *
  959. * @param {string} method
  960. * The name of the method to extend.
  961. *
  962. * @param {Highcharts.WrapProceedFunction} func
  963. * A wrapper function callback. This function is called with the same
  964. * arguments as the original function, except that the original function
  965. * is unshifted and passed as the first argument.
  966. */
  967. function wrap(obj, method, func) {
  968. var proceed = obj[method];
  969. obj[method] = function () {
  970. var args = Array.prototype.slice.call(arguments), outerArgs = arguments, ctx = this, ret;
  971. ctx.proceed = function () {
  972. proceed.apply(ctx, arguments.length ? arguments : outerArgs);
  973. };
  974. args.unshift(proceed);
  975. ret = func.apply(this, args);
  976. ctx.proceed = null;
  977. return ret;
  978. };
  979. }
  980. /**
  981. * Format a string according to a subset of the rules of Python's String.format
  982. * method.
  983. *
  984. * @example
  985. * var s = Highcharts.format(
  986. * 'The {color} fox was {len:.2f} feet long',
  987. * { color: 'red', len: Math.PI }
  988. * );
  989. * // => The red fox was 3.14 feet long
  990. *
  991. * @function Highcharts.format
  992. *
  993. * @param {string} str
  994. * The string to format.
  995. *
  996. * @param {Record<string, *>} ctx
  997. * The context, a collection of key-value pairs where each key is
  998. * replaced by its value.
  999. *
  1000. * @param {Highcharts.Chart} [chart]
  1001. * A `Chart` instance used to get numberFormatter and time.
  1002. *
  1003. * @return {string}
  1004. * The formatted string.
  1005. */
  1006. function format(str, ctx, chart) {
  1007. var splitter = '{', isInside = false, segment, valueAndFormat, ret = [], val, index;
  1008. var floatRegex = /f$/;
  1009. var decRegex = /\.([0-9])/;
  1010. var lang = H.defaultOptions.lang;
  1011. var time = chart && chart.time || H.time;
  1012. var numberFormatter = chart && chart.numberFormatter || numberFormat;
  1013. while (str) {
  1014. index = str.indexOf(splitter);
  1015. if (index === -1) {
  1016. break;
  1017. }
  1018. segment = str.slice(0, index);
  1019. if (isInside) { // we're on the closing bracket looking back
  1020. valueAndFormat = segment.split(':');
  1021. val = getNestedProperty(valueAndFormat.shift() || '', ctx);
  1022. // Format the replacement
  1023. if (valueAndFormat.length && typeof val === 'number') {
  1024. segment = valueAndFormat.join(':');
  1025. if (floatRegex.test(segment)) { // float
  1026. var decimals = parseInt((segment.match(decRegex) || ['', '-1'])[1], 10);
  1027. if (val !== null) {
  1028. val = numberFormatter(val, decimals, lang.decimalPoint, segment.indexOf(',') > -1 ? lang.thousandsSep : '');
  1029. }
  1030. }
  1031. else {
  1032. val = time.dateFormat(segment, val);
  1033. }
  1034. }
  1035. // Push the result and advance the cursor
  1036. ret.push(val);
  1037. }
  1038. else {
  1039. ret.push(segment);
  1040. }
  1041. str = str.slice(index + 1); // the rest
  1042. isInside = !isInside; // toggle
  1043. splitter = isInside ? '}' : '{'; // now look for next matching bracket
  1044. }
  1045. ret.push(str);
  1046. return ret.join('');
  1047. }
  1048. /**
  1049. * Get the magnitude of a number.
  1050. *
  1051. * @function Highcharts.getMagnitude
  1052. *
  1053. * @param {number} num
  1054. * The number.
  1055. *
  1056. * @return {number}
  1057. * The magnitude, where 1-9 are magnitude 1, 10-99 magnitude 2 etc.
  1058. */
  1059. function getMagnitude(num) {
  1060. return Math.pow(10, Math.floor(Math.log(num) / Math.LN10));
  1061. }
  1062. /**
  1063. * Take an interval and normalize it to multiples of round numbers.
  1064. *
  1065. * @deprecated
  1066. * @function Highcharts.normalizeTickInterval
  1067. *
  1068. * @param {number} interval
  1069. * The raw, un-rounded interval.
  1070. *
  1071. * @param {Array<*>} [multiples]
  1072. * Allowed multiples.
  1073. *
  1074. * @param {number} [magnitude]
  1075. * The magnitude of the number.
  1076. *
  1077. * @param {boolean} [allowDecimals]
  1078. * Whether to allow decimals.
  1079. *
  1080. * @param {boolean} [hasTickAmount]
  1081. * If it has tickAmount, avoid landing on tick intervals lower than
  1082. * original.
  1083. *
  1084. * @return {number}
  1085. * The normalized interval.
  1086. *
  1087. * @todo
  1088. * Move this function to the Axis prototype. It is here only for historical
  1089. * reasons.
  1090. */
  1091. function normalizeTickInterval(interval, multiples, magnitude, allowDecimals, hasTickAmount) {
  1092. var normalized, i, retInterval = interval;
  1093. // round to a tenfold of 1, 2, 2.5 or 5
  1094. magnitude = pick(magnitude, 1);
  1095. normalized = interval / magnitude;
  1096. // multiples for a linear scale
  1097. if (!multiples) {
  1098. multiples = hasTickAmount ?
  1099. // Finer grained ticks when the tick amount is hard set, including
  1100. // when alignTicks is true on multiple axes (#4580).
  1101. [1, 1.2, 1.5, 2, 2.5, 3, 4, 5, 6, 8, 10] :
  1102. // Else, let ticks fall on rounder numbers
  1103. [1, 2, 2.5, 5, 10];
  1104. // the allowDecimals option
  1105. if (allowDecimals === false) {
  1106. if (magnitude === 1) {
  1107. multiples = multiples.filter(function (num) {
  1108. return num % 1 === 0;
  1109. });
  1110. }
  1111. else if (magnitude <= 0.1) {
  1112. multiples = [1 / magnitude];
  1113. }
  1114. }
  1115. }
  1116. // normalize the interval to the nearest multiple
  1117. for (i = 0; i < multiples.length; i++) {
  1118. retInterval = multiples[i];
  1119. // only allow tick amounts smaller than natural
  1120. if ((hasTickAmount &&
  1121. retInterval * magnitude >= interval) ||
  1122. (!hasTickAmount &&
  1123. (normalized <=
  1124. (multiples[i] +
  1125. (multiples[i + 1] || multiples[i])) / 2))) {
  1126. break;
  1127. }
  1128. }
  1129. // Multiply back to the correct magnitude. Correct floats to appropriate
  1130. // precision (#6085).
  1131. retInterval = correctFloat(retInterval * magnitude, -Math.round(Math.log(0.001) / Math.LN10));
  1132. return retInterval;
  1133. }
  1134. /**
  1135. * Sort an object array and keep the order of equal items. The ECMAScript
  1136. * standard does not specify the behaviour when items are equal.
  1137. *
  1138. * @function Highcharts.stableSort
  1139. *
  1140. * @param {Array<*>} arr
  1141. * The array to sort.
  1142. *
  1143. * @param {Function} sortFunction
  1144. * The function to sort it with, like with regular Array.prototype.sort.
  1145. *
  1146. * @return {void}
  1147. */
  1148. function stableSort(arr, sortFunction) {
  1149. // @todo It seems like Chrome since v70 sorts in a stable way internally,
  1150. // plus all other browsers do it, so over time we may be able to remove this
  1151. // function
  1152. var length = arr.length, sortValue, i;
  1153. // Add index to each item
  1154. for (i = 0; i < length; i++) {
  1155. arr[i].safeI = i; // stable sort index
  1156. }
  1157. arr.sort(function (a, b) {
  1158. sortValue = sortFunction(a, b);
  1159. return sortValue === 0 ? a.safeI - b.safeI : sortValue;
  1160. });
  1161. // Remove index from items
  1162. for (i = 0; i < length; i++) {
  1163. delete arr[i].safeI; // stable sort index
  1164. }
  1165. }
  1166. /**
  1167. * Non-recursive method to find the lowest member of an array. `Math.min` raises
  1168. * a maximum call stack size exceeded error in Chrome when trying to apply more
  1169. * than 150.000 points. This method is slightly slower, but safe.
  1170. *
  1171. * @function Highcharts.arrayMin
  1172. *
  1173. * @param {Array<*>} data
  1174. * An array of numbers.
  1175. *
  1176. * @return {number}
  1177. * The lowest number.
  1178. */
  1179. function arrayMin(data) {
  1180. var i = data.length, min = data[0];
  1181. while (i--) {
  1182. if (data[i] < min) {
  1183. min = data[i];
  1184. }
  1185. }
  1186. return min;
  1187. }
  1188. /**
  1189. * Non-recursive method to find the lowest member of an array. `Math.max` raises
  1190. * a maximum call stack size exceeded error in Chrome when trying to apply more
  1191. * than 150.000 points. This method is slightly slower, but safe.
  1192. *
  1193. * @function Highcharts.arrayMax
  1194. *
  1195. * @param {Array<*>} data
  1196. * An array of numbers.
  1197. *
  1198. * @return {number}
  1199. * The highest number.
  1200. */
  1201. function arrayMax(data) {
  1202. var i = data.length, max = data[0];
  1203. while (i--) {
  1204. if (data[i] > max) {
  1205. max = data[i];
  1206. }
  1207. }
  1208. return max;
  1209. }
  1210. /**
  1211. * Utility method that destroys any SVGElement instances that are properties on
  1212. * the given object. It loops all properties and invokes destroy if there is a
  1213. * destroy method. The property is then delete.
  1214. *
  1215. * @function Highcharts.destroyObjectProperties
  1216. *
  1217. * @param {*} obj
  1218. * The object to destroy properties on.
  1219. *
  1220. * @param {*} [except]
  1221. * Exception, do not destroy this property, only delete it.
  1222. */
  1223. function destroyObjectProperties(obj, except) {
  1224. objectEach(obj, function (val, n) {
  1225. // If the object is non-null and destroy is defined
  1226. if (val && val !== except && val.destroy) {
  1227. // Invoke the destroy
  1228. val.destroy();
  1229. }
  1230. // Delete the property from the object.
  1231. delete obj[n];
  1232. });
  1233. }
  1234. /**
  1235. * Discard a HTML element by moving it to the bin and delete.
  1236. *
  1237. * @function Highcharts.discardElement
  1238. *
  1239. * @param {Highcharts.HTMLDOMElement} element
  1240. * The HTML node to discard.
  1241. */
  1242. function discardElement(element) {
  1243. // create a garbage bin element, not part of the DOM
  1244. if (!garbageBin) {
  1245. garbageBin = createElement('div');
  1246. }
  1247. // move the node and empty bin
  1248. if (element) {
  1249. garbageBin.appendChild(element);
  1250. }
  1251. garbageBin.innerHTML = '';
  1252. }
  1253. var garbageBin;
  1254. /**
  1255. * Fix JS round off float errors.
  1256. *
  1257. * @function Highcharts.correctFloat
  1258. *
  1259. * @param {number} num
  1260. * A float number to fix.
  1261. *
  1262. * @param {number} [prec=14]
  1263. * The precision.
  1264. *
  1265. * @return {number}
  1266. * The corrected float number.
  1267. */
  1268. function correctFloat(num, prec) {
  1269. return parseFloat(num.toPrecision(prec || 14));
  1270. }
  1271. /**
  1272. * The time unit lookup
  1273. *
  1274. * @ignore
  1275. */
  1276. var timeUnits = {
  1277. millisecond: 1,
  1278. second: 1000,
  1279. minute: 60000,
  1280. hour: 3600000,
  1281. day: 24 * 3600000,
  1282. week: 7 * 24 * 3600000,
  1283. month: 28 * 24 * 3600000,
  1284. year: 364 * 24 * 3600000
  1285. };
  1286. /**
  1287. * Format a number and return a string based on input settings.
  1288. *
  1289. * @sample highcharts/members/highcharts-numberformat/
  1290. * Custom number format
  1291. *
  1292. * @function Highcharts.numberFormat
  1293. *
  1294. * @param {number} number
  1295. * The input number to format.
  1296. *
  1297. * @param {number} decimals
  1298. * The amount of decimals. A value of -1 preserves the amount in the
  1299. * input number.
  1300. *
  1301. * @param {string} [decimalPoint]
  1302. * The decimal point, defaults to the one given in the lang options, or
  1303. * a dot.
  1304. *
  1305. * @param {string} [thousandsSep]
  1306. * The thousands separator, defaults to the one given in the lang
  1307. * options, or a space character.
  1308. *
  1309. * @return {string}
  1310. * The formatted number.
  1311. */
  1312. function numberFormat(number, decimals, decimalPoint, thousandsSep) {
  1313. number = +number || 0;
  1314. decimals = +decimals;
  1315. var lang = H.defaultOptions.lang, origDec = (number.toString().split('.')[1] || '').split('e')[0].length, strinteger, thousands, ret, roundedNumber, exponent = number.toString().split('e'), fractionDigits, firstDecimals = decimals;
  1316. if (decimals === -1) {
  1317. // Preserve decimals. Not huge numbers (#3793).
  1318. decimals = Math.min(origDec, 20);
  1319. }
  1320. else if (!isNumber(decimals)) {
  1321. decimals = 2;
  1322. }
  1323. else if (decimals && exponent[1] && exponent[1] < 0) {
  1324. // Expose decimals from exponential notation (#7042)
  1325. fractionDigits = decimals + +exponent[1];
  1326. if (fractionDigits >= 0) {
  1327. // remove too small part of the number while keeping the notation
  1328. exponent[0] = (+exponent[0]).toExponential(fractionDigits)
  1329. .split('e')[0];
  1330. decimals = fractionDigits;
  1331. }
  1332. else {
  1333. // fractionDigits < 0
  1334. exponent[0] = exponent[0].split('.')[0] || 0;
  1335. if (decimals < 20) {
  1336. // use number instead of exponential notation (#7405)
  1337. number = (exponent[0] * Math.pow(10, exponent[1]))
  1338. .toFixed(decimals);
  1339. }
  1340. else {
  1341. // or zero
  1342. number = 0;
  1343. }
  1344. exponent[1] = 0;
  1345. }
  1346. }
  1347. // Add another decimal to avoid rounding errors of float numbers. (#4573)
  1348. // Then use toFixed to handle rounding.
  1349. roundedNumber = (Math.abs(exponent[1] ? exponent[0] : number) +
  1350. Math.pow(10, -Math.max(decimals, origDec) - 1)).toFixed(decimals);
  1351. // A string containing the positive integer component of the number
  1352. strinteger = String(pInt(roundedNumber));
  1353. // Leftover after grouping into thousands. Can be 0, 1 or 2.
  1354. thousands = strinteger.length > 3 ? strinteger.length % 3 : 0;
  1355. // Language
  1356. decimalPoint = pick(decimalPoint, lang.decimalPoint);
  1357. thousandsSep = pick(thousandsSep, lang.thousandsSep);
  1358. // Start building the return
  1359. ret = number < 0 ? '-' : '';
  1360. // Add the leftover after grouping into thousands. For example, in the
  1361. // number 42 000 000, this line adds 42.
  1362. ret += thousands ? strinteger.substr(0, thousands) + thousandsSep : '';
  1363. if (+exponent[1] < 0 && !firstDecimals) {
  1364. ret = '0';
  1365. }
  1366. else {
  1367. // Add the remaining thousands groups, joined by the thousands separator
  1368. ret += strinteger
  1369. .substr(thousands)
  1370. .replace(/(\d{3})(?=\d)/g, '$1' + thousandsSep);
  1371. }
  1372. // Add the decimal point and the decimal component
  1373. if (decimals) {
  1374. // Get the decimal component
  1375. ret += decimalPoint + roundedNumber.slice(-decimals);
  1376. }
  1377. if (exponent[1] && +ret !== 0) {
  1378. ret += 'e' + exponent[1];
  1379. }
  1380. return ret;
  1381. }
  1382. /**
  1383. * Easing definition
  1384. *
  1385. * @private
  1386. * @function Math.easeInOutSine
  1387. *
  1388. * @param {number} pos
  1389. * Current position, ranging from 0 to 1.
  1390. *
  1391. * @return {number}
  1392. * Ease result
  1393. */
  1394. Math.easeInOutSine = function (pos) {
  1395. return -0.5 * (Math.cos(Math.PI * pos) - 1);
  1396. };
  1397. /**
  1398. * Returns the value of a property path on a given object.
  1399. *
  1400. * @private
  1401. * @function getNestedProperty
  1402. *
  1403. * @param {string} path
  1404. * Path to the property, for example `custom.myValue`.
  1405. *
  1406. * @param {unknown} obj
  1407. * Instance containing the property on the specific path.
  1408. *
  1409. * @return {unknown}
  1410. * The unknown property value.
  1411. */
  1412. function getNestedProperty(path, obj) {
  1413. if (!path) {
  1414. return obj;
  1415. }
  1416. var pathElements = path.split('.').reverse();
  1417. var subProperty = obj;
  1418. if (pathElements.length === 1) {
  1419. return subProperty[path];
  1420. }
  1421. var pathElement = pathElements.pop();
  1422. while (typeof pathElement !== 'undefined' &&
  1423. typeof subProperty !== 'undefined' &&
  1424. subProperty !== null) {
  1425. subProperty = subProperty[pathElement];
  1426. pathElement = pathElements.pop();
  1427. }
  1428. return subProperty;
  1429. }
  1430. /**
  1431. * Get the computed CSS value for given element and property, only for numerical
  1432. * properties. For width and height, the dimension of the inner box (excluding
  1433. * padding) is returned. Used for fitting the chart within the container.
  1434. *
  1435. * @function Highcharts.getStyle
  1436. *
  1437. * @param {Highcharts.HTMLDOMElement} el
  1438. * An HTML element.
  1439. *
  1440. * @param {string} prop
  1441. * The property name.
  1442. *
  1443. * @param {boolean} [toInt=true]
  1444. * Parse to integer.
  1445. *
  1446. * @return {number|string}
  1447. * The numeric value.
  1448. */
  1449. function getStyle(el, prop, toInt) {
  1450. var style;
  1451. // For width and height, return the actual inner pixel size (#4913)
  1452. if (prop === 'width') {
  1453. var offsetWidth = Math.min(el.offsetWidth, el.scrollWidth);
  1454. // In flex boxes, we need to use getBoundingClientRect and floor it,
  1455. // because scrollWidth doesn't support subpixel precision (#6427) ...
  1456. var boundingClientRectWidth = el.getBoundingClientRect &&
  1457. el.getBoundingClientRect().width;
  1458. // ...unless if the containing div or its parents are transform-scaled
  1459. // down, in which case the boundingClientRect can't be used as it is
  1460. // also scaled down (#9871, #10498).
  1461. if (boundingClientRectWidth < offsetWidth &&
  1462. boundingClientRectWidth >= offsetWidth - 1) {
  1463. offsetWidth = Math.floor(boundingClientRectWidth);
  1464. }
  1465. return Math.max(0, // #8377
  1466. (offsetWidth -
  1467. H.getStyle(el, 'padding-left') -
  1468. H.getStyle(el, 'padding-right')));
  1469. }
  1470. if (prop === 'height') {
  1471. return Math.max(0, // #8377
  1472. Math.min(el.offsetHeight, el.scrollHeight) -
  1473. H.getStyle(el, 'padding-top') -
  1474. H.getStyle(el, 'padding-bottom'));
  1475. }
  1476. if (!win.getComputedStyle) {
  1477. // SVG not supported, forgot to load oldie.js?
  1478. error(27, true);
  1479. }
  1480. // Otherwise, get the computed style
  1481. style = win.getComputedStyle(el, undefined); // eslint-disable-line no-undefined
  1482. if (style) {
  1483. style = style.getPropertyValue(prop);
  1484. if (pick(toInt, prop !== 'opacity')) {
  1485. style = pInt(style);
  1486. }
  1487. }
  1488. return style;
  1489. }
  1490. /**
  1491. * Search for an item in an array.
  1492. *
  1493. * @function Highcharts.inArray
  1494. *
  1495. * @deprecated
  1496. *
  1497. * @param {*} item
  1498. * The item to search for.
  1499. *
  1500. * @param {Array<*>} arr
  1501. * The array or node collection to search in.
  1502. *
  1503. * @param {number} [fromIndex=0]
  1504. * The index to start searching from.
  1505. *
  1506. * @return {number}
  1507. * The index within the array, or -1 if not found.
  1508. */
  1509. function inArray(item, arr, fromIndex) {
  1510. error(32, false, void 0, { 'Highcharts.inArray': 'use Array.indexOf' });
  1511. return arr.indexOf(item, fromIndex);
  1512. }
  1513. /* eslint-disable valid-jsdoc */
  1514. /**
  1515. * Return the value of the first element in the array that satisfies the
  1516. * provided testing function.
  1517. *
  1518. * @function Highcharts.find<T>
  1519. *
  1520. * @param {Array<T>} arr
  1521. * The array to test.
  1522. *
  1523. * @param {Function} callback
  1524. * The callback function. The function receives the item as the first
  1525. * argument. Return `true` if this item satisfies the condition.
  1526. *
  1527. * @return {T|undefined}
  1528. * The value of the element.
  1529. */
  1530. var find = Array.prototype.find ?
  1531. /* eslint-enable valid-jsdoc */
  1532. function (arr, callback) {
  1533. return arr.find(callback);
  1534. } :
  1535. // Legacy implementation. PhantomJS, IE <= 11 etc. #7223.
  1536. function (arr, callback) {
  1537. var i, length = arr.length;
  1538. for (i = 0; i < length; i++) {
  1539. if (callback(arr[i], i)) { // eslint-disable-line callback-return
  1540. return arr[i];
  1541. }
  1542. }
  1543. };
  1544. /**
  1545. * Returns an array of a given object's own properties.
  1546. *
  1547. * @function Highcharts.keys
  1548. * @deprecated
  1549. *
  1550. * @param {*} obj
  1551. * The object of which the properties are to be returned.
  1552. *
  1553. * @return {Array<string>}
  1554. * An array of strings that represents all the properties.
  1555. */
  1556. function keys(obj) {
  1557. error(32, false, void 0, { 'Highcharts.keys': 'use Object.keys' });
  1558. return Object.keys(obj);
  1559. }
  1560. /**
  1561. * Get the element's offset position, corrected for `overflow: auto`.
  1562. *
  1563. * @function Highcharts.offset
  1564. *
  1565. * @param {global.Element} el
  1566. * The DOM element.
  1567. *
  1568. * @return {Highcharts.OffsetObject}
  1569. * An object containing `left` and `top` properties for the position in
  1570. * the page.
  1571. */
  1572. function offset(el) {
  1573. var docElem = doc.documentElement, box = (el.parentElement || el.parentNode) ?
  1574. el.getBoundingClientRect() :
  1575. { top: 0, left: 0, width: 0, height: 0 };
  1576. return {
  1577. top: box.top + (win.pageYOffset || docElem.scrollTop) -
  1578. (docElem.clientTop || 0),
  1579. left: box.left + (win.pageXOffset || docElem.scrollLeft) -
  1580. (docElem.clientLeft || 0),
  1581. width: box.width,
  1582. height: box.height
  1583. };
  1584. }
  1585. /* eslint-disable valid-jsdoc */
  1586. /**
  1587. * Iterate over object key pairs in an object.
  1588. *
  1589. * @function Highcharts.objectEach<T>
  1590. *
  1591. * @param {*} obj
  1592. * The object to iterate over.
  1593. *
  1594. * @param {Highcharts.ObjectEachCallbackFunction<T>} fn
  1595. * The iterator callback. It passes three arguments:
  1596. * * value - The property value.
  1597. * * key - The property key.
  1598. * * obj - The object that objectEach is being applied to.
  1599. *
  1600. * @param {T} [ctx]
  1601. * The context.
  1602. *
  1603. * @return {void}
  1604. */
  1605. function objectEach(obj, fn, ctx) {
  1606. /* eslint-enable valid-jsdoc */
  1607. for (var key in obj) {
  1608. if (Object.hasOwnProperty.call(obj, key)) {
  1609. fn.call(ctx || obj[key], obj[key], key, obj);
  1610. }
  1611. }
  1612. }
  1613. /**
  1614. * Iterate over an array.
  1615. *
  1616. * @deprecated
  1617. * @function Highcharts.each
  1618. *
  1619. * @param {Array<*>} arr
  1620. * The array to iterate over.
  1621. *
  1622. * @param {Function} fn
  1623. * The iterator callback. It passes three arguments:
  1624. * - `item`: The array item.
  1625. * - `index`: The item's index in the array.
  1626. * - `arr`: The array that each is being applied to.
  1627. *
  1628. * @param {*} [ctx]
  1629. * The context.
  1630. *
  1631. * @return {void}
  1632. */
  1633. /**
  1634. * Filter an array by a callback.
  1635. *
  1636. * @deprecated
  1637. * @function Highcharts.grep
  1638. *
  1639. * @param {Array<*>} arr
  1640. * The array to filter.
  1641. *
  1642. * @param {Function} callback
  1643. * The callback function. The function receives the item as the first
  1644. * argument. Return `true` if the item is to be preserved.
  1645. *
  1646. * @return {Array<*>}
  1647. * A new, filtered array.
  1648. */
  1649. /**
  1650. * Map an array by a callback.
  1651. *
  1652. * @deprecated
  1653. * @function Highcharts.map
  1654. *
  1655. * @param {Array<*>} arr
  1656. * The array to map.
  1657. *
  1658. * @param {Function} fn
  1659. * The callback function. Return the new value for the new array.
  1660. *
  1661. * @return {Array<*>}
  1662. * A new array item with modified items.
  1663. */
  1664. /**
  1665. * Reduce an array to a single value.
  1666. *
  1667. * @deprecated
  1668. * @function Highcharts.reduce
  1669. *
  1670. * @param {Array<*>} arr
  1671. * The array to reduce.
  1672. *
  1673. * @param {Function} fn
  1674. * The callback function. Return the reduced value. Receives 4
  1675. * arguments: Accumulated/reduced value, current value, current array
  1676. * index, and the array.
  1677. *
  1678. * @param {*} initialValue
  1679. * The initial value of the accumulator.
  1680. *
  1681. * @return {*}
  1682. * The reduced value.
  1683. */
  1684. /**
  1685. * Test whether at least one element in the array passes the test implemented by
  1686. * the provided function.
  1687. *
  1688. * @deprecated
  1689. * @function Highcharts.some
  1690. *
  1691. * @param {Array<*>} arr
  1692. * The array to test
  1693. *
  1694. * @param {Function} fn
  1695. * The function to run on each item. Return truty to pass the test.
  1696. * Receives arguments `currentValue`, `index` and `array`.
  1697. *
  1698. * @param {*} ctx
  1699. * The context.
  1700. *
  1701. * @return {boolean}
  1702. */
  1703. objectEach({
  1704. map: 'map',
  1705. each: 'forEach',
  1706. grep: 'filter',
  1707. reduce: 'reduce',
  1708. some: 'some'
  1709. }, function (val, key) {
  1710. H[key] = function (arr) {
  1711. var _a;
  1712. error(32, false, void 0, (_a = {}, _a["Highcharts." + key] = "use Array." + val, _a));
  1713. return Array.prototype[val].apply(arr, [].slice.call(arguments, 1));
  1714. };
  1715. });
  1716. /* eslint-disable valid-jsdoc */
  1717. /**
  1718. * Add an event listener.
  1719. *
  1720. * @function Highcharts.addEvent<T>
  1721. *
  1722. * @param {Highcharts.Class<T>|T} el
  1723. * The element or object to add a listener to. It can be a
  1724. * {@link HTMLDOMElement}, an {@link SVGElement} or any other object.
  1725. *
  1726. * @param {string} type
  1727. * The event type.
  1728. *
  1729. * @param {Highcharts.EventCallbackFunction<T>|Function} fn
  1730. * The function callback to execute when the event is fired.
  1731. *
  1732. * @param {Highcharts.EventOptionsObject} [options]
  1733. * Options for adding the event.
  1734. *
  1735. * @return {Function}
  1736. * A callback function to remove the added event.
  1737. */
  1738. function addEvent(el, type, fn, options) {
  1739. /* eslint-enable valid-jsdoc */
  1740. if (options === void 0) { options = {}; }
  1741. // Add hcEvents to either the prototype (in case we're running addEvent on a
  1742. // class) or the instance. If hasOwnProperty('hcEvents') is false, it is
  1743. // inherited down the prototype chain, in which case we need to set the
  1744. // property on this instance (which may itself be a prototype).
  1745. var owner = typeof el === 'function' && el.prototype || el;
  1746. if (!Object.hasOwnProperty.call(owner, 'hcEvents')) {
  1747. owner.hcEvents = {};
  1748. }
  1749. var events = owner.hcEvents;
  1750. // Allow click events added to points, otherwise they will be prevented by
  1751. // the TouchPointer.pinch function after a pinch zoom operation (#7091).
  1752. if (H.Point && // without H a dependency loop occurs
  1753. el instanceof H.Point &&
  1754. el.series &&
  1755. el.series.chart) {
  1756. el.series.chart.runTrackerClick = true;
  1757. }
  1758. // Handle DOM events
  1759. // If the browser supports passive events, add it to improve performance
  1760. // on touch events (#11353).
  1761. var addEventListener = (el.addEventListener || H.addEventListenerPolyfill);
  1762. if (addEventListener) {
  1763. addEventListener.call(el, type, fn, H.supportsPassiveEvents ? {
  1764. passive: options.passive === void 0 ?
  1765. type.indexOf('touch') !== -1 : options.passive,
  1766. capture: false
  1767. } : false);
  1768. }
  1769. if (!events[type]) {
  1770. events[type] = [];
  1771. }
  1772. var eventObject = {
  1773. fn: fn,
  1774. order: typeof options.order === 'number' ? options.order : Infinity
  1775. };
  1776. events[type].push(eventObject);
  1777. // Order the calls
  1778. events[type].sort(function (a, b) { return a.order - b.order; });
  1779. // Return a function that can be called to remove this event.
  1780. return function () {
  1781. removeEvent(el, type, fn);
  1782. };
  1783. }
  1784. /* eslint-disable valid-jsdoc */
  1785. /**
  1786. * Remove an event that was added with {@link Highcharts#addEvent}.
  1787. *
  1788. * @function Highcharts.removeEvent<T>
  1789. *
  1790. * @param {Highcharts.Class<T>|T} el
  1791. * The element to remove events on.
  1792. *
  1793. * @param {string} [type]
  1794. * The type of events to remove. If undefined, all events are removed
  1795. * from the element.
  1796. *
  1797. * @param {Highcharts.EventCallbackFunction<T>} [fn]
  1798. * The specific callback to remove. If undefined, all events that match
  1799. * the element and optionally the type are removed.
  1800. *
  1801. * @return {void}
  1802. */
  1803. function removeEvent(el, type, fn) {
  1804. /* eslint-enable valid-jsdoc */
  1805. /**
  1806. * @private
  1807. * @param {string} type - event type
  1808. * @param {Highcharts.EventCallbackFunction<T>} fn - callback
  1809. * @return {void}
  1810. */
  1811. function removeOneEvent(type, fn) {
  1812. var removeEventListener = (el.removeEventListener || H.removeEventListenerPolyfill);
  1813. if (removeEventListener) {
  1814. removeEventListener.call(el, type, fn, false);
  1815. }
  1816. }
  1817. /**
  1818. * @private
  1819. * @param {any} eventCollection - collection
  1820. * @return {void}
  1821. */
  1822. function removeAllEvents(eventCollection) {
  1823. var types, len;
  1824. if (!el.nodeName) {
  1825. return; // break on non-DOM events
  1826. }
  1827. if (type) {
  1828. types = {};
  1829. types[type] = true;
  1830. }
  1831. else {
  1832. types = eventCollection;
  1833. }
  1834. objectEach(types, function (_val, n) {
  1835. if (eventCollection[n]) {
  1836. len = eventCollection[n].length;
  1837. while (len--) {
  1838. removeOneEvent(n, eventCollection[n][len].fn);
  1839. }
  1840. }
  1841. });
  1842. }
  1843. var owner = typeof el === 'function' && el.prototype || el;
  1844. if (Object.hasOwnProperty.call(owner, 'hcEvents')) {
  1845. var events = owner.hcEvents;
  1846. if (type) {
  1847. var typeEvents = (events[type] || []);
  1848. if (fn) {
  1849. events[type] = typeEvents.filter(function (obj) {
  1850. return fn !== obj.fn;
  1851. });
  1852. removeOneEvent(type, fn);
  1853. }
  1854. else {
  1855. removeAllEvents(events);
  1856. events[type] = [];
  1857. }
  1858. }
  1859. else {
  1860. removeAllEvents(events);
  1861. delete owner.hcEvents;
  1862. }
  1863. }
  1864. }
  1865. /* eslint-disable valid-jsdoc */
  1866. /**
  1867. * Fire an event that was registered with {@link Highcharts#addEvent}.
  1868. *
  1869. * @function Highcharts.fireEvent<T>
  1870. *
  1871. * @param {T} el
  1872. * The object to fire the event on. It can be a {@link HTMLDOMElement},
  1873. * an {@link SVGElement} or any other object.
  1874. *
  1875. * @param {string} type
  1876. * The type of event.
  1877. *
  1878. * @param {Highcharts.Dictionary<*>|Event} [eventArguments]
  1879. * Custom event arguments that are passed on as an argument to the event
  1880. * handler.
  1881. *
  1882. * @param {Highcharts.EventCallbackFunction<T>|Function} [defaultFunction]
  1883. * The default function to execute if the other listeners haven't
  1884. * returned false.
  1885. *
  1886. * @return {void}
  1887. */
  1888. function fireEvent(el, type, eventArguments, defaultFunction) {
  1889. /* eslint-enable valid-jsdoc */
  1890. var e, i;
  1891. eventArguments = eventArguments || {};
  1892. if (doc.createEvent &&
  1893. (el.dispatchEvent || el.fireEvent)) {
  1894. e = doc.createEvent('Events');
  1895. e.initEvent(type, true, true);
  1896. extend(e, eventArguments);
  1897. if (el.dispatchEvent) {
  1898. el.dispatchEvent(e);
  1899. }
  1900. else {
  1901. el.fireEvent(type, e);
  1902. }
  1903. }
  1904. else if (el.hcEvents) {
  1905. if (!eventArguments.target) {
  1906. // We're running a custom event
  1907. extend(eventArguments, {
  1908. // Attach a simple preventDefault function to skip
  1909. // default handler if called. The built-in
  1910. // defaultPrevented property is not overwritable (#5112)
  1911. preventDefault: function () {
  1912. eventArguments.defaultPrevented = true;
  1913. },
  1914. // Setting target to native events fails with clicking
  1915. // the zoom-out button in Chrome.
  1916. target: el,
  1917. // If the type is not set, we're running a custom event
  1918. // (#2297). If it is set, we're running a browser event,
  1919. // and setting it will cause en error in IE8 (#2465).
  1920. type: type
  1921. });
  1922. }
  1923. var events = [];
  1924. var object = el;
  1925. var multilevel = false;
  1926. // Recurse up the inheritance chain and collect hcEvents set as own
  1927. // objects on the prototypes.
  1928. while (object.hcEvents) {
  1929. if (Object.hasOwnProperty.call(object, 'hcEvents') &&
  1930. object.hcEvents[type]) {
  1931. if (events.length) {
  1932. multilevel = true;
  1933. }
  1934. events.unshift.apply(events, object.hcEvents[type]);
  1935. }
  1936. object = Object.getPrototypeOf(object);
  1937. }
  1938. // For performance reasons, only sort the event handlers in case we are
  1939. // dealing with multiple levels in the prototype chain. Otherwise, the
  1940. // events are already sorted in the addEvent function.
  1941. if (multilevel) {
  1942. // Order the calls
  1943. events.sort(function (a, b) { return a.order - b.order; });
  1944. }
  1945. // Call the collected event handlers
  1946. events.forEach(function (obj) {
  1947. // If the event handler returns false, prevent the default handler
  1948. // from executing
  1949. if (obj.fn.call(el, eventArguments) === false) {
  1950. eventArguments.preventDefault();
  1951. }
  1952. });
  1953. }
  1954. // Run the default if not prevented
  1955. if (defaultFunction && !eventArguments.defaultPrevented) {
  1956. defaultFunction.call(el, eventArguments);
  1957. }
  1958. }
  1959. var serialMode;
  1960. /**
  1961. * Get a unique key for using in internal element id's and pointers. The key is
  1962. * composed of a random hash specific to this Highcharts instance, and a
  1963. * counter.
  1964. *
  1965. * @example
  1966. * var id = uniqueKey(); // => 'highcharts-x45f6hp-0'
  1967. *
  1968. * @function Highcharts.uniqueKey
  1969. *
  1970. * @return {string}
  1971. * A unique key.
  1972. */
  1973. var uniqueKey = (function () {
  1974. var hash = Math.random().toString(36).substring(2, 9) + '-';
  1975. var id = 0;
  1976. return function () {
  1977. return 'highcharts-' + (serialMode ? '' : hash) + id++;
  1978. };
  1979. }());
  1980. /**
  1981. * Activates a serial mode for element IDs provided by
  1982. * {@link Highcharts.uniqueKey}. This mode can be used in automated tests, where
  1983. * a simple comparison of two rendered SVG graphics is needed.
  1984. *
  1985. * **Note:** This is only for testing purposes and will break functionality in
  1986. * webpages with multiple charts.
  1987. *
  1988. * @example
  1989. * if (
  1990. * process &&
  1991. * process.env.NODE_ENV === 'development'
  1992. * ) {
  1993. * Highcharts.useSerialIds(true);
  1994. * }
  1995. *
  1996. * @function Highcharts.useSerialIds
  1997. *
  1998. * @param {boolean} [mode]
  1999. * Changes the state of serial mode.
  2000. *
  2001. * @return {boolean|undefined}
  2002. * State of the serial mode.
  2003. */
  2004. function useSerialIds(mode) {
  2005. return (serialMode = pick(mode, serialMode));
  2006. }
  2007. function isFunction(obj) {
  2008. return typeof obj === 'function';
  2009. }
  2010. /**
  2011. * Get the updated default options. Until 3.0.7, merely exposing defaultOptions
  2012. * for outside modules wasn't enough because the setOptions method created a new
  2013. * object.
  2014. *
  2015. * @function Highcharts.getOptions
  2016. *
  2017. * @return {Highcharts.Options}
  2018. */
  2019. var getOptions = H.getOptions = function () {
  2020. return H.defaultOptions;
  2021. };
  2022. /**
  2023. * Merge the default options with custom options and return the new options
  2024. * structure. Commonly used for defining reusable templates.
  2025. *
  2026. * @sample highcharts/global/useutc-false Setting a global option
  2027. * @sample highcharts/members/setoptions Applying a global theme
  2028. *
  2029. * @function Highcharts.setOptions
  2030. *
  2031. * @param {Highcharts.Options} options
  2032. * The new custom chart options.
  2033. *
  2034. * @return {Highcharts.Options}
  2035. * Updated options.
  2036. */
  2037. var setOptions = H.setOptions = function (options) {
  2038. // Copy in the default options
  2039. H.defaultOptions = merge(true, H.defaultOptions, options);
  2040. // Update the time object
  2041. if (options.time || options.global) {
  2042. H.time.update(merge(H.defaultOptions.global, H.defaultOptions.time, options.global, options.time));
  2043. }
  2044. return H.defaultOptions;
  2045. };
  2046. // Register Highcharts as a plugin in jQuery
  2047. if (win.jQuery) {
  2048. /**
  2049. * Highcharts-extended JQuery.
  2050. *
  2051. * @external JQuery
  2052. */
  2053. /**
  2054. * Helper function to return the chart of the current JQuery selector
  2055. * element.
  2056. *
  2057. * @function external:JQuery#highcharts
  2058. *
  2059. * @return {Highcharts.Chart}
  2060. * The chart that is linked to the JQuery selector element.
  2061. */ /**
  2062. * Factory function to create a chart in the current JQuery selector
  2063. * element.
  2064. *
  2065. * @function external:JQuery#highcharts
  2066. *
  2067. * @param {'Chart'|'Map'|'StockChart'|string} [className]
  2068. * Name of the factory class in the Highcharts namespace.
  2069. *
  2070. * @param {Highcharts.Options} [options]
  2071. * The chart options structure.
  2072. *
  2073. * @param {Highcharts.ChartCallbackFunction} [callback]
  2074. * Function to run when the chart has loaded and and all external
  2075. * images are loaded. Defining a
  2076. * [chart.events.load](https://api.highcharts.com/highcharts/chart.events.load)
  2077. * handler is equivalent.
  2078. *
  2079. * @return {JQuery}
  2080. * The current JQuery selector.
  2081. */
  2082. win.jQuery.fn.highcharts = function () {
  2083. var args = [].slice.call(arguments);
  2084. if (this[0]) { // this[0] is the renderTo div
  2085. // Create the chart
  2086. if (args[0]) {
  2087. new H[ // eslint-disable-line computed-property-spacing, no-new
  2088. // Constructor defaults to Chart
  2089. isString(args[0]) ? args.shift() : 'Chart'](this[0], args[0], args[1]);
  2090. return this;
  2091. }
  2092. // When called without parameters or with the return argument,
  2093. // return an existing chart
  2094. return charts[attr(this[0], 'data-highcharts-chart')];
  2095. }
  2096. };
  2097. }
  2098. // TODO use named exports when supported.
  2099. var utilitiesModule = {
  2100. addEvent: addEvent,
  2101. arrayMax: arrayMax,
  2102. arrayMin: arrayMin,
  2103. attr: attr,
  2104. clamp: clamp,
  2105. cleanRecursively: cleanRecursively,
  2106. clearTimeout: internalClearTimeout,
  2107. correctFloat: correctFloat,
  2108. createElement: createElement,
  2109. css: css,
  2110. defined: defined,
  2111. destroyObjectProperties: destroyObjectProperties,
  2112. discardElement: discardElement,
  2113. erase: erase,
  2114. error: error,
  2115. extend: extend,
  2116. extendClass: extendClass,
  2117. find: find,
  2118. fireEvent: fireEvent,
  2119. format: format,
  2120. getMagnitude: getMagnitude,
  2121. getNestedProperty: getNestedProperty,
  2122. getOptions: getOptions,
  2123. getStyle: getStyle,
  2124. inArray: inArray,
  2125. isArray: isArray,
  2126. isClass: isClass,
  2127. isDOMElement: isDOMElement,
  2128. isFunction: isFunction,
  2129. isNumber: isNumber,
  2130. isObject: isObject,
  2131. isString: isString,
  2132. keys: keys,
  2133. merge: merge,
  2134. normalizeTickInterval: normalizeTickInterval,
  2135. numberFormat: numberFormat,
  2136. objectEach: objectEach,
  2137. offset: offset,
  2138. pad: pad,
  2139. pick: pick,
  2140. pInt: pInt,
  2141. relativeLength: relativeLength,
  2142. removeEvent: removeEvent,
  2143. setOptions: setOptions,
  2144. splat: splat,
  2145. stableSort: stableSort,
  2146. syncTimeout: syncTimeout,
  2147. timeUnits: timeUnits,
  2148. uniqueKey: uniqueKey,
  2149. useSerialIds: useSerialIds,
  2150. wrap: wrap
  2151. };
  2152. export default utilitiesModule;